Four colored dashes chase each other around every letter outline, forever. Four copies of the same SVG text share one dash pattern and keyframe, and negative delays space them a quarter apart.
Also known as: animated text stroke css, svg stroke dasharray text, colorful outline text loop.
<svg class="txt-svg-text-stroke-loop" viewBox="0 0 440 110" role="img" aria-label="Stroke"> <text x="220" y="86" text-anchor="middle" font-size="96" style="--i: 0">Stroke</text> <text x="220" y="86" text-anchor="middle" font-size="96" style="--i: 1">Stroke</text> <text x="220" y="86" text-anchor="middle" font-size="96" style="--i: 2">Stroke</text> <text x="220" y="86" text-anchor="middle" font-size="96" style="--i: 3">Stroke</text> </svg>
.txt-svg-text-stroke-loop {
--c: var(--txt-color, #3b82f6);
font-size: var(--txt-size, 32px);
font-family: system-ui, sans-serif;
font-weight: 700;
line-height: 1.2;
width: 10em;
height: auto;
overflow: visible;}
.txt-svg-text-stroke-loop text {
font-family: "Arial Black", "Helvetica Neue", Arial, sans-serif;
font-weight: 900;
fill: none;
stroke: var(--c);
stroke-width: 3.4;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 5% 30%;
animation: txt-svg-text-stroke-loop-chase 6s linear infinite;
animation-delay: calc(var(--i) * -1.5s);
}
.txt-svg-text-stroke-loop text:nth-child(1) { fill: color-mix(in srgb, var(--c) 14%, transparent); }
.txt-svg-text-stroke-loop text:nth-child(2) { stroke: color-mix(in srgb, var(--c) 45%, #ec4899); }
.txt-svg-text-stroke-loop text:nth-child(3) { stroke: color-mix(in srgb, var(--c) 45%, #22d3ee); }
.txt-svg-text-stroke-loop text:nth-child(4) { stroke: color-mix(in srgb, var(--c) 45%, #a855f7); }
/* 35% is one full dash + gap, so the loop lands where it began */
@keyframes txt-svg-text-stroke-loop-chase {
to { stroke-dashoffset: -35%; }
}
@media (prefers-reduced-motion: reduce) {
.txt-svg-text-stroke-loop, .txt-svg-text-stroke-loop *, .txt-svg-text-stroke-loop::before, .txt-svg-text-stroke-loop::after, .txt-svg-text-stroke-loop *::before, .txt-svg-text-stroke-loop *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--txt-color on the element or a parent.
Currently previewing #3b82f6.--txt-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 40px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.