Mesh gradient
Gradients · Pure CSS
A soft mesh gradient: four large pools of token colour blend into one another across the page and drift very slowly, as if the colour were breathing. Smooth everywhere, with no edges or stripes, like a modern app splash screen.
✓ (1×) · claude-haiku-5-5 → claude-opus-5-5# Build the "Mesh gradient" background effect (`mesh-gradient`) Family: Gradients · pure CSS. Four soft pools of colour blend into each other and drift slowly. ## Look A soft mesh gradient: four large pools of token colour blend into one another across the page and drift very slowly, as if the colour were breathing. Smooth everywhere, with no edges or stripes, like a modern app splash screen. ## Parameters (current values) - Speed `--fx-speed`: 0.5 (range 0.1–2) - Intensity `--fx-intensity`: 0.8 (range 0.2–1) - Colour A `--fx-color-a`: the `primary` colour token, `var(--c-primary)` - Colour B `--fx-color-b`: the `secondary` colour token, `var(--c-secondary)` - Colour C `--fx-color-c`: the `accent` colour token, `var(--c-accent)` - Background `--fx-color-bg`: the `bg` colour token, `var(--c-bg)` ## Recipe - The element: `background-color: var(--fx-color-bg)`. Let `mix(X)` stand for `color-mix(in srgb, var(--fx-color-X) calc(var(--fx-intensity) * 100%), transparent)`. - `::before` (`content: ''; position: absolute; inset: -25%`, oversized so drifting never shows an edge): `background: radial-gradient(40% 50% at 22% 28%, mix(a), transparent 70%), radial-gradient(45% 45% at 78% 22%, mix(b), transparent 70%), radial-gradient(50% 55% at 70% 78%, mix(c), transparent 70%), radial-gradient(40% 40% at 26% 78%, mix(b), transparent 70%)`. - `::after` (same box, `opacity: 0.6`): two more pools, `radial-gradient(35% 40% at 50% 50%, mix(c), transparent 70%)` and `radial-gradient(30% 35% at 85% 60%, mix(a), transparent 70%)`. - Inside `@media (prefers-reduced-motion: no-preference)`: `::before` runs keyframes `fx-mesh-drift` (0% `transform: translate(0, 0) rotate(0deg) scale(1)`; 50% `translate(4%, -3%) rotate(8deg) scale(1.06)`; 100% `translate(-3%, 4%) rotate(-6deg) scale(0.98)`) for `calc(30s / var(--fx-speed))`, `ease-in-out`, `infinite alternate`; `::after` runs the same keyframes for `calc(42s / var(--fx-speed))` in `alternate-reverse`. - Animate only `transform` (never `background-position` or the gradients) so it stays cheap. ## CSS fallback It is pure CSS: the still state, before the animation moves, is the whole effect. ## Runtime rules - Mount it in one element that fills a fixed, `pointer-events: none`, `aria-hidden` layer behind the page content; every parameter above is a CSS custom property on that element. - Colours come only from the colour-token variables above (mix them with `color-mix()` or alpha), never hard-coded hex, so the effect follows any palette and light or dark mode. - CSS only: gradients, `mask`, pseudo-elements and inline `data:image/svg+xml` (no `<script>` or `<image>` inside it). No images, remote URLs, `@import` or JavaScript. Keep it under ~8 KB. - Animate only inside `@media (prefers-reduced-motion: no-preference)`, with durations divided by `--fx-speed` (for example `calc(24s / var(--fx-speed))`). The still state, before any animation runs, must look complete: it is what reduced motion and screenshots (a `?shot` URL flag) show. ## Avoid - Hard colour stops or visible gradient edges - More than three hues plus the background - Fast motion: one drift cycle under 15 seconds at speed 1 - CSS `filter: blur()` on the large layers (slow on phones)
Copied!