Split-flap board
CSS + JSA departure board: each character is four half-height leaves, and a change drops the old top half and lands the new bottom half. JS only swaps the letters and restarts the CSS animation.
One word stacked twenty times along the Z axis. Laid on a tilted floor, the copies merge into a solid extrusion under a gradient front.
Your edited version
translateZ(calc(var(--i) * -1.2px)). Seen at an angle the copies merge into a solid extrusion.rotateX(54deg) rotateZ(-32deg) lays the whole stack on an isometric-looking floor: tip it back, then turn it on the floor.--i grows (hsl(... calc(46% - var(--i) * 1.3%))) — a cheap ambient shadow down the "sides" with no lighting math.background-clip: text; the last, deepest copy is blurred into a floor shadow instead.alternate + ease-in-out makes the sway loop seamless: the way back is the mirror image of the way there.translateZ(calc(var(--i) * -1.2px))rotateX + rotateZ floorlightness from --ibackground-clip: text<div class="scene">
<div class="depth">
<span style="--i:0">Depth</span>
<span aria-hidden="true" style="--i:1">Depth</span>
<span aria-hidden="true" style="--i:2">Depth</span>
<span aria-hidden="true" style="--i:3">Depth</span>
<span aria-hidden="true" style="--i:4">Depth</span>
<span aria-hidden="true" style="--i:5">Depth</span>
<span aria-hidden="true" style="--i:6">Depth</span>
<span aria-hidden="true" style="--i:7">Depth</span>
<span aria-hidden="true" style="--i:8">Depth</span>
<span aria-hidden="true" style="--i:9">Depth</span>
<span aria-hidden="true" style="--i:10">Depth</span>
<span aria-hidden="true" style="--i:11">Depth</span>
<span aria-hidden="true" style="--i:12">Depth</span>
<span aria-hidden="true" style="--i:13">Depth</span>
<span aria-hidden="true" style="--i:14">Depth</span>
<span aria-hidden="true" style="--i:15">Depth</span>
<span aria-hidden="true" style="--i:16">Depth</span>
<span aria-hidden="true" style="--i:17">Depth</span>
<span aria-hidden="true" style="--i:18">Depth</span>
<span aria-hidden="true" style="--i:19">Depth</span>
<span aria-hidden="true" style="--i:20">Depth</span>
</div>
</div>
.scene {
perspective: 800px;
}
.depth {
position: relative;
transform-style: preserve-3d;
transform: rotateX(54deg) rotateZ(-32deg);
animation: sway 7s ease-in-out infinite alternate;
font-size: 50px;
font-weight: 900;
line-height: 1;
letter-spacing: 0.02em;
text-transform: uppercase;
user-select: none;
}
.depth span {
position: absolute;
inset: 0;
/* 1.2px per step: at this tilt that is about one screen pixel, so no gaps show */
transform: translateZ(calc(var(--i) * -1.2px));
color: hsl(252 62% calc(46% - var(--i) * 1.3%));
}
/* the front copy gives the element its size and carries the gradient */
.depth span:first-child {
position: relative;
display: block;
background: linear-gradient(100deg, #2ee6d6, #8b6cff 45%, #ff4d9d);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
/* the last copy is the soft shadow on the floor: static, so the blur costs nothing per frame */
.depth span:last-child {
color: rgb(0 0 0 / 0.55);
text-shadow: 0 0 10px rgb(0 0 0 / 0.6);
transform: translateZ(-25px) translate(-5px, 7px);
}
@keyframes sway {
from { transform: rotateX(56deg) rotateZ(-40deg); }
to { transform: rotateX(48deg) rotateZ(-22deg); }
}
// Block text: the same word 20 times, each copy one step further down the Z axis. Seen at an
// angle the copies merge into a solid extrusion. --i is the copy's index (0 = the lit front).
.d-shadowtext {
position: relative;
transform-style: preserve-3d;
// Lay the word on an isometric-looking floor: tip it back, then turn it on the floor.
transform: rotateX(54deg) rotateZ(-32deg);
animation: d-shadowtext-sway 7s ease-in-out infinite alternate;
font-size: 50px;
font-weight: 900;
line-height: 1;
letter-spacing: 0.02em;
text-transform: uppercase;
user-select: none;
span {
position: absolute;
inset: 0;
// 1.2px per step: at this tilt that is about one screen pixel, so no gaps show.
transform: translateZ(calc(var(--i) * -1.2px));
// deeper copies get darker: a cheap ambient shadow down the sides
color: hsl(252 62% calc(46% - var(--i) * 1.3%));
}
// The front copy gives the element its size and carries the gradient.
span:first-child {
position: relative;
display: block;
background: linear-gradient(100deg, var(--accent-2), var(--accent) 45%, var(--hot));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
// The last copy is the soft shadow on the floor. Static, so the blur costs nothing per frame.
span:last-child {
color: rgb(0 0 0 / 0.55);
text-shadow: 0 0 10px rgb(0 0 0 / 0.6);
transform: translateZ(-25px) translate(-5px, 7px);
}
}
// alternate + ease-in-out = the way back is the mirror image, so the loop has no seam
@keyframes d-shadowtext-sway {
from {
transform: rotateX(56deg) rotateZ(-40deg);
}
to {
transform: rotateX(48deg) rotateZ(-22deg);
}
}