Overview
A CSS aurora gradient background drifts layered radial-gradient blobs behind foreground content via transform + opacity — no gradient-stop interpolation, no JS frame loop. The visual reads as ambient depth because two or more colored blobs slide past each other on different cycle lengths, occasionally overlapping for a brighter hot spot. Foreground content stays anchored on a legibility surface so the aurora never compromises reading contrast.
When to use it
Reach for aurora drift on hero sections, marketing surfaces, and dashboard headers that want depth without competing for reading attention. Skip it under any layout where the user needs to focus on dense text or fine UI — the constant motion in peripheral vision is exhausting. Skip it for the body of a documentation page; reserve ambient motion for above the fold or behind a hero card.
How it works
Each aurora layer is an absolutely-positioned <span> at inset: -34% so the radial gradient extends past the parent and never reveals a hard edge. The layer animates a translate3d + rotate + scale keyframe with ease-in-out infinite alternate, so the layer breathes back and forth instead of looping with a visible seam. Two layers on offset cycle durations (e.g. 8.6s and 10.4s) drift independently, which is what makes the brighter overlap moments feel non-repeating.
The important production distinction is that the radial-gradient() itself does not animate. The browser only moves a pre-painted layer with transform, while opacity controls how strongly each aurora color field blends into the surface. That keeps the animated aurora background closer to compositor work than paint work, which is the difference between a calm hero effect and a janky gradient demo.
Production gotchas
filter: blur() on the aurora layer is GPU-cheap but creates a stacking context that traps mix-blend-mode from siblings — the legibility surface on top should sit in a different stacking context or the blend will look wrong. Layers at inset: -34% need an overflow: hidden parent or the gradient bleeds out of the card on subpixel scrolls. On low-end devices the Gaussian blur on multiple layers can drop frames; the pattern runs cleanly because the blobs animate transform-only, but if you add a third layer keep the blur radius under 28px.
Accessibility
Ambient motion is one of the textbook vestibular triggers, so the prefers-reduced-motion: reduce branch freezes the layer transforms at their rest position. Foreground content is the only thing screen readers see; the layers are aria-hidden="true" and pointer-events: none.
References