25 CSS Text Animations 06 / 25
CSS Letter Spacing Animation
Dramatic letter-spacing expansion and contraction paired with opacity and blur transitions creates an airy, editorial headline entrance.
The code
<div class="ta-06">
<div class="ta-06__stage">
<h2 class="ta-06__word ta-06__word--1">EXPAND</h2>
<h2 class="ta-06__word ta-06__word--2">YOUR</h2>
<h2 class="ta-06__word ta-06__word--3">HORIZON</h2>
</div>
</div> <div class="ta-06">
<div class="ta-06__stage">
<h2 class="ta-06__word ta-06__word--1">EXPAND</h2>
<h2 class="ta-06__word ta-06__word--2">YOUR</h2>
<h2 class="ta-06__word ta-06__word--3">HORIZON</h2>
</div>
</div>.ta-06, .ta-06 *, .ta-06 *::before, .ta-06 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-06 ::selection { background: #7c3aed; color: #fff; }
.ta-06 {
--bg: #09090b;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', 'Helvetica Neue', sans-serif;
overflow: hidden;
}
.ta-06__stage {
text-align: center;
display: flex;
flex-direction: column;
gap: 0.15rem;
}
.ta-06__word {
font-size: clamp(1.4rem, 4.5vw, 2.8rem);
font-weight: 800;
text-transform: uppercase;
opacity: 0;
animation: ta-06-expand 1.2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.ta-06__word--1 { color: #e2e8f0; animation-delay: 0.1s; }
.ta-06__word--2 { color: #7c3aed; animation-delay: 0.4s; letter-spacing: 0.3em; font-weight: 300; }
.ta-06__word--3 { color: #e2e8f0; animation-delay: 0.7s; }
@keyframes ta-06-expand {
0% {
opacity: 0;
letter-spacing: -0.4em;
filter: blur(10px);
}
60% {
opacity: 1;
filter: blur(0);
}
100% {
opacity: 1;
filter: blur(0);
letter-spacing: 0.15em;
}
}
.ta-06__word--2 {
animation-name: ta-06-expand2;
}
@keyframes ta-06-expand2 {
0% {
opacity: 0;
letter-spacing: -0.2em;
filter: blur(10px);
}
100% {
opacity: 1;
filter: blur(0);
letter-spacing: 0.4em;
}
}
@media (prefers-reduced-motion: reduce) {
.ta-06__word {
animation: none;
opacity: 1;
filter: none;
letter-spacing: 0.1em;
}
} .ta-06, .ta-06 *, .ta-06 *::before, .ta-06 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-06 ::selection { background: #7c3aed; color: #fff; }
.ta-06 {
--bg: #09090b;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', 'Helvetica Neue', sans-serif;
overflow: hidden;
}
.ta-06__stage {
text-align: center;
display: flex;
flex-direction: column;
gap: 0.15rem;
}
.ta-06__word {
font-size: clamp(1.4rem, 4.5vw, 2.8rem);
font-weight: 800;
text-transform: uppercase;
opacity: 0;
animation: ta-06-expand 1.2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.ta-06__word--1 { color: #e2e8f0; animation-delay: 0.1s; }
.ta-06__word--2 { color: #7c3aed; animation-delay: 0.4s; letter-spacing: 0.3em; font-weight: 300; }
.ta-06__word--3 { color: #e2e8f0; animation-delay: 0.7s; }
@keyframes ta-06-expand {
0% {
opacity: 0;
letter-spacing: -0.4em;
filter: blur(10px);
}
60% {
opacity: 1;
filter: blur(0);
}
100% {
opacity: 1;
filter: blur(0);
letter-spacing: 0.15em;
}
}
.ta-06__word--2 {
animation-name: ta-06-expand2;
}
@keyframes ta-06-expand2 {
0% {
opacity: 0;
letter-spacing: -0.2em;
filter: blur(10px);
}
100% {
opacity: 1;
filter: blur(0);
letter-spacing: 0.4em;
}
}
@media (prefers-reduced-motion: reduce) {
.ta-06__word {
animation: none;
opacity: 1;
filter: none;
letter-spacing: 0.1em;
}
}How this works
The animation starts with letters tightly compressed at letter-spacing: -0.5em and low opacity, then expands to the final spacing while fading in. The letter-spacing property adds space uniformly between all characters — negative values push them together into an overlap, while large positive values spread them across the container like an airy display typeface.
A filter: blur() value starts high (around 12px) and eases to zero simultaneously, giving the impression of letters resolving into focus as they space out — similar to a rack-focus effect in cinematography. Both properties animate together in a single keyframe block using a smooth ease-out curve so the expansion decelerates naturally to rest.
Customize
- Start even tighter by setting the initial
letter-spacingto-1emfor a denser clump that explodes apart on reveal. - Combine with
transform: scaleX(0.5)at the start keyframe so the entire word compresses horizontally before expanding — a more theatrical entrance. - Apply to a thin-weight font like
font-weight: 100with a large display size for maximum impact in editorial layouts. - Loop the animation with
animation-iteration-count: infinite; animation-direction: alternateto create a breathing expand-contract rhythm for ambient background text. - Chain multiple words with increasing delays using
animation-delayso each word reveals sequentially like a title card sequence.
Watch out for
letter-spacingadds trailing space after the last character too, so centered text with large spacing values may appear visually off-center; compensate with a matching negativemargin-right.- Animating
filter: blur()is not composited in all browsers — it may cause repaints. Combine withwill-change: filter, letter-spacingto hint for layer promotion. - Very negative
letter-spacingvalues can cause characters to overlap and become illegible; test at your smallest viewport size to ensure readability mid-animation.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 36+ | 9+ | 34+ | 36+ |
Animating letter-spacing via CSS transitions/animations is broadly supported; filter blur animation works in all modern browsers.