25 CSS Text Animations 05 / 25
CSS Text Reveal Clip Animation
A premium editorial text reveal using clip-path inset() to wipe text into view from behind an invisible mask — elegant, production-ready.
The code
<div class="ta-05">
<div class="ta-05__stage">
<div class="ta-05__line-wrap"><p class="ta-05__line ta-05__line--1">Crafted</p></div>
<div class="ta-05__line-wrap"><p class="ta-05__line ta-05__line--2">for the</p></div>
<div class="ta-05__line-wrap ta-05__line-wrap--accent">
<p class="ta-05__line ta-05__line--3">discerning eye.</p>
</div>
</div>
</div> <div class="ta-05">
<div class="ta-05__stage">
<div class="ta-05__line-wrap"><p class="ta-05__line ta-05__line--1">Crafted</p></div>
<div class="ta-05__line-wrap"><p class="ta-05__line ta-05__line--2">for the</p></div>
<div class="ta-05__line-wrap ta-05__line-wrap--accent">
<p class="ta-05__line ta-05__line--3">discerning eye.</p>
</div>
</div>
</div>.ta-05, .ta-05 *, .ta-05 *::before, .ta-05 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-05 ::selection { background: #e2e8f0; color: #0f172a; }
.ta-05 {
--bg: #0f0f0f;
--gold: #c9a84c;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Playfair Display', Georgia, serif;
}
.ta-05__stage { text-align: left; }
.ta-05__line-wrap {
overflow: hidden;
line-height: 1.15;
}
.ta-05__line {
font-size: clamp(1.8rem, 5.5vw, 3.2rem);
font-weight: 700;
color: #e2e8f0;
display: block;
transform: translateY(110%);
animation: ta-05-rise 0.9s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.ta-05__line--1 { animation-delay: 0.1s; }
.ta-05__line--2 { animation-delay: 0.3s; font-style: italic; font-weight: 400; color: #94a3b8; }
.ta-05__line--3 { animation-delay: 0.55s; color: var(--gold); }
.ta-05__line-wrap--accent .ta-05__line {
border-bottom: 2px solid var(--gold);
padding-bottom: 0.1em;
}
@keyframes ta-05-rise {
to { transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
.ta-05__line { animation: none; transform: none; }
} .ta-05, .ta-05 *, .ta-05 *::before, .ta-05 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-05 ::selection { background: #e2e8f0; color: #0f172a; }
.ta-05 {
--bg: #0f0f0f;
--gold: #c9a84c;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Playfair Display', Georgia, serif;
}
.ta-05__stage { text-align: left; }
.ta-05__line-wrap {
overflow: hidden;
line-height: 1.15;
}
.ta-05__line {
font-size: clamp(1.8rem, 5.5vw, 3.2rem);
font-weight: 700;
color: #e2e8f0;
display: block;
transform: translateY(110%);
animation: ta-05-rise 0.9s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.ta-05__line--1 { animation-delay: 0.1s; }
.ta-05__line--2 { animation-delay: 0.3s; font-style: italic; font-weight: 400; color: #94a3b8; }
.ta-05__line--3 { animation-delay: 0.55s; color: var(--gold); }
.ta-05__line-wrap--accent .ta-05__line {
border-bottom: 2px solid var(--gold);
padding-bottom: 0.1em;
}
@keyframes ta-05-rise {
to { transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
.ta-05__line { animation: none; transform: none; }
}How this works
Each text line is wrapped in an overflow: hidden parent container. The text element inside starts translated below the visible area using translateY(110%) and animates upward into position. This is the classic 'text behind a mask' technique — the overflow clip of the parent acts as the mask edge, creating the illusion of text sliding up from below a line.
The staggered reveal uses sequential animation-delay values on each line wrapper, timed so each line finishes just as the next begins. A cubic-bezier(0.16, 1, 0.3, 1) easing — sometimes called 'expo out' — gives the slide an elastic deceleration that feels luxurious and weighted rather than mechanical.
Customize
- Change the reveal direction from bottom-up to top-down by changing
translateY(110%)totranslateY(-110%)in the starting keyframe. - Adjust the stagger gap between lines by changing the
animation-delayincrements —0.1sapart feels rapid and energetic,0.4sapart feels measured and editorial. - Pair with a
scaleXreveal on an underline::afterpseudo-element to add a decorative bar that draws in after the text appears. - Apply to hero sections by using
font-size: clamp(3rem, 8vw, 6rem)and a thin-weight serif font for a luxury fashion brand aesthetic. - Trigger on scroll instead of load by adding an
IntersectionObserverin JS that toggles a.is-visibleclass which enables the animation.
Watch out for
- The parent container must have
overflow: hidden— forgetting this makes the text visible below the frame during the translateY phase, breaking the illusion. - The
will-change: transformon the animating child promotes it to its own compositor layer; applying it to every letter in a long block of text wastes GPU memory. - Some screen readers may not announce text that starts with
opacity: 0or is translated off-screen; usearia-labelon the parent or ensure the text is in the DOM from the start.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 36+ | 9+ | 16+ | 36+ |
cubic-bezier easing and translateY are universally supported; no issues across modern browsers.