Skip to content
← ALL EXPERIMENTS

03 / CSS / 2026-04-20

Subway Berserk

Six takes on the split-flap display. Same phrases. Wildly different typography, mechanics, and feel.

How it works

// 01 DPI and pixel density

Every variant runs the same general pattern. Each character slot gets a staggered start time so the letters begin changing at different moments. During the roll, the slot displays random intermediate glyphs pulled from an alphabet that matches the variant's character set. Each slot has its own total duration drawn from a small random range, which means the slots land at different times rather than all finishing together. The spread of durations is the cascade you hear when a real Solari board clacks through an update.

// 02 Bleed and cut tolerance

The techniques differ. Variant 1 uses CSS 3D rotateX with perspective to give the flap a physical hinge. Variant 2 maps each character to a boolean grid and tweens a per-dot lifetime so the transition looks like pixels dissolving. Variant 4 renders each slot as a tall reel of characters translated on Y with a cubic-bezier that overshoots by a few pixels before settling, which is what sells the mechanical bounce. Variant 5 scrambles through glyphs including %, $, #, and @ at a rate proportional to the alphabetic distance from the last character, so a jump from A to B feels quick and a jump from A to Z takes longer. Variant 6 lights SVG segments of a 14-segment display with a pink glow after each segment settles.

// 03 Safe zone and trim accuracy

The performance constraint is real. Animating fifteen-plus slots at once means avoiding React re-renders inside the hot loop. The variants that use canvas draw directly to a 2D context on a requestAnimationFrame tick. The CSS variants batch updates with useState only at settle points, never per-frame per-slot. RAF beats setInterval because the browser aligns it with the display refresh rate, which is how the widget holds 60 fps on a mid-range phone.

OBJECT / subway.berserkCSS
......
......

// why this exists

six distinct treatments of one motion problem, executed in one pass

A split-flap display is the mechanical departure board you grew up watching in train stations and airports. Italian company Solari di Udine built the best-known version in 1956, which is why designers still call them Solari boards today. Inside the cabinet, each character slot is a small drum wrapped with fifty or so hinged plastic cards, each card printed with one letter or number. When the schedule changes, a motor rotates the drum and the cards slap down one by one in sequence, producing the signature tick-tick-tick as they fall into place.

The reason this pattern still feels satisfying in 2026 is that it refuses to be instant. Digital displays update in a single frame. A split-flap makes you wait. You see the current letter begin to flip, you hear the mechanism work, and for a second or two the board shows a smear of intermediate characters before landing on the new answer. Dozens of slots do this at once, each on its own clock, and the staggered landings produce a soft cascade instead of a single event. That cascade is the whole point. It gives analog time to a digital display.

This widget is six different digital interpretations of that one physical idea. Classic split-flap, rendered with CSS 3D cards that peel from top to bottom on a warm black cabinet. LED dot-matrix, each character drawn on a 7x5 grid of amber dots that dissolve pixel by pixel as the matrix morphs. Railway station mechanical, with pink hinge flashes when a card lands. Rolling odometer, where every slot is a vertical reel that spins through the alphabet with a cubic-bezier overshoot. Typewriter cipher, scrambling through letters and symbols at a duration proportional to the alphabetic distance from the previous character. And a 14-segment heritage LED display, with ghost segments at 5% opacity so you can see the skeleton of every possible glyph behind the illuminated one.

Same phrases cycle through all six variants. The typography and mechanics change dramatically. The point is to show that one animation concept, executed with real intent, gives you a whole vocabulary of brand moments.

Frequently asked questions

How does a split-flap display work?

A motor rotates a drum wrapped with hinged cards, each printed with one character. When the drum passes the target character, the motor stops and the last card falls into view. The tick-tick-tick sound is each card slapping down against the next as the drum spins.

What is a Solari board?

A split-flap display made by Solari di Udine, an Italian company that has manufactured them since 1956. Their boards ran in train stations and airports worldwide, and the name Solari became a generic term for any split-flap.

How do I animate individual letters in CSS?

Put each letter in its own element so you can transform it independently. For a flap effect, use rotateX with perspective on a parent. For a reel, stack characters vertically inside an overflow-hidden window and translate the stack on Y. Stagger start times with transition-delay or JavaScript setTimeout.

Is CSS 3D performant enough for flip animations?

Yes, if you stick to transform and opacity. The browser promotes transformed elements to their own compositor layer, which means the GPU does the math. Adding will-change: transform helps. Animating width, height, or top/left kills it.

When did dot-matrix displays become common?

Character-cell LED dot-matrix displays took over transit signage in the 1980s and 1990s as the cost of discrete LEDs dropped. They replaced many split-flap boards because they had no moving parts, though a lot of people still prefer the mechanical ones.

What is a 14-segment display?

An evolution of the 7-segment digit you see on calculators. A 14-segment cell adds diagonal and vertical bars so it can render full uppercase letters, not just digits. 16-segment adds two more for a slightly cleaner A, M, and W. Before dot-matrix got cheap, this was how signs showed letters.

Why do the letters land at different times?

Each slot gets its own start delay and its own total duration. On a real Solari board, the variation comes from mechanical tolerance and differing distances to the target character. On a digital one, you introduce the variation on purpose because it is the satisfying part.

Can I drop one of these variants into my own site?

Yes. Each variant is a single self-contained component with no cross-imports. Copy the file, import the component, adjust the palette tokens. No dependencies beyond React.

How do you keep 60 fps with fifteen slots animating at once?

Draw to canvas for pixel-heavy variants like dot-matrix. For CSS variants, batch state updates so React re-renders once per settle event rather than per frame per slot. Use requestAnimationFrame over setInterval so updates align to the display refresh.

Does this respect reduced motion preferences?

Yes. Every variant reads prefers-reduced-motion and falls back to a static final state if the user has requested reduced motion. The widget never animates against that preference.