CSS SVG Loaders — 5 Animated Spinner Patterns with Pure CSS
SVG-based loaders are lighter, crisper, and more flexible than GIF or canvas alternatives. Every pattern below is pure CSS — no JavaScript, no library, no build step. Copy the SVG and CSS into your project and you are done.
Why SVG for Loaders?
SVG loaders render crisp at any size and DPI, scale from 16px to 200px without blurring, and weigh under 1 KB each. Because the shapes are CSS-targetable, you can theme them with a single color variable or CSS custom property — no need for multiple image variants.
Key CSS properties for SVG animation
stroke-dasharray— sets the dash pattern on a stroked pathstroke-dashoffset— shifts the dash along the path (drives draw-on / ring effects)transform-origin— center of rotation; usetransform-box: fill-boxalongside itanimation-delay(or--dcustom property) — stagger multiple elements
1. Rotating Spinner
The classic indeterminate loader. A partial-stroke circle rotated continuously.
SVG
<svg viewBox="0 0 40 40" width="40" height="40">
<circle
class="spinner"
cx="20" cy="20" r="16"
fill="none"
stroke="#6366f1"
stroke-width="3"
stroke-dasharray="22 78"
stroke-linecap="round"
/>
</svg>CSS
.spinner {
transform-origin: 50% 50%;
animation: spin 800ms linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}2. Progress Ring
A determinate ring that fills to a percentage. Set --progress to any value 0–100.
SVG
<svg viewBox="0 0 40 40" width="80" height="80"
style="--progress: 72">
<!-- track -->
<circle cx="20" cy="20" r="16"
fill="none" stroke="#2A2A2A" stroke-width="3"/>
<!-- fill -->
<circle class="ring" cx="20" cy="20" r="16"
fill="none" stroke="#6366f1" stroke-width="3"
stroke-linecap="round"/>
</svg>CSS
.ring {
/* circumference of r=16 ≈ 100.5 */
stroke-dasharray: 100.5;
stroke-dashoffset: calc(100.5 - (100.5 * var(--progress) / 100));
transform: rotate(-90deg);
transform-origin: 50% 50%;
transition: stroke-dashoffset 600ms ease;
}3. Pulsing Circle
A filled circle that scales and fades in a loop — great for 'live' or 'recording' indicators.
SVG
<svg viewBox="0 0 40 40" width="40" height="40">
<circle class="pulse-ring" cx="20" cy="20" r="10"
fill="none" stroke="#6366f1" stroke-width="2"/>
<circle cx="20" cy="20" r="6" fill="#6366f1"/>
</svg>CSS
.pulse-ring {
transform-origin: 50% 50%;
animation: pulse 1400ms ease-out infinite;
}
@keyframes pulse {
0% { transform: scale(0.8); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}4. Three Bouncing Dots
Three circles that bounce with staggered delays — the standard chat/typing indicator pattern.
SVG
<svg viewBox="0 0 60 20" width="60" height="20"> <circle class="dot" style="--d:0ms" cx="10" cy="10" r="4" fill="#6366f1"/> <circle class="dot" style="--d:150ms" cx="30" cy="10" r="4" fill="#6366f1"/> <circle class="dot" style="--d:300ms" cx="50" cy="10" r="4" fill="#6366f1"/> </svg>
CSS
.dot {
animation: bounce 900ms var(--d) ease-in-out infinite alternate;
transform-origin: 50% 50%;
}
@keyframes bounce {
from { transform: translateY(4px); opacity: 0.4; }
to { transform: translateY(-4px); opacity: 1; }
}5. Skeleton Shimmer Bar
A placeholder bar with a moving shimmer gradient — matches the skeleton screen pattern used by Facebook, LinkedIn, and YouTube.
SVG
<svg viewBox="0 0 200 16" width="200" height="16">
<defs>
<linearGradient id="shimmer" x1="0%" x2="100%" y1="0%" y2="0%"
gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#1A1A1A"/>
<stop offset="50%" stop-color="#2A2A2A"/>
<stop offset="100%" stop-color="#1A1A1A"/>
</linearGradient>
</defs>
<rect class="shimmer-bar" rx="4" ry="4"
width="200" height="16" fill="url(#shimmer)"/>
</svg>CSS
@keyframes shimmer {
from { transform: translateX(-100%); }
to { transform: translateX(100%); }
}
.shimmer-bar {
animation: shimmer 1400ms ease-in-out infinite;
transform-box: fill-box;
}Common Gotchas
Rotation jitters in Safari
Add transform-box: fill-box to any SVG element you rotate. Without it, Safari computes transform-origin relative to the SVG viewport rather than the element's own bounding box.
Circumference formula
For progress rings: circumference = 2 × π × r. For r=16: ~100.5. For r=20: ~125.7. Use this in stroke-dasharray and stroke-dashoffset calculations.
CSS animations in <img> tags
CSS animations are sandboxed when an SVG is loaded via <img src>. Use inline SVG in your HTML/JSX, or switch to SMIL animations which work inside standalone SVG files.
Build Custom Loaders Visually
The patterns above cover the most common cases, but sometimes you need a custom loader that matches your brand exactly — a specific easing curve, a unique shape, or a multi-element sequence. CSSVG lets you design that visually and export the CSS in one click.
- →Add shapes from the Layers panel or import your own SVG
- →Drag the timeline to set keyframes — position, scale, opacity, fill
- →Preview the loop live on the canvas, adjust easing with the cubic bezier picker
- →Export → CSS for a drop-in file, or Export → SMIL for a fully standalone SVG
Design Your Own SVG Loader
Build and export a custom animated SVG loader in minutes — free, no account needed.
Open the Editor — it's free