A glass globe with glowing tendrils that wander from a bright core out to the glass, flickering as they go, like a plasma lamp. Each tendril has its own speed so the pattern keeps changing.
Also known as: plasma lamp animation, electric orb loader, tesla ball.
<svg class="ldr-plasma-ball" viewBox="0 0 100 100" role="status" aria-label="Loading"> <circle class="ldr-plasma-ball-glass" cx="50" cy="50" r="46" /> <g class="ldr-plasma-ball-bolt"><path d="M50 50 C40 40 60 30 49 18 S46 9 50 5" /><circle cx="50" cy="5" r="3" /></g> <g class="ldr-plasma-ball-bolt"><path d="M50 50 C60 41 41 31 52 19 S55 10 50 5" /><circle cx="50" cy="5" r="3" /></g> <g class="ldr-plasma-ball-bolt"><path d="M50 50 C43 39 57 33 47 20 S52 9 50 5" /><circle cx="50" cy="5" r="3" /></g> <g class="ldr-plasma-ball-bolt"><path d="M50 50 C58 38 44 29 53 17 S47 8 50 5" /><circle cx="50" cy="5" r="3" /></g> <g class="ldr-plasma-ball-bolt"><path d="M50 50 C41 42 58 28 48 18 S53 11 50 5" /><circle cx="50" cy="5" r="3" /></g> <circle class="ldr-plasma-ball-core" cx="50" cy="50" r="10" /> </svg>
.ldr-plasma-ball {
--s: var(--ldr-size, 48px);
--c: var(--ldr-color, #3b82f6);
width: var(--s);
height: var(--s);
overflow: visible;
filter: drop-shadow(0 0 calc(var(--s) / 22) var(--c));
}
.ldr-plasma-ball-glass {
fill: color-mix(in srgb, var(--ldr-color, #3b82f6) 10%, transparent);
stroke: color-mix(in srgb, var(--ldr-color, #3b82f6) 45%, transparent);
stroke-width: 3;
}
.ldr-plasma-ball-bolt {
transform-box: view-box;
transform-origin: 50% 50%;
fill: oklch(from var(--c) l c calc(h + 50));
stroke: oklch(from var(--c) l c calc(h + 50));
animation: ldr-plasma-ball-wander var(--t) ease-in-out infinite alternate, ldr-plasma-ball-flicker 0.4s steps(1, end) infinite;
}
.ldr-plasma-ball-bolt path {
fill: none;
stroke-width: 3.5;
stroke-linecap: round;
}
.ldr-plasma-ball-bolt:nth-of-type(1) { --r: 0deg; --t: 2.4s; }
.ldr-plasma-ball-bolt:nth-of-type(2) { --r: 75deg; --t: 3.1s; animation-delay: -1s, -0.1s; }
.ldr-plasma-ball-bolt:nth-of-type(3) { --r: 150deg; --t: 2.7s; animation-delay: -2s, -0.25s; }
.ldr-plasma-ball-bolt:nth-of-type(4) { --r: 220deg; --t: 3.5s; animation-delay: -0.6s, -0.15s; }
.ldr-plasma-ball-bolt:nth-of-type(5) { --r: 290deg; --t: 2.9s; animation-delay: -1.6s, -0.3s; }
.ldr-plasma-ball-core {
fill: var(--c);
stroke: color-mix(in srgb, var(--c) 40%, #fff);
stroke-width: 4;
}
@keyframes ldr-plasma-ball-wander {
from { transform: rotate(calc(var(--r) - 30deg)); }
to { transform: rotate(calc(var(--r) + 30deg)); }
}
@keyframes ldr-plasma-ball-flicker {
0%, 100% { opacity: 1; }
30% { opacity: 0.55; }
45% { opacity: 0.9; }
70% { opacity: 0.4; }
}
@media (prefers-reduced-motion: reduce) {
.ldr-plasma-ball, .ldr-plasma-ball *, .ldr-plasma-ball::before, .ldr-plasma-ball::after, .ldr-plasma-ball *::before, .ldr-plasma-ball *::after {
animation-duration: 3s;
}
}--ldr-color on the element or a parent.
Currently previewing #3b82f6.--ldr-size. Every dimension in the snippet is
derived from it. Currently previewing 64px.animation shorthand.
Delays on the children are relative, so they keep their rhythm.role="status" and an
aria-label so screen readers announce the wait. The reduced-motion rule
at the end slows the animation for users who asked for less motion.