25 CSS Text Animations 11 / 25
CSS Text Stroke Draw Animation
SVG stroke-dashoffset animation draws each letter outline progressively as if a pen is writing the text in real time.
The code
<div class="ta-11">
<div class="ta-11__stage">
<svg class="ta-11__svg" viewBox="0 0 400 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Draw">
<text class="ta-11__text" x="50%" y="88" text-anchor="middle">DRAW</text>
</svg>
<p class="ta-11__sub">SVG stroke-dashoffset · path length animation</p>
</div>
</div> <div class="ta-11">
<div class="ta-11__stage">
<svg class="ta-11__svg" viewBox="0 0 400 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Draw">
<text class="ta-11__text" x="50%" y="88" text-anchor="middle">DRAW</text>
</svg>
<p class="ta-11__sub">SVG stroke-dashoffset · path length animation</p>
</div>
</div>.ta-11, .ta-11 *, .ta-11 *::before, .ta-11 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-11 ::selection { background: #7c3aed; color: #fff; }
.ta-11 {
--bg: #08050f;
--stroke: #a78bfa;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', sans-serif;
}
.ta-11__stage { text-align: center; width: 100%; max-width: 420px; }
.ta-11__svg {
width: 100%;
overflow: visible;
}
.ta-11__text {
font-family: 'Syne', 'Helvetica Neue', sans-serif;
font-size: 88px;
font-weight: 900;
fill: transparent;
stroke: var(--stroke);
stroke-width: 1.8;
stroke-dasharray: 1200;
stroke-dashoffset: 1200;
letter-spacing: 6px;
animation:
ta-11-draw 2.5s cubic-bezier(0.4, 0, 0.2, 1) 0.3s forwards,
ta-11-fill 0.6s ease 2.4s forwards;
}
@keyframes ta-11-draw {
to { stroke-dashoffset: 0; }
}
@keyframes ta-11-fill {
to { fill: rgba(167, 139, 250, 0.15); }
}
.ta-11__sub {
font-size: 0.65rem;
color: #2d1a4a;
margin-top: 0.75rem;
letter-spacing: 0.1em;
font-family: 'Courier New', monospace;
}
@media (prefers-reduced-motion: reduce) {
.ta-11__text {
animation: none;
stroke-dashoffset: 0;
fill: rgba(167, 139, 250, 0.15);
}
} .ta-11, .ta-11 *, .ta-11 *::before, .ta-11 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-11 ::selection { background: #7c3aed; color: #fff; }
.ta-11 {
--bg: #08050f;
--stroke: #a78bfa;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', sans-serif;
}
.ta-11__stage { text-align: center; width: 100%; max-width: 420px; }
.ta-11__svg {
width: 100%;
overflow: visible;
}
.ta-11__text {
font-family: 'Syne', 'Helvetica Neue', sans-serif;
font-size: 88px;
font-weight: 900;
fill: transparent;
stroke: var(--stroke);
stroke-width: 1.8;
stroke-dasharray: 1200;
stroke-dashoffset: 1200;
letter-spacing: 6px;
animation:
ta-11-draw 2.5s cubic-bezier(0.4, 0, 0.2, 1) 0.3s forwards,
ta-11-fill 0.6s ease 2.4s forwards;
}
@keyframes ta-11-draw {
to { stroke-dashoffset: 0; }
}
@keyframes ta-11-fill {
to { fill: rgba(167, 139, 250, 0.15); }
}
.ta-11__sub {
font-size: 0.65rem;
color: #2d1a4a;
margin-top: 0.75rem;
letter-spacing: 0.1em;
font-family: 'Courier New', monospace;
}
@media (prefers-reduced-motion: reduce) {
.ta-11__text {
animation: none;
stroke-dashoffset: 0;
fill: rgba(167, 139, 250, 0.15);
}
}How this works
The text is rendered as an SVG <text> element with fill: none and a coloured stroke. The SVG stroke-dasharray property sets the dash and gap length to match the full perimeter of the text path. Setting stroke-dashoffset to the same full-length value makes the stroke entirely invisible — the offset shifts the dash pattern so the gap covers the entire path.
The ta-11-draw keyframe animates stroke-dashoffset from the full path length down to 0, which progressively slides the visible dash portion over the text path — creating the illusion of a pen drawing each letter. A fill-in keyframe follows with a delayed fill opacity animation so the solid fill bleeds in after the stroke is complete.
Customize
- Adjust the
stroke-widthfrom1.5to3for a bold marker line, or down to0.8for a delicate pen stroke. - Change the drawing speed by altering
animation-durationon the text element —2sis purposeful,6sis mesmerizingly slow. - Animate stroke colour during the draw by adding colour stops to the keyframe — going from
stroke: #7c3aedtostroke: #ec4899mid-draw adds visual interest. - Add a subtle
filter: drop-shadow(0 0 6px currentColor)on the SVG for a glowing neon draw-on effect against dark backgrounds. - Set
stroke-dashoffsetin reverse (from 0 to full length) to create an erase effect — text draws out of existence.
Watch out for
- The
stroke-dasharrayvalue must equal the total path length of the text — for SVG text this is a fixed value you measure once, but for paths you'd usegetTotalLength()in JS. - SVG text strokes render at the centre of the glyph outline, so thick strokes overflow into letter counters (the enclosed spaces in 'o', 'e', 'p') — test legibility at your chosen stroke width.
- The final fill animation must start after the draw is visually complete; use
animation-delayequal to or slightly longer than the draw duration to prevent premature fill bleed.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 31+ | 6.1+ | 11+ | 31+ |
SVG stroke-dashoffset animation is universally supported. Ensure the SVG viewBox matches the text dimensions to prevent clipping.