Split-Flap Board
Entrance & Kinetic · Animated · pure CSS
An airport Solari departure board: every letter sits on its own dark rounded chip split by a hinge line, and the blank top card clacks down two to five times in an accelerating-then-settling rhythm before folding away to reveal the bright glyph, cascading across the line by index. Choose amber, white or phosphor-green — the mechanics are sold through hinge shadow and motion rather than fake intermediate characters (per-letter markup).
How it works
Split-Flap Board is an animated entrance & kinetic text effect rendered entirely in CSS. Each character is wrapped in its own span so it can animate independently — the HTML and JSX exports include that per-letter markup.
Controls
Split-Flap Board exposes 4 dedicated controls — Flaps, Duration, Stagger and Board — on top of the shared type controls (font, weight, letter-spacing and case). Open it in the generator to tune every value live, then copy the updated CSS.
CSS
/* Split-Flap Board — made with TEXT-FX · https://text-fx.app
* HTML: each character is wrapped in a <span> — see the HTML export.
* Font: 'Space Grotesk', sans-serif (load from Google Fonts).
*/
.text-effect {
font-family: 'Space Grotesk', sans-serif;
font-weight: 700;
letter-spacing: 8px;
text-transform: none;
}
.text-effect {
white-space: pre;
line-height: 1.5;
}
.text-effect .fx-ch {
position: relative;
display: inline-block;
box-sizing: border-box;
height: 1.5em;
min-width: 0.62em;
margin: 0 0.05em;
vertical-align: middle;
border-radius: 0.12em;
border: 1px solid hsl(222 14% 4%);
background: linear-gradient(180deg, hsl(220 12% 16%), hsl(223 14% 8%));
box-shadow: 0 0.05em 0.14em hsl(0 0% 0% / 0.5), inset 0 0 0 1px hsl(0 0% 100% / 0.06);
perspective: 6em;
}
.text-effect .fx-glyph {
display: block;
padding: 0 0.16em;
line-height: 1.5em;
text-align: center;
color: hsl(145 70% 55%);
text-shadow: 0 0 0.06em hsl(146 90% 50% / 0.5), 0 0 0.42em hsl(150 90% 42% / 0.28);
}
.text-effect .fx-ch::after {
content: "";
position: absolute;
left: 0.06em;
right: 0.06em;
top: 50%;
height: 0.05em;
transform: translateY(-0.025em);
background: linear-gradient(180deg, hsl(0 0% 0% / 0.72), hsl(0 0% 100% / 0.05));
z-index: 3;
pointer-events: none;
}
.text-effect .fx-flap {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 50%;
transform-origin: 50% 100%;
transform: rotateX(-90deg);
border-radius: 0.1em 0.1em 0 0;
background: linear-gradient(180deg, hsl(220 12% 19%), hsl(222 13% 10%));
box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.05), inset 0 -0.06em 0.06em hsl(0 0% 0% / 0.6);
backface-visibility: hidden;
z-index: 2;
animation: text-effect-flap 1.47s linear both;
animation-delay: calc(var(--i) * 70ms);
}
.text-effect .fx-ch.fx-sp {
min-width: 0.85em;
}
.text-effect:hover .fx-ch .fx-flap {
animation-name: text-effect-flap-r;
}
@keyframes text-effect-flap {
0% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
32.93% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
33.33% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
66.27% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
66.67% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.2, 0.62, 0.35, 1); }
94% { transform: rotateX(-90deg); }
100% { transform: rotateX(-90deg); }
}
@keyframes text-effect-flap-r {
0% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
32.93% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
33.33% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
66.27% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
66.67% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.2, 0.62, 0.35, 1); }
94% { transform: rotateX(-90deg); }
100% { transform: rotateX(-90deg); }
}
HTML
This effect needs the markup below (per-letter spans, SVG defs, or a data-text attribute).
<!-- Made with TEXT-FX · https://text-fx.app -->
<style>
.text-effect {
font-family: 'Space Grotesk', sans-serif;
font-weight: 700;
letter-spacing: 8px;
text-transform: none;
}
.text-effect {
white-space: pre;
line-height: 1.5;
}
.text-effect .fx-ch {
position: relative;
display: inline-block;
box-sizing: border-box;
height: 1.5em;
min-width: 0.62em;
margin: 0 0.05em;
vertical-align: middle;
border-radius: 0.12em;
border: 1px solid hsl(222 14% 4%);
background: linear-gradient(180deg, hsl(220 12% 16%), hsl(223 14% 8%));
box-shadow: 0 0.05em 0.14em hsl(0 0% 0% / 0.5), inset 0 0 0 1px hsl(0 0% 100% / 0.06);
perspective: 6em;
}
.text-effect .fx-glyph {
display: block;
padding: 0 0.16em;
line-height: 1.5em;
text-align: center;
color: hsl(145 70% 55%);
text-shadow: 0 0 0.06em hsl(146 90% 50% / 0.5), 0 0 0.42em hsl(150 90% 42% / 0.28);
}
.text-effect .fx-ch::after {
content: "";
position: absolute;
left: 0.06em;
right: 0.06em;
top: 50%;
height: 0.05em;
transform: translateY(-0.025em);
background: linear-gradient(180deg, hsl(0 0% 0% / 0.72), hsl(0 0% 100% / 0.05));
z-index: 3;
pointer-events: none;
}
.text-effect .fx-flap {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 50%;
transform-origin: 50% 100%;
transform: rotateX(-90deg);
border-radius: 0.1em 0.1em 0 0;
background: linear-gradient(180deg, hsl(220 12% 19%), hsl(222 13% 10%));
box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.05), inset 0 -0.06em 0.06em hsl(0 0% 0% / 0.6);
backface-visibility: hidden;
z-index: 2;
animation: text-effect-flap 1.47s linear both;
animation-delay: calc(var(--i) * 70ms);
}
.text-effect .fx-ch.fx-sp {
min-width: 0.85em;
}
.text-effect:hover .fx-ch .fx-flap {
animation-name: text-effect-flap-r;
}
@keyframes text-effect-flap {
0% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
32.93% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
33.33% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
66.27% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
66.67% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.2, 0.62, 0.35, 1); }
94% { transform: rotateX(-90deg); }
100% { transform: rotateX(-90deg); }
}
@keyframes text-effect-flap-r {
0% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
32.93% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
33.33% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.55, 0.02, 0.9, 0.42); }
66.27% { transform: rotateX(-90deg); animation-timing-function: steps(1, end); }
66.67% { transform: rotateX(0deg); animation-timing-function: cubic-bezier(0.2, 0.62, 0.35, 1); }
94% { transform: rotateX(-90deg); }
100% { transform: rotateX(-90deg); }
}
</style>
<div class="text-effect"><span class="fx-ch" style="--i:0;--n:9"><span class="fx-glyph">Y</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:1;--n:9"><span class="fx-glyph">o</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:2;--n:9"><span class="fx-glyph">u</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:3;--n:9"><span class="fx-glyph">r</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch fx-sp" style="--i:4;--n:9"></span><span class="fx-ch" style="--i:5;--n:9"><span class="fx-glyph">t</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:6;--n:9"><span class="fx-glyph">e</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:7;--n:9"><span class="fx-glyph">x</span><span class="fx-flap" aria-hidden="true"></span></span><span class="fx-ch" style="--i:8;--n:9"><span class="fx-glyph">t</span><span class="fx-flap" aria-hidden="true"></span></span></div>
- Category
- Entrance & Kinetic
- Type
- Animated
- Browser support
- All modern browsers
- Capabilities
- perLetter