Overview
Multiline text reveal where each line appears as a whole unit (never a partial clip) via three CSS techniques: a max-height stack that pops rows in vertically, a clip-path: inset() top-edge wipe, and a clip-path: inset() left-edge draw. Layout never shifts — every row reserves its space and only the visibility animates.
When to use it
Reach for line-step reveal on multi-line hero copy, editorial sub-heads, marketing taglines. Skip it for body paragraphs — users will scan ahead of the reveal and the effect becomes friction. Skip it on content shorter than two lines; the step boundary is the point of the pattern.
How it works
For the max-height variant, each line lives in its own wrapper <span class="line"> with display: block; overflow: hidden; max-height: 0. A staggered @keyframes animates max-height from 0 to a value larger than any plausible line (2lh) so each row pops fully in. For clip-path variants, each line wrapper starts with clip-path: inset(0 0 100% 0) (top wipe) or inset(0 100% 0 0) (left wipe) and animates the matching side to 0. Use per-line animation-delay for the stagger.
Production gotchas
Animating max-height to a generous fixed value works for short lines but blows out layout if the line wraps to two visual lines — cap each wrapper to a single line at the typography level (truncate or guarantee width). The clip-path approach is layout-safe across wrapping but does not animate clip-path in Safari before 14 — gate behind @supports (clip-path: inset(0)) if you support old iOS. Long lines on wide viewports may need a proportional animation-duration for the left-edge variant or the wipe feels rushed.
Accessibility
The text is real DOM throughout — screen readers announce all lines at once on page load, regardless of the visual reveal. This is correct behavior; the reveal is decorative. Under prefers-reduced-motion: reduce drop all delays and durations to zero so lines appear instantly. Verify final-state contrast on each line; nothing about the reveal pattern changes the legibility floor.
References
Implementation depth
A multiline typewriter should reveal whole lines, not partial rows clipped through the baseline. Reserve line boxes up front, then animate max-height or clip-path per wrapper so the layout does not reflow while the text appears.
The implementation risk is responsive wrapping. If the copy wraps differently at narrow widths, a hardcoded line height can cut descenders or expose half a line. Test the longest localized string before tuning delays.