---
name: aurora-background
description: Use when you want "Dreamy, premium, futuristic" - Simulates northern-light waves and glowing color fields.
---

# Aurora Background

> **Category:** Background  -  **Personality:** Dreamy, premium, futuristic
>
> **Best use:** AI websites, hero sections
>
> **Ratings:** Professional 4/5 - Casual 4/5 - Exotic 5/5 - Visual impact 5/5 - Difficulty 4/5 - Performance cost 4/5

## What it is

An aurora background fakes the northern lights: soft, luminous ribbons of green, teal, violet and magenta that drift and shimmer across a deep night sky. It is built entirely from large, heavily-blurred gradient shapes (one rotating **conic** field, a few **linear** "curtains", and a couple of **radial** glow pools) that are composited with `mix-blend-mode: screen` so wherever they overlap they brighten like real light, then nudged around forever with `@keyframes`. Because nothing is ever a flat fill — the hue is always rotating and the curtains are always waving — it reads as living *atmosphere* rather than a static gradient. That dreamy, premium quality is exactly why it has become the signature backdrop for AI product heroes.

## Dependencies / CDN

**None - pure CSS.** The demo only loads two display/body fonts (Syne for headings, Manrope for body), which are optional:

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet">
```

## HTML

Background layers first (sky → stars → aurora → scrim → grain), then your content on top:

```html
<div class="au-stage">
  <!-- background -->
  <div class="au-sky" aria-hidden="true"></div>
  <div class="au-stars" aria-hidden="true"></div>
  <div class="au-aurora" aria-hidden="true">
    <span class="au-cone"></span>
    <span class="au-band au-b1"></span>
    <span class="au-band au-b2"></span>
    <span class="au-band au-b3"></span>
    <span class="au-glow au-g1"></span>
    <span class="au-glow au-g2"></span>
  </div>
  <div class="au-scrim" aria-hidden="true"></div>
  <div class="au-grain" aria-hidden="true"></div>

  <!-- foreground: an AI product hero -->
  <div class="au-content">
    <div class="au-hero">
      <span class="au-eyebrow"><span class="au-ping"></span>Introducing Polaris&nbsp;2.0</span>
      <h1 class="au-h">Intelligence that<br>moves like <em>light</em>.</h1>
      <p class="au-sub">Polaris turns a single prompt into production-ready software.</p>
      <form class="au-prompt" onsubmit="return false">
        <span class="au-prompt-ic">&#10022;</span>
        <input class="au-input" type="text" placeholder="Describe what you want to build&hellip;">
        <button class="au-gen" type="submit">Generate</button>
      </form>
    </div>
  </div>
</div>
```

## CSS

This is the whole background system, verbatim. (Foreground typography — `.au-content/.au-hero/.au-h/.au-prompt` etc. — is omitted; style it however you like.)

```css
/* The stage MUST clip + isolate so the screen-blend stays inside it */
.au-stage{position:relative;border-radius:28px;overflow:hidden;min-height:660px;display:flex;
  background:#04060e;isolation:isolate;font-family:'Manrope',system-ui,sans-serif}

/* 1) deep night sky — the dark base that the light builds up on */
.au-sky{position:absolute;inset:0;z-index:0;
  background:radial-gradient(125% 95% at 50% -20%,#16224d 0%,#0b1230 34%,#06091a 68%,#03040b 100%)}

/* 2) faint starfield (one tiny dot per radial-gradient) */
.au-stars{position:absolute;inset:0;z-index:1;opacity:.55;animation:au-twinkle 7s ease-in-out infinite;
  background-repeat:no-repeat;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 18%,rgba(255,255,255,.9),transparent),
    radial-gradient(1px 1px at 28% 32%,rgba(202,225,255,.8),transparent),
    radial-gradient(1.6px 1.6px at 63% 26%,rgba(220,235,255,.85),transparent),
    radial-gradient(1.2px 1.2px at 88% 30%,rgba(255,255,255,.8),transparent),
    radial-gradient(1px 1px at 54% 40%,rgba(210,230,255,.7),transparent),
    radial-gradient(1.3px 1.3px at 70% 48%,rgba(255,255,255,.6),transparent)}

/* 3) the aurora — every layer paints with screen so overlaps glow */
.au-aurora{position:absolute;inset:0;z-index:2;overflow:hidden;
  transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.au-band,.au-glow,.au-cone{position:absolute;mix-blend-mode:screen;will-change:transform,opacity}

/* rotating conic hue-field — keeps the colour ever-shifting (never a flat gradient) */
.au-cone{top:-70%;left:50%;width:150%;height:170%;transform:translateX(-50%);
  background:conic-gradient(from 210deg at 50% 38%,
    rgba(46,233,170,0) 0deg,rgba(46,233,170,.34) 55deg,rgba(34,211,238,.30) 120deg,
    rgba(124,92,255,.34) 205deg,rgba(232,121,249,.26) 275deg,rgba(46,233,170,0) 360deg);
  filter:blur(72px);opacity:.6;animation:au-rotate 42s linear infinite}

/* three waving curtains of light (transparent → colour → transparent, then skewed) */
.au-b1{top:-28%;left:2%;width:58%;height:120%;
  background:linear-gradient(102deg,transparent 0 28%,rgba(56,233,176,.55) 46%,rgba(34,211,238,.4) 64%,transparent 82% 100%);
  filter:blur(56px);transform:rotate(-11deg) skewX(-13deg);animation:au-wave1 17s ease-in-out infinite}
.au-b2{top:-32%;left:28%;width:54%;height:128%;
  background:linear-gradient(96deg,transparent 0 30%,rgba(34,211,238,.5) 48%,rgba(124,92,255,.42) 66%,transparent 84% 100%);
  filter:blur(58px);transform:rotate(7deg) skewX(10deg);animation:au-wave2 21s ease-in-out infinite}
.au-b3{top:-26%;right:0%;width:52%;height:118%;
  background:linear-gradient(110deg,transparent 0 26%,rgba(124,92,255,.46) 46%,rgba(232,121,249,.4) 66%,transparent 84% 100%);
  filter:blur(54px);transform:rotate(-6deg) skewX(-9deg);animation:au-wave3 19s ease-in-out infinite}

/* luminous colour pools near the horizon */
.au-g1{bottom:-22%;left:-6%;width:62%;height:72%;
  background:radial-gradient(circle at 50% 50%,rgba(56,233,176,.42),transparent 64%);
  filter:blur(52px);animation:au-pulse 12s ease-in-out infinite}
.au-g2{bottom:-26%;right:-8%;width:66%;height:78%;
  background:radial-gradient(circle at 50% 50%,rgba(140,92,255,.4),rgba(232,121,249,.18) 42%,transparent 68%);
  filter:blur(56px);animation:au-pulse 15s ease-in-out infinite reverse}

/* 4) darken scrim (for text contrast) + film grain (for premium texture) */
.au-scrim{position:absolute;inset:0;z-index:3;pointer-events:none;
  background:
    radial-gradient(115% 70% at 50% 84%,rgba(3,5,12,.6) 0%,transparent 56%),
    linear-gradient(180deg,rgba(3,5,12,.55) 0%,transparent 20%,transparent 58%,rgba(3,5,12,.62) 100%)}
.au-grain{position:absolute;inset:0;z-index:4;pointer-events:none;opacity:.06;mix-blend-mode:overlay;
  background-size:160px 160px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

.au-content{position:relative;z-index:5} /* your hero sits on top */

/* drift / rotate / pulse — animate transform & opacity ONLY, never the blur radius */
@keyframes au-rotate{to{transform:translateX(-50%) rotate(360deg)}}
@keyframes au-wave1{0%,100%{transform:rotate(-11deg) skewX(-13deg) translate3d(0,0,0) scaleY(1);opacity:.82}
  50%{transform:rotate(-6deg) skewX(-21deg) translate3d(7%,-3%,0) scaleY(1.07);opacity:1}}
@keyframes au-wave2{0%,100%{transform:rotate(7deg) skewX(10deg) translate3d(0,0,0) scaleY(1);opacity:.8}
  50%{transform:rotate(3deg) skewX(18deg) translate3d(-6%,-4%,0) scaleY(1.1);opacity:1}}
@keyframes au-wave3{0%,100%{transform:rotate(-6deg) skewX(-9deg) translate3d(0,0,0) scaleY(1);opacity:.85}
  50%{transform:rotate(-10deg) skewX(-2deg) translate3d(5%,-2%,0) scaleY(1.06);opacity:1}}
@keyframes au-pulse{0%,100%{opacity:.65;transform:scale(1)}50%{opacity:1;transform:scale(1.13)}}
@keyframes au-twinkle{0%,100%{opacity:.4}50%{opacity:.72}}

/* freeze every moving layer for reduced-motion users */
@media(prefers-reduced-motion:reduce){
  .au-band,.au-glow,.au-cone,.au-stars,.au-ping{animation:none}
  .au-aurora{transition:none}}
```

## JavaScript

Not required — the aurora is pure CSS. The demo only adds two optional, `prefers-reduced-motion`-gated touches: a gentle pointer-parallax on the aurora (depth) and a typewriter placeholder in the prompt (AI-hero flavour).

```js
(function(){
  var stage=document.querySelector('.au-stage'),
      aurora=document.querySelector('.au-aurora'),
      input=document.querySelector('.au-input'),
      form=document.querySelector('.au-prompt');

  if(form)form.addEventListener('submit',function(e){e.preventDefault();}); // demo only

  if(window.matchMedia&&matchMedia('(prefers-reduced-motion: reduce)').matches)return;

  /* 1) parallax: drift the aurora a few px counter to the pointer */
  if(stage&&aurora){
    stage.addEventListener('pointermove',function(e){
      var r=stage.getBoundingClientRect();
      var dx=((e.clientX-r.left)/r.width-.5)*-18,
          dy=((e.clientY-r.top)/r.height-.5)*-12;
      aurora.style.transform='translate3d('+dx.toFixed(1)+'px,'+dy.toFixed(1)+'px,0)';
    });
    stage.addEventListener('pointerleave',function(){aurora.style.transform='translate3d(0,0,0)';});
  }

  /* 2) cycle example prompts through the placeholder */
  if(input){
    var ideas=['a SaaS dashboard with auth and billing…','an iOS app for tracking houseplants…',
      'a landing page for a synthwave label…','a Slack bot that summarises standups…'];
    var i=0,c=0,del=false;
    (function tick(){
      if(document.activeElement===input||input.value){return setTimeout(tick,500);} // pause while typing
      var t=ideas[i];
      c+=del?-1:1;
      input.setAttribute('placeholder',t.slice(0,c)+'▏');
      if(!del&&c>=t.length){del=true;return setTimeout(tick,1500);}
      if(del&&c<=0){del=false;i=(i+1)%ideas.length;return setTimeout(tick,320);}
      setTimeout(tick,del?26:52);
    })();
  }
})();
```

## How it works

- **A dark base + `mix-blend-mode: screen` = light.** Screen never darkens, only adds, so each translucent gradient *brightens* the night sky and overlapping layers brighten each other — exactly how real aurora light stacks. On a light background it would do nothing.
- **Big `filter: blur()` is what turns shapes into "aurora".** A 50–70px blur dissolves the hard edges of each gradient into soft, flowing bands. The shapes are deliberately oversized (and pushed past the edges with negative offsets) so the blur never reveals a boundary.
- **Three gradient *types*, three jobs.** A slowly **rotating conic** gradient is the secret to never looking flat — it sweeps the hue around continuously. **Linear** gradients (transparent → colour → transparent, then `skewX`-ed) read as hanging *curtains*. **Radial** pools sit on the horizon as glowing colour fields.
- **`@keyframes` animate transform & opacity only.** Each curtain rotates/skews/translates/pulses on its own slightly-different duration, so they drift out of sync and the whole field feels organic. The blur radius is *never* animated (see performance).
- **`isolation: isolate` on the stage** gives the screen-blend a private group to composite in, so the light builds up over the sky *inside* the panel instead of bleeding onto the page behind it.
- **A scrim restores legibility.** A radial+linear dark overlay above the aurora dims the zone behind the headline so white text stays readable over the bright bands; a faint SVG grain on top kills banding and adds a premium film texture.

## Customization

- **Palette:** swap the `rgba()` hues in `.au-cone`, `.au-b1/2/3`, `.au-g1/2`. Greens/teals/violets/magenta = classic aurora; try cyan/blue/indigo for "deep space", or amber/rose for a warm dawn.
- **Intensity:** raise the colour alphas (`.4` → `.6`) and `.au-cone` opacity for a vivid hero; lower them for a whisper-quiet section background.
- **Calm vs. energetic:** lengthen the `au-wave*` / `au-rotate` durations for a slow, meditative drift; shorten them for a more alive feel.
- **Softness:** more `blur()` = dreamier and more diffuse; less = sharper, more "ribbon-like" curtains.
- **Placement:** keep the bands up top (as here) so the aurora hangs in the "sky" and the lower half stays dark for text — or center them to wrap the headline in light.

## Accessibility & performance

- **Respect `prefers-reduced-motion`:** the demo freezes every band, glow, the conic and the parallax. Frozen, it's still a beautiful static aurora.
- **Blur is the cost.** Large `filter: blur()` on several big, animated layers is GPU-heavy. Keep the layer count modest, add `will-change: transform, opacity`, and **never animate the blur radius** — that forces a re-rasterise every frame. Animate `transform`/`opacity` instead (cheap, compositor-only).
- **Contrast:** bright aurora + white text can fail WCAG. The dark scrim behind the copy is not optional — verify text contrast over the *brightest* frame of the animation.
- **Decorative:** all background layers are `aria-hidden="true"` and `pointer-events:none` where appropriate, so they never reach the accessibility tree or steal clicks.

## Gotchas

- **`mix-blend-mode: screen` needs an isolation context.** Without `isolation: isolate` (or another stacking context) on the stage, the bands blend against whatever is *behind the whole component* on the page and the effect looks wrong. The dark base must live inside that same context.
- **No dark base = no effect.** Screen over a light/white background produces ~white. The aurora only exists because it sits over a near-black sky.
- **`overflow: hidden` + `border-radius` on the stage** is required — the oversized, blurred bands extend well past the panel and must be clipped to the rounded frame.
- **A `transform` on the blurred layer creates a stacking context** (the parallax does this). That's fine here, but be aware it changes the scope the screen-blend composites in — keep the dark sky and the aurora in a predictable order.
- **`backdrop-filter` on the glass prompt bar needs the `-webkit-` prefix** for Safari/iOS, or it silently does nothing.
- **Mobile:** the same blur stack can jank on low-end phones. Consider dropping a curtain or two, or reducing the blur radius under a `max-width` media query.
