scroll
Tags that turn the scrollbar into a timeline. Layers drift at their own depth, and a pinned stage plays a scene as you scroll through it. Scroll back up and everything runs in reverse.
Same scroll, different speeds.
Show the codeHide the code
<script type="module">
import "motion-components/motion-parallax";
</script>
<div class="depth-stage">
<motion-parallax class="orb orb-yellow" depth="-2.2"></motion-parallax>
<motion-parallax class="orb orb-blue" depth="1.4"></motion-parallax>
<motion-parallax class="orb orb-ring" depth="3.2"></motion-parallax>
<div class="lanes">
<motion-parallax axis="x" depth="3" class="lane lane-near">
<span>near near near near near near</span>
</motion-parallax>
<motion-parallax axis="x" depth="-1.6" class="lane lane-mid">
<span>middle middle middle middle middle middle</span>
</motion-parallax>
<motion-parallax axis="x" depth="0.6" class="lane lane-far">
<span>far away far away far away far away far away far away</span>
</motion-parallax>
</div>
</div>
<style>
.depth-stage { position: relative; height: 70vh; }
.orb { position: absolute; display: block; border-radius: 50%; }
.orb-yellow { width: 22vw; aspect-ratio: 1; top: 4%; right: 6%; background: #facc15; }
.orb-blue { width: 14vw; aspect-ratio: 1; bottom: 6%; left: 4%; background: #60a5fa; }
.orb-ring { width: 26vw; aspect-ratio: 1; top: 30%; left: 34%; border: 2px solid #2e2e3e; }
.lanes {
position: absolute; inset: 0; overflow: hidden;
display: flex; flex-direction: column; justify-content: center; gap: 2vh;
}
.lane { display: block; white-space: pre; line-height: 1; margin-left: -30vw; }
.lane-near { font-size: 14vw; font-weight: 800; }
.lane-mid { font-size: 8vw; font-weight: 300; opacity: 0.8; }
.lane-far { font-size: 4vw; font-weight: 600; color: #8888a8; }
</style>Now keep scrolling. The stage stays put while the scene plays.
Scroll back up to take it apart.
Show the codeHide the code
<script type="module">
import "motion-components/motion-scene";
</script>
<motion-scene height="420vh" class="scene">
<div class="ring ring-1" data-from='{"scale":0.2,"opacity":0}' data-to='{"scale":2.6,"opacity":0.9}' data-start="0" data-end="0.7"></div>
<div class="ring ring-2" data-from='{"scale":0.1,"opacity":0}' data-to='{"scale":1.8,"opacity":0.8}' data-start="0.1" data-end="0.8"></div>
<div class="ring ring-3" data-from='{"scale":0.05,"opacity":0}' data-to='{"scale":1.1,"opacity":1}' data-start="0.2" data-end="0.9"></div>
<div class="word" data-from='{"scale":1,"opacity":1}' data-to='{"scale":9,"opacity":0}' data-start="0.62" data-end="0.92" aria-label="scroll">
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"-38vw","y":"-30vh","rotate":"-40deg","scale":2.4}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.04" data-end="0.36">s</span>
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"24vw","y":"-42vh","rotate":"30deg","scale":0.4}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.09" data-end="0.39999999999999997">c</span>
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"-18vw","y":"36vh","rotate":"70deg","scale":1.8}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.14" data-end="0.44">r</span>
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"40vw","y":"28vh","rotate":"-25deg","scale":0.5}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.19000000000000003" data-end="0.48">o</span>
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"-44vw","y":"8vh","rotate":"15deg","scale":3}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.24000000000000002" data-end="0.52">l</span>
<span class="letter" aria-hidden="true" data-from='{"opacity":0,"x":"34vw","y":"-6vh","rotate":"-60deg","scale":0.3}' data-to='{"opacity":1,"x":"0vw","y":"0vh","rotate":"0deg","scale":1}' data-start="0.29" data-end="0.56">l</span>
</div>
<p class="scene-end" data-from='{"opacity":0,"y":"30px"}' data-to='{"opacity":1,"y":"0px"}' data-start="0.86" data-end="1">
Scroll back up to take it apart.
</p>
</motion-scene>
<style>
.scene { display: block; position: relative; }
.ring {
position: absolute; top: 50%; left: 50%;
width: min(70vw, 70vh); aspect-ratio: 1;
margin: calc(min(70vw, 70vh) / -2) 0 0 calc(min(70vw, 70vh) / -2);
border-radius: 50%; pointer-events: none;
}
.ring-1 { border: 2px solid #2e2e3e; }
.ring-2 { border: 2px solid #60a5fa; }
.ring-3 { border: 3px solid #facc15; }
.word {
position: relative; display: flex;
font-size: 25vw; font-weight: 800; line-height: 1; color: #facc15;
}
.letter { display: inline-block; }
.scene-end {
position: absolute; left: 0; right: 0; bottom: 14vh; margin: 0;
text-align: center; font-size: 2rem; font-weight: 600;
}
</style>Go deeper
Two longer pages take each tag further: a full parallax showcase with speed spectra and depth planes, and three pinned scenes built from data attributes.