parallaxParallax
Move foreground and background at restrained relative speeds to create depth.
Preview
Layers respond to the same scroll input at different displacement rates, creating apparent depth.
FullReduced
FullReduced
Preview
Scroll
Parallax
Continue
Implement Parallax: Move foreground and background at restrained relative speeds to create depth. Use Distance 48px, Speed ratio 35%, Axis y. Drive it from viewport entry or scroll progress. Use semantic HTML, scope CSS to .motion-demo--parallax. Provide equivalent low-motion behavior for prefers-reduced-motion and .force-reduced-motion.
<div class="motion-demo motion-demo--parallax" data-motion="parallax" aria-label="Parallax demo">
<div class="motion-scroll-track"><span>Scroll</span><article class="motion-surface">
<strong>Parallax</strong>
<span class="motion-line"></span>
<span class="motion-line"></span>
</article><span>Continue</span></div>
</div>.motion-demo.motion-demo--parallax {
box-sizing: border-box;
position: relative;
display: grid;
place-items: center;
width: min(100%, 34rem);
min-height: 15rem;
padding: 2rem;
overflow: hidden;
color: #18181b;
background: #fafafa;
border: 1px solid #e4e4e7;
border-radius: 16px;
isolation: isolate;
}
.motion-demo.motion-demo--parallax *, .motion-demo.motion-demo--parallax *::before, .motion-demo.motion-demo--parallax *::after {
box-sizing: border-box;
}
.motion-demo.motion-demo--parallax .motion-surface {
position: relative;
display: grid;
gap: 0.65rem;
width: min(100%, 18rem);
padding: 1.25rem;
background: #ffffff;
border: 1px solid #e4e4e7;
border-radius: 16px;
box-shadow: none;
}
.motion-demo.motion-demo--parallax .motion-surface strong { font-weight: 500; }
.motion-demo.motion-demo--parallax .motion-line {
display: block;
width: 100%;
height: 0.5rem;
background: #e4e4e7;
border-radius: 999px;
}
.motion-demo.motion-demo--parallax .motion-line:last-child { width: 62%; }
.motion-demo.motion-demo--parallax .motion-button {
position: relative;
min-height: 2.75rem;
padding: 0.75rem 1.1rem;
color: white;
font: inherit;
font-weight: 700;
background: #18181b;
border: 0;
border-radius: 999px;
cursor: pointer;
}
.motion-demo.motion-demo--parallax .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
.motion-demo.motion-demo--parallax .motion-action-row {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 0.85rem;
}
.motion-demo.motion-demo--parallax .motion-replay-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--parallax .motion-pausable-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--parallax button.motion-surface {
color: inherit;
font: inherit;
text-align: start;
cursor: pointer;
}
.motion-demo.motion-demo--parallax .motion-replay-button,
.motion-demo.motion-demo--parallax .motion-undo-button,
.motion-demo.motion-demo--parallax .motion-dismiss-button,
.motion-demo.motion-demo--parallax .motion-pause-button {
min-height: 2.75rem;
padding: 0.65rem 0.9rem;
color: #18181b;
font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
background: #ffffff;
border: 1px solid #d4d4d8;
border-radius: 8px;
cursor: pointer;
}
.motion-demo.motion-demo--parallax .motion-replay-button:focus-visible,
.motion-demo.motion-demo--parallax .motion-undo-button:focus-visible,
.motion-demo.motion-demo--parallax .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--parallax .motion-pause-button:focus-visible,
.motion-demo.motion-demo--parallax [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--parallax [data-swipe-target]:focus-visible {
outline: 3px solid rgb(37 99 235 / 32%);
outline-offset: 3px;
}
.motion-demo.motion-demo--parallax .motion-status {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.motion-demo.motion-demo--parallax .motion-ripple-ink {
position: absolute;
width: 12px;
height: 12px;
pointer-events: none;
background: rgb(255 255 255 / 72%);
border-radius: 50%;
transform: translate(-50%, -50%) scale(0.95);
opacity: 0;
}
.motion-demo.motion-demo--parallax .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--parallax .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 16px; }
.motion-demo.motion-demo--parallax .motion-state--to { background: #18181b; color: white; }
.motion-demo.motion-demo--parallax .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--parallax .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--parallax .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--parallax svg { width: min(100%, 20rem); height: auto; }
.motion-demo.motion-demo--parallax { max-height: 15rem; overflow-x: hidden; overflow-y: auto; place-items: start center; }
.motion-demo.motion-demo--parallax .motion-scroll-track { display: grid; place-items: center; gap: 10rem; width: 100%; min-height: 48rem; padding-block: 5rem; }
.motion-demo.motion-demo--parallax .motion-surface { animation: motion-parallax linear both; animation-timeline: scroll(nearest); animation-range: 10% 80%; }
@keyframes motion-parallax { from { transform: translateY(17px); } to { transform: none; } }
@supports not (animation-timeline: scroll()) { .motion-demo.motion-demo--parallax .motion-surface { animation: motion-parallax 700ms linear both; } }
@keyframes motion-parallax-reduced-fade {
from { opacity: 0.84; }
to { opacity: 1; }
}
.force-reduced-motion .motion-demo.motion-demo--parallax {
animation: motion-parallax-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.force-reduced-motion .motion-demo.motion-demo--parallax *,
.force-reduced-motion .motion-demo.motion-demo--parallax *::before,
.force-reduced-motion .motion-demo.motion-demo--parallax *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.force-reduced-motion .motion-demo.motion-demo--parallax .motion-button,
.force-reduced-motion .motion-demo.motion-demo--parallax [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--parallax [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--parallax [data-spring-target] {
transform: none !important;
}
.force-reduced-motion .motion-demo.motion-demo--parallax .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--parallax .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--parallax .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
.motion-demo.motion-demo--parallax {
animation: motion-parallax-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.motion-demo.motion-demo--parallax *, .motion-demo.motion-demo--parallax *::before, .motion-demo.motion-demo--parallax *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.motion-demo.motion-demo--parallax .motion-button,
.motion-demo.motion-demo--parallax [data-reorder-item],
.motion-demo.motion-demo--parallax [data-swipe-target],
.motion-demo.motion-demo--parallax [data-spring-target] {
transform: none !important;
}
.motion-demo.motion-demo--parallax .motion-path { stroke-dashoffset: 0 !important; }
.motion-demo.motion-demo--parallax .motion-word--from { opacity: 0 !important; visibility: hidden; }
.motion-demo.motion-demo--parallax .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}Learn more
Terms and distinctions
parallaxParallax
视差English definition
Layers respond to the same scroll input at different displacement rates, creating apparent depth.
Chinese translation
滚动时背景与前景以不同速度移动,从而营造纵深感。
Before implementation
- Purpose
- Create depth with restrained foreground-background speed differences while keeping primary content stable.
- Frequency
- Use sparingly in hero and showcase areas; repetition across long pages adds visual load.
- Trigger
- Drive from page scroll, binding travel to the container's visible range.
- Enter / exit
- Maintain continuous position around viewport entry and avoid threshold-based jumps.
- Interruptibility
- Follow current scroll position directly when direction changes, with no catch-up animation.
- Gesture and keyboard
- Never capture scroll gestures, and set pointer-event rules so background layers do not block content.
- Reduced-motion strategy
- Fix every layer at its clearest informational position and remove differential movement.
Accessibility
Reduced motion
Fix every layer at its clearest informational position and remove differential movement.
Parameter reference
| Parameter | Range / options | Default | Purpose |
|---|---|---|---|
distance | 0px–160px | 48px | Controls how far the element travels. |
speed | 10%–80% | 35% | Adjusts speed ratio. |
axis | Vertical / Horizontal | Vertical | Selects axis. |
Pre-delivery review
- Keep text near the page's scroll speed.
- Test mobile browser chrome changes for exaggerated travel.