AI CSS Animations

Plasma Ball Loader

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.

HTML

<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>

CSS

.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;
  }
}

Customizing this loader

  • Color: set --ldr-color on the element or a parent. Currently previewing #3b82f6.
  • Size: set --ldr-size. Every dimension in the snippet is derived from it. Currently previewing 64px.
  • Speed: change the duration on the animation shorthand. Delays on the children are relative, so they keep their rhythm.
  • Accessibility: the root carries 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.

Similar loaders