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.
A headline printed across three panels folded like a brochure. Each panel is a window onto the same wide sheet; hover or focus flattens the paper.
Your edited version
rotateY(52deg), and its left/right neighbours hang off its edges and swing back twice as far — so in absolute terms they land at -52deg, folding like a “Z” seen from above.transform-style: preserve-3d or the fold flattens at that level; the visible paper inside each hinge is a separate element that is allowed to clip.calc(var(--i) * -100%) — so the printed headline lines up across the folds.opacity: 0 on hover/focus — cheap, since only opacity is animating, not the gradient itself.:hover/:focus-visible every panel’s transform resets to none, flattening the whole sheet in one shared transition.--u, tied to the canvas, so the headline is the same share of a gallery card, the editor and a recording canvas.nested hinges with transform-originsame sheet offset by --i × -100%clip the leaf, never the hingeshading faded with opacity<div class="scene">
<div class="fold" tabindex="0" aria-label="Unfold: a headline on folded paper, flattens on hover or focus">
<div class="panel panel-mid">
<b style="--i:1" aria-hidden="true"><span><small>HOVER TO</small>UNFOLD</span></b>
<div class="panel panel-left"><b style="--i:0" aria-hidden="true"><span><small>HOVER TO</small>UNFOLD</span></b></div>
<div class="panel panel-right"><b style="--i:2" aria-hidden="true"><span><small>HOVER TO</small>UNFOLD</span></b></div>
</div>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the headline is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.45vmin;
perspective: calc(800 * var(--u));
}
/* the static hit area: it takes :hover / :focus and never moves (the paper inside does) */
.fold {
display: grid;
place-items: center;
width: calc(214 * var(--u)); /* 3 panels x 66 units, plus a little breathing room */
height: calc(144 * var(--u));
border-radius: calc(12 * var(--u));
cursor: pointer;
transform-style: preserve-3d;
}
.fold:focus-visible {
outline: calc(2 * var(--u)) solid #2ee6d6;
outline-offset: calc(2 * var(--u));
}
/* every panel is a hinge that may hold the next panel; the visible paper is its <b> */
.panel {
position: relative;
width: calc(66 * var(--u));
height: calc(104 * var(--u));
pointer-events: none;
transform-style: preserve-3d;
transition: transform 0.9s cubic-bezier(0.3, 1.25, 0.5, 1);
}
/* the middle panel is the root: it swings one way... */
.panel-mid {
transform: rotateX(8deg) rotateY(52deg);
}
/* ...and its neighbours hang on its edges and swing back twice as far */
.panel-left,
.panel-right {
position: absolute;
top: 0;
transform: rotateY(-104deg);
}
.panel-left {
right: 100%;
transform-origin: 100% 50%;
}
.panel-right {
left: 100%;
transform-origin: 0 50%;
}
.fold:hover .panel,
.fold:focus-visible .panel {
transform: none;
}
/* the paper: a window one panel wide... */
.panel > b {
position: absolute;
inset: 0;
overflow: hidden;
backface-visibility: hidden;
}
/* ...onto a sheet three panels wide, shifted left by --i panels, so the same sheet lines up */
.panel > b > span {
position: absolute;
top: 0;
left: calc(var(--i) * -100%);
display: grid;
place-content: center;
gap: calc(4 * var(--u));
width: 300%;
height: 100%;
/* deep enough for its white words: the bright #8b6cff, #ff4d9d, #ffb547 were 2.5:1 */
background: linear-gradient(115deg, #6a45f5, #d1206f 60%, #c96f00);
color: #fff;
font-size: calc(41 * var(--u));
font-weight: 900;
line-height: 1;
letter-spacing: 0.03em;
text-align: center;
}
.panel > b > span small {
font-size: calc(10 * var(--u));
font-weight: 700;
letter-spacing: 0.3em; /* full white: at 0.85, under the middle panel's sheen, it was 2.9:1 */
}
/* shading that sells the fold: fades out as the paper flattens (opacity is cheap to animate) */
.panel > b::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(90deg, rgb(0 0 0 / 0.45), rgb(0 0 0 / 0.1));
transition: opacity 0.9s;
}
.panel-mid > b::after {
background: linear-gradient(90deg, rgb(255 255 255 / 0.12), rgb(255 255 255 / 0));
}
.fold:hover .panel > b::after,
.fold:focus-visible .panel > b::after {
opacity: 0;
}