10 / 30
All 30 in 30 CSS Text Animations
- 01CSS Text Sparkle Particle Highlight Hover
- 02Pure CSS Scroll Driven Text Reveal Timeline
- 03CSS Sticky Scroll Text Opacity Fade
- 04CSS Text Path Curve Scroll Animation
- 05CSS Multi Layer Parallax Text Scroll
- 06Pure CSS Typewriter Effect Single Line
- 07CSS Text Reveal Animation on Page Load
- 08CSS Staggered Text Letter Reveal Keyframes
- 09CSS Animated Gradient Text Color Wave
- 10CSS Split Text Reveal Animation Overflow Hidden
- 11CSS Wavy Text Animation Keyframes
- 12CSS Text Unscramble Animation on Load
- 13CSS 3D Flip Text Reveal Animation
- 14CSS Text Hover Underline Stretch Animation
- 15CSS Text Hover Glitch Effect Keyframes
- 16CSS Variable Font Weight Animation on Hover
- 17CSS Text Fill on Hover Left to Right
- 18CSS Perspective Text Tilt on Mousemove
- 19CSS Text Hover Scatter Gather Letters
- 20CSS Marquee Horizontal Text Scroll Continuous
- 21CSS Glowing Neon Sign Text Flicker Animation
- 22CSS Animated Liquid Fill Text Effect
- 23CSS 3D Extrude Shadow Text Animation
- 24CSS Animated Stroke Text Drawing Effect
- 25CSS Metallic Shimmer Text Animation
- 26CSS Spotlight Text Reveal Mask
- 27CSS Rainbow Text Sweep Keyframes
- 28CSS Smoky Text Dissipate Blur Animation
- 29CSS Holographic Foil Text Reflection Animation
- 30CSS Rotating Text Wheel Vertical Loop
CSS Split Text Reveal Animation Overflow Hidden
The agency-site classic: multi-line headlines where each line climbs out of an invisible overflow:hidden mask — shown as a warm editorial three-liner and a brutalist skew-rise where lines shear upright as they land.
Build interactive UI like this from scratch: 20 HTML, CSS & JavaScript projects
ZTM · JavaScript Web Projects · 30‑day money-back guarantee · Affiliate link
The code
<div class="cat-10-group">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-10a" aria-label="Editorial line mask reveal">
<h1 class="cat-10a__title">
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:0">We craft</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:1">interfaces that</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line cat-10a__line--em" style="--i:2">feel inevitable.</span></span>
</h1>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-10b" aria-label="Skewed line mask reveal">
<h1 class="cat-10b__title">
<span class="cat-10b__mask"><span class="cat-10b__line" style="--i:0">BOLD</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--ghost" style="--i:1">MOVES</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--acid" style="--i:2">ONLY.</span></span>
</h1>
</section>
</div><div class="cat-10-group">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-10a" aria-label="Editorial line mask reveal">
<h1 class="cat-10a__title">
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:0">We craft</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:1">interfaces that</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line cat-10a__line--em" style="--i:2">feel inevitable.</span></span>
</h1>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-10b" aria-label="Skewed line mask reveal">
<h1 class="cat-10b__title">
<span class="cat-10b__mask"><span class="cat-10b__line" style="--i:0">BOLD</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--ghost" style="--i:1">MOVES</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--acid" style="--i:2">ONLY.</span></span>
</h1>
</section>
</div>.cat-10-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-10-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-10a,
.cat-10a *,
.cat-10a *::before,
.cat-10a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10a {
--ink: #26201a;
--accent: oklch(0.6 0.13 60);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,#f7f2e9,#efe6d6);
font-family: 'Playfair Display',Georgia,serif;
}
.cat-10a__title {
font-size: clamp(36px,6vw,76px);
font-weight: 600;
line-height: 1.12;
color: var(--ink);
letter-spacing: -.015em;
}
.cat-10a__mask {
display: block;
overflow: hidden;
padding-bottom: .1em;
margin-bottom: -.1em;
}
.cat-10a__line {
display: block;
transform: translateY(112%);
animation: cat-10a-rise .85s cubic-bezier(.16,.84,.3,1) calc(var(--i)*140ms + .25s) both;
}
.cat-10a__line--em {
font-style: italic;
color: var(--accent);
}
@keyframes cat-10a-rise {
to {
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10a__line {
animation: none;
transform: none;
}
}
.cat-10b,
.cat-10b *,
.cat-10b *::before,
.cat-10b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10b {
--acid: oklch(0.9 0.21 125);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #101010;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.cat-10b__title {
font-size: clamp(52px,9.4vw,128px);
font-weight: 900;
line-height: .96;
letter-spacing: -.03em;
color: #f4f4f0;
text-transform: uppercase;
}
.cat-10b__mask {
display: block;
overflow: hidden;
padding-bottom: .06em;
margin-bottom: -.06em;
}
.cat-10b__line {
display: block;
transform-origin: left bottom;
transform: translateY(115%) skewY(7deg);
animation: cat-10b-rise .8s cubic-bezier(.2,.85,.25,1) calc(var(--i)*120ms + .2s) both;
}
.cat-10b__line--ghost {
color: transparent;
-webkit-text-stroke: 2px #f4f4f0;
}
.cat-10b__line--acid {
color: var(--acid);
}
@keyframes cat-10b-rise {
to {
transform: translateY(0) skewY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10b__line {
animation: none;
transform: none;
}
}.cat-10-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-10-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-10a,
.cat-10a *,
.cat-10a *::before,
.cat-10a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10a {
--ink: #26201a;
--accent: oklch(0.6 0.13 60);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,#f7f2e9,#efe6d6);
font-family: 'Playfair Display',Georgia,serif;
}
.cat-10a__title {
font-size: clamp(36px,6vw,76px);
font-weight: 600;
line-height: 1.12;
color: var(--ink);
letter-spacing: -.015em;
}
.cat-10a__mask {
display: block;
overflow: hidden;
padding-bottom: .1em;
margin-bottom: -.1em;
}
.cat-10a__line {
display: block;
transform: translateY(112%);
animation: cat-10a-rise .85s cubic-bezier(.16,.84,.3,1) calc(var(--i)*140ms + .25s) both;
}
.cat-10a__line--em {
font-style: italic;
color: var(--accent);
}
@keyframes cat-10a-rise {
to {
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10a__line {
animation: none;
transform: none;
}
}
.cat-10b,
.cat-10b *,
.cat-10b *::before,
.cat-10b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10b {
--acid: oklch(0.9 0.21 125);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #101010;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.cat-10b__title {
font-size: clamp(52px,9.4vw,128px);
font-weight: 900;
line-height: .96;
letter-spacing: -.03em;
color: #f4f4f0;
text-transform: uppercase;
}
.cat-10b__mask {
display: block;
overflow: hidden;
padding-bottom: .06em;
margin-bottom: -.06em;
}
.cat-10b__line {
display: block;
transform-origin: left bottom;
transform: translateY(115%) skewY(7deg);
animation: cat-10b-rise .8s cubic-bezier(.2,.85,.25,1) calc(var(--i)*120ms + .2s) both;
}
.cat-10b__line--ghost {
color: transparent;
-webkit-text-stroke: 2px #f4f4f0;
}
.cat-10b__line--acid {
color: var(--acid);
}
@keyframes cat-10b-rise {
to {
transform: translateY(0) skewY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10b__line {
animation: none;
transform: none;
}
}/* No JavaScript — each line lives in its own overflow:hidden mask and climbs from translateY(112%) with a 140ms stagger. */ /* No JavaScript — lines rise while unskewing from skewY(7deg), transform-origin left-bottom, so each lands with a whip of momentum. */
/* No JavaScript — each line lives in its own overflow:hidden mask and climbs from translateY(112%) with a 140ms stagger. */
/* No JavaScript — lines rise while unskewing from skewY(7deg), transform-origin left-bottom, so each lands with a whip of momentum. */Here's a working CSS Text Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Split Text Reveal Animation Overflow Hidden
Source: https://codefronts.com/motion/css-text-animations/css-letter-spacing-animation/
The agency-site classic: multi-line headlines where each line climbs out of an invisible overflow:hidden mask — shown as a warm editorial three-liner and a brutalist skew-rise where lines shear upright as they land.
## HTML
```html
<div class="cat-10-group">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-10a" aria-label="Editorial line mask reveal">
<h1 class="cat-10a__title">
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:0">We craft</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:1">interfaces that</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line cat-10a__line--em" style="--i:2">feel inevitable.</span></span>
</h1>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-10b" aria-label="Skewed line mask reveal">
<h1 class="cat-10b__title">
<span class="cat-10b__mask"><span class="cat-10b__line" style="--i:0">BOLD</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--ghost" style="--i:1">MOVES</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--acid" style="--i:2">ONLY.</span></span>
</h1>
</section>
</div>
```
## CSS
```css
.cat-10-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-10-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-10a,
.cat-10a *,
.cat-10a *::before,
.cat-10a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10a {
--ink: #26201a;
--accent: oklch(0.6 0.13 60);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,#f7f2e9,#efe6d6);
font-family: 'Playfair Display',Georgia,serif;
}
.cat-10a__title {
font-size: clamp(36px,6vw,76px);
font-weight: 600;
line-height: 1.12;
color: var(--ink);
letter-spacing: -.015em;
}
.cat-10a__mask {
display: block;
overflow: hidden;
padding-bottom: .1em;
margin-bottom: -.1em;
}
.cat-10a__line {
display: block;
transform: translateY(112%);
animation: cat-10a-rise .85s cubic-bezier(.16,.84,.3,1) calc(var(--i)*140ms + .25s) both;
}
.cat-10a__line--em {
font-style: italic;
color: var(--accent);
}
@keyframes cat-10a-rise {
to {
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10a__line {
animation: none;
transform: none;
}
}
.cat-10b,
.cat-10b *,
.cat-10b *::before,
.cat-10b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10b {
--acid: oklch(0.9 0.21 125);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #101010;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.cat-10b__title {
font-size: clamp(52px,9.4vw,128px);
font-weight: 900;
line-height: .96;
letter-spacing: -.03em;
color: #f4f4f0;
text-transform: uppercase;
}
.cat-10b__mask {
display: block;
overflow: hidden;
padding-bottom: .06em;
margin-bottom: -.06em;
}
.cat-10b__line {
display: block;
transform-origin: left bottom;
transform: translateY(115%) skewY(7deg);
animation: cat-10b-rise .8s cubic-bezier(.2,.85,.25,1) calc(var(--i)*120ms + .2s) both;
}
.cat-10b__line--ghost {
color: transparent;
-webkit-text-stroke: 2px #f4f4f0;
}
.cat-10b__line--acid {
color: var(--acid);
}
@keyframes cat-10b-rise {
to {
transform: translateY(0) skewY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10b__line {
animation: none;
transform: none;
}
}
```
## JavaScript
```js
/* No JavaScript — each line lives in its own overflow:hidden mask and climbs from translateY(112%) with a 140ms stagger. */
/* No JavaScript — lines rise while unskewing from skewY(7deg), transform-origin left-bottom, so each lands with a whip of momentum. */
```Here's a working CSS Text Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Split Text Reveal Animation Overflow Hidden
Source: https://codefronts.com/motion/css-text-animations/css-letter-spacing-animation/
The agency-site classic: multi-line headlines where each line climbs out of an invisible overflow:hidden mask — shown as a warm editorial three-liner and a brutalist skew-rise where lines shear upright as they land.
## HTML
```html
<div class="cat-10-group">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-10a" aria-label="Editorial line mask reveal">
<h1 class="cat-10a__title">
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:0">We craft</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line" style="--i:1">interfaces that</span></span>
<span class="cat-10a__mask"><span class="cat-10a__line cat-10a__line--em" style="--i:2">feel inevitable.</span></span>
</h1>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-10b" aria-label="Skewed line mask reveal">
<h1 class="cat-10b__title">
<span class="cat-10b__mask"><span class="cat-10b__line" style="--i:0">BOLD</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--ghost" style="--i:1">MOVES</span></span>
<span class="cat-10b__mask"><span class="cat-10b__line cat-10b__line--acid" style="--i:2">ONLY.</span></span>
</h1>
</section>
</div>
```
## CSS
```css
.cat-10-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-10-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-10a,
.cat-10a *,
.cat-10a *::before,
.cat-10a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10a {
--ink: #26201a;
--accent: oklch(0.6 0.13 60);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,#f7f2e9,#efe6d6);
font-family: 'Playfair Display',Georgia,serif;
}
.cat-10a__title {
font-size: clamp(36px,6vw,76px);
font-weight: 600;
line-height: 1.12;
color: var(--ink);
letter-spacing: -.015em;
}
.cat-10a__mask {
display: block;
overflow: hidden;
padding-bottom: .1em;
margin-bottom: -.1em;
}
.cat-10a__line {
display: block;
transform: translateY(112%);
animation: cat-10a-rise .85s cubic-bezier(.16,.84,.3,1) calc(var(--i)*140ms + .25s) both;
}
.cat-10a__line--em {
font-style: italic;
color: var(--accent);
}
@keyframes cat-10a-rise {
to {
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10a__line {
animation: none;
transform: none;
}
}
.cat-10b,
.cat-10b *,
.cat-10b *::before,
.cat-10b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-10b {
--acid: oklch(0.9 0.21 125);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #101010;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.cat-10b__title {
font-size: clamp(52px,9.4vw,128px);
font-weight: 900;
line-height: .96;
letter-spacing: -.03em;
color: #f4f4f0;
text-transform: uppercase;
}
.cat-10b__mask {
display: block;
overflow: hidden;
padding-bottom: .06em;
margin-bottom: -.06em;
}
.cat-10b__line {
display: block;
transform-origin: left bottom;
transform: translateY(115%) skewY(7deg);
animation: cat-10b-rise .8s cubic-bezier(.2,.85,.25,1) calc(var(--i)*120ms + .2s) both;
}
.cat-10b__line--ghost {
color: transparent;
-webkit-text-stroke: 2px #f4f4f0;
}
.cat-10b__line--acid {
color: var(--acid);
}
@keyframes cat-10b-rise {
to {
transform: translateY(0) skewY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-10b__line {
animation: none;
transform: none;
}
}
```
## JavaScript
```js
/* No JavaScript — each line lives in its own overflow:hidden mask and climbs from translateY(112%) with a 140ms stagger. */
/* No JavaScript — lines rise while unskewing from skewY(7deg), transform-origin left-bottom, so each lands with a whip of momentum. */
```How this works
Each line gets two elements: a mask (display:block; overflow:hidden) and the moving line inside it. Because the mask hugs the line box, a translateY(110%) hides the text completely with no clip-path math:
.mask{overflow:hidden}
.line{transform:translateY(110%);
animation:rise .85s cubic-bezier(.16,.84,.3,1) both}
.mask:nth-child(2) .line{animation-delay:.14s}The skew variant adds skewY(7deg) to the hidden state with transform-origin:left bottom; unskewing during the rise gives the line a whip of momentum. Padding on the mask (with negative margin compensation) keeps descenders like g/y from shaving against the mask edge.
Make it yours
- Delay lines by 120–160ms each — slower reads editorial, faster reads app-like.
- Swap rise direction per line (alternate up/down) for a shutter feel.
- Tint one line or word as the accent — one, not three.
- Trigger on scroll instead of load by pairing the same keyframes with animation-timeline:view() (see demo 16).
Gotchas — read before shipping
- Give masks a little bottom padding (offset by negative margin) or descenders get clipped mid-animation.
- Each line needs its own mask — one mask around all lines reveals them as a block.
- line-height below 1.1 will clip ascenders in the mask; test with real copy.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 26+.
Pure transform + overflow — works everywhere, including old mobile WebViews. Reduced-motion shows all lines settled.