# Aurora Gradient Field

> A vivid mesh-gradient background of drifting colour with a bright lead bloom and a slower halo that follow the cursor across the page, built without canvas or WebGL.

Canonical: https://gsapvault.com/effects/aurora-gradient-field
Live demo: https://gsapvault.com/demos/aurora-gradient-field/index.html

| Property | Value |
|----------|-------|
| Type | effect |
| Tier | paid |
| Price | £5 |
| Difficulty | intermediate |
| Plugins | Core GSAP only |
| Techniques | gradient, ambient, organic-motion, mouse-follow, quickTo, token-theming, pointer-effects |
| Uses Lenis | No |

## Overview

An ambient aurora background built entirely from layered CSS radial gradients. Six colour stops drift on their own slow, non-harmonic cycles so the field never visibly repeats, and a wide conic sweep turns behind them like a curtain of light.

A bright bloom follows the cursor around the page, arriving about a third of a second behind it, while a much wider halo follows at nearly twice the delay. That separation leaves a visible wake across the field instead of a single light welded to the pointer. The two gradient layers also lean toward the cursor by different amounts, which is what turns a flat wash into depth.

Four palettes cross-fade through a dip rather than cutting, and every one of them is a set of CSS hue tokens the script never reads, so your own palette is a copied block and six numbers.

The legibility treatment is local, not global: a feathered band of shade sits behind the reading column only, so the field runs at full strength everywhere the copy is not, and body text still measures above 5.9:1 against every palette.

There is no canvas and no WebGL, so it runs on anything and costs a fraction of a shader background.

## Features

- Pure CSS gradient field driven by custom properties, no canvas and no WebGL
- Dual cursor light driven by gsap.quickTo: a compact bright lead bloom and a wide halo following at nearly twice the delay, both bound to the window so overlaid content never swallows movement
- Six drifting colour stops on non-harmonic cycles, so the loop is never visible
- Two gradient layers that lean toward the pointer by different amounts and in opposite directions, for parallax depth without a second asset
- Conic aurora sweep turning slowly behind the stops, which is what stops the field reading as a static wash
- Local contrast treatment: a feathered band of shade behind the reading column instead of a scrim over the whole canvas, so the field stays vivid in the margins while body text holds AA
- Four palettes included, defined purely as CSS hue tokens plus optional lightness and saturation offsets that you can copy and re-point
- Palette controls that dip the field through the change so new hues fade in instead of cutting, with the fade timeline managed so overlapping presses cannot strand it dim
- Fine grain layer that dithers the ramps and kills the banding large gradients suffer from
- Gradient writes throttled while transforms stay at full frame rate, and the field pauses off screen or in a hidden tab
- A tap equivalent on touch and a composed still under reduced motion

## Use Cases

- Hero and landing page backgrounds that need depth without a heavy asset
- SaaS and product sites where the background must stay behind readable copy
- Section backdrops, footers and call-to-action bands that would otherwise be flat colour
- Login, pricing and coming-soon pages that want atmosphere with almost no payload
- Dark interfaces that need ambient colour on low-power devices where WebGL is a bad trade

## Vibe-Code Ready Setup

This effect includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

Each layer paints a stack of radial gradients whose stop positions, radii and light values are CSS custom properties. A gsap.ticker advances one parametric clock and writes those properties, so every stop moves on its own sine with an unrelated frequency and phase.

Pointer position drives two bloom layers through gsap.quickTo: the bright core follows at 0.32 seconds and the larger echo at 1.9 times that delay. Both move as offsets from the centre where CSS already parks them, so their resting state is correct before any script runs. The listener is on the window rather than the field, because the field is a background with the page's content stacked over it. The same pointer value lerps into the two layers' transforms, leaning them opposite ways for depth.

The field's light values are written every pass but held flat: only the hue drifts. That is what lets the reading band be measured once and stay correct, rather than needing a contrast check at a peak that is easy to forget.

A palette press runs a single timeline that dips the layers' opacity, swaps the palette attribute at the bottom of the dip and fades back up. There is exactly one of these at a time and it is killed before a new one is built, because two overlapping dips can otherwise leave the field almost invisible with nothing scheduled to restore it.

Every value written to a custom property is clamped and checked for finiteness first, because a non-finite number silently invalidates the declaration that reads it and takes the whole gradient with it.

An IntersectionObserver and a visibilitychange listener remove the ticker when the field is off screen or the tab is hidden. Under reduced motion the script paints a single composed frame, attaches no ticker or pointer listeners, and keeps palette controls operable with an instant colour change.

## Integration Preview

How this effect integrates into a page. The full documentation (examples, events, programmatic API, customization guide) ships with the download.

### Quick Start

**1. Add to your HTML `<head>`:**

```html
<link rel="stylesheet" href="path/to/style.css">
```

**2. Add the field to your `<body>`:**

```html
<div class="hero" data-aurora data-aurora-palette="aurora">
  <div data-aurora-layer="1" aria-hidden="true"></div>
  <div data-aurora-layer="2" aria-hidden="true"></div>
  <div data-aurora-sweep aria-hidden="true"></div>
  <div data-aurora-echo aria-hidden="true"></div>
  <div data-aurora-focus aria-hidden="true"></div>
  <div data-aurora-grain aria-hidden="true"></div>
  <div data-aurora-scrim aria-hidden="true"></div>
  <div data-aurora-readband aria-hidden="true"></div>

  <!-- Your own content, in a positioned wrapper above the field -->
  <div class="hero__content">
    <h1>Light that never sits still</h1>
    <p>Your lede.</p>
  </div>
</div>
```

**3. Add before the closing `</body>` tag:**

```html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script src="path/to/script.js"></script>
```

The script finds every `[data-aurora]` element, writes custom properties onto it and its layers on a shared ticker, drives the bloom with `gsap.quickTo`, and stops entirely when the field scrolls off screen or the tab is hidden. It needs no GSAP plugins.

**Pointer tracking is bound to `window`, not to the field.** This is deliberate and it is what makes the effect usable as a page background: if the listener sat on the element, every paragraph, link and button stacked on top of the field would swallow the movement and the light would only follow the cursor over the gaps between your content.

### Options

Set these on the `[data-aurora]` element.

| Attribute | Values | Default | Description |
|---|---:|---:|---|
| `data-aurora` | marker | required | Identifies a field |
| `data-aurora-palette` | `aurora`, `tide`, `dusk`, `ember`, or your own | none | Selects a palette block in the CSS |
| `data-aurora-speed` | number | `1` | Drift rate. `0.5` is barely-there ambience, `2` is restless |
| `data-aurora-intensity` | number | `1` | Scales how far the stops travel on their drift |
| `data-aurora-parallax` | pixels | `48` | How far the layers lean toward the pointer. `0` disables the lean |
| `data-aurora-follow` | seconds | `0.32` | How long the bloom takes to reach the pointer. Below about `0.15` it is welded to the cursor and reads as a sprite; past about `0.5` the connection to your hand is gone |

Child hooks:

| Attribute | Where | Description |
|---|---|---|
| `data-aurora-layer="1"` / `"2"` | inside the field | A gradient stop stack. The number selects which three hues it uses |
| `data-aurora-sweep` | inside the field | The rotating conic aurora band |
| `data-aurora-focus` | inside the field | The compact lead bloom that follows the pointer |
| `data-aurora-echo` | inside the field | The wider trailing halo, following at 1.9 times the configured delay |
| `data-aurora-grain` | inside the field | The anti-banding noise tile |
| `data-aurora-scrim` | inside the field | The light whole-surface veil that seats the field on a dark page |
| `data-aurora-readband` | inside the field | The feathered band of shade behind the reading column. Set `--a-read` to your measure |
| `data-aurora-palette-control="name"` | anywhere | Swaps the palette, fading the field through the change |
| `data-aurora-target="field-id"` | on a control | Points a control at a field it does not live inside |

### Accessibility

- **Reduced motion**: under `prefers-reduced-motion: reduce` the script paints one composed frame and attaches no ticker or pointer listeners. Palette buttons remain operable and change the still instantly, without the cross-fade dip.
- **Without JavaScript**: the CSS carries a complete resting state, so the field paints in full. Nothing on the page is hidden waiting for a script.
- **Contrast**: the field's light values are held flat, so the reading band can be tuned once. Measured per real glyph pixel across all four palettes, white copy over the field stays at or above 5.9:1, comfortably past the 4.5:1 AA threshold. Text that runs outside the band needs its own patch; see "Putting text over the field" above.
- **Keyboard**: the palette controls are ordinary buttons carrying `aria-pressed`, so the only interactive part of the effect is reachable and announced.
- **Touch**: a coarse pointer has no hover, so a tap or a drag places the bloom where the finger landed.
- **Decorative by definition**: every layer carries `aria-hidden="true"` and `pointer-events: none`. Nothing the effect adds is announced or focusable.

### Dependencies

- **GSAP 3.14.2** (core only, no plugins)

### Browser Support

Uses modern `hsl()` slash-alpha syntax, `conic-gradient`, `mix-blend-mode` and `background-blend-mode`: current Chrome, Safari, Firefox and Edge. Older engines fall back to the field's base colour, which is a solid dark ground rather than a broken layout.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium effect. The standard license costs £5 one-time and covers unlimited personal and commercial projects with no attribution required. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Aurora Gradient Field](https://gsapvault.com/effects/aurora-gradient-field)
- [Effects & Templates Vault (£39 one-time, best value): every current and future effect and template](https://gsapvault.com/effects)

## Judge the Code Quality First

These related effects are free with complete source published, written to the same production standard (cleanup functions, reduced-motion support, framework-agnostic):

- [Parallax Hero](https://gsapvault.com/effects/parallax-hero.md): A pinned hero that separates its background photograph, copy, and foreground card into distinct scroll depths from a single scrubbed ScrollTrigger.

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
