18 CSS Gradient UI07 / 18
Animated Mesh / Aurora Gradient Background
A full-viewport aurora built from four drifting radial-gradient blobs, a conic wash and a film-grain overlay — the mesh-gradient look every 2026 landing page wants, hand-written in ~40 lines of CSS with no generator and no canvas.
Published
The code
<div class="cgu-07-group">
<section class="cgu-07" aria-label="Animated mesh aurora gradient background demo">
<div class="cgu-07__sky" aria-hidden="true"></div>
<div class="cgu-07__grain" aria-hidden="true"></div>
<div class="cgu-07__content">
<p class="cgu-07__eyebrow">07 · Mesh / aurora background</p>
<h2 class="cgu-07__title">Four blobs.<br>One aurora.</h2>
<p class="cgu-07__sub">This entire sky is four radial-gradients on a slowly drifting layer — no canvas, no WebGL, no generator export. View source; it fits on a screen.</p>
<div class="cgu-07__row">
<button class="cgu-07__btn" type="button">Copy the CSS</button>
<button class="cgu-07__btn cgu-07__btn--ghost" type="button">Read the technique</button>
</div>
<dl class="cgu-07__stats">
<div class="cgu-07__stat"><dt>Layers</dt><dd>4 + grain</dd></div>
<div class="cgu-07__stat"><dt>JavaScript</dt><dd>0 bytes</dd></div>
<div class="cgu-07__stat"><dt>Repaints</dt><dd>compositor-only</dd></div>
</dl>
</div>
</section>
</div><div class="cgu-07-group">
<section class="cgu-07" aria-label="Animated mesh aurora gradient background demo">
<div class="cgu-07__sky" aria-hidden="true"></div>
<div class="cgu-07__grain" aria-hidden="true"></div>
<div class="cgu-07__content">
<p class="cgu-07__eyebrow">07 · Mesh / aurora background</p>
<h2 class="cgu-07__title">Four blobs.<br>One aurora.</h2>
<p class="cgu-07__sub">This entire sky is four radial-gradients on a slowly drifting layer — no canvas, no WebGL, no generator export. View source; it fits on a screen.</p>
<div class="cgu-07__row">
<button class="cgu-07__btn" type="button">Copy the CSS</button>
<button class="cgu-07__btn cgu-07__btn--ghost" type="button">Read the technique</button>
</div>
<dl class="cgu-07__stats">
<div class="cgu-07__stat"><dt>Layers</dt><dd>4 + grain</dd></div>
<div class="cgu-07__stat"><dt>JavaScript</dt><dd>0 bytes</dd></div>
<div class="cgu-07__stat"><dt>Repaints</dt><dd>compositor-only</dd></div>
</dl>
</div>
</section>
</div>.cgu-07-group {
display: block;
width: 100%;
}
.cgu-07,
.cgu-07 *,
.cgu-07 *::before,
.cgu-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgu-07 {
position: relative;
isolation: isolate;
overflow: hidden;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 64px 24px;
font-family: 'Segoe UI',system-ui,sans-serif;
color: #f2f1ff;
background: #07060d;
}
.cgu-07__sky {
position: absolute;
inset: -25%;
z-index: -2;
background: radial-gradient(38% 42% at 20% 25%,oklch(0.6 0.24 300 / .85),transparent 68%),radial-gradient(34% 38% at 78% 20%,oklch(0.7 0.19 200 / .8),transparent 66%),radial-gradient(40% 44% at 70% 78%,oklch(0.65 0.23 345 / .7),transparent 70%),radial-gradient(36% 40% at 25% 80%,oklch(0.72 0.17 150 / .55),transparent 68%),conic-gradient(from 200deg at 50% 50%,#0b0817,#120f22,#0b0817);
filter: blur(42px) saturate(1.15);
animation: cgu07-drift 60s ease-in-out infinite alternate;
}
.cgu-07__grain {
position: absolute;
inset: 0;
z-index: -1;
opacity: .16;
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.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}
.cgu-07__content {
position: relative;
width: min(680px,100%);
text-align: center;
display: grid;
gap: 20px;
justify-items: center;
}
.cgu-07__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .28em;
text-transform: uppercase;
color: rgba(242,241,255,.75);
}
.cgu-07__title {
font-size: clamp(40px,7vw,84px);
font-weight: 850;
letter-spacing: -.03em;
line-height: 1.0;
text-wrap: balance;
text-shadow: 0 2px 40px rgba(0,0,0,.45);
}
.cgu-07__sub {
max-width: 52ch;
font-size: 16px;
line-height: 1.65;
color: rgba(242,241,255,.82);
text-wrap: pretty;
}
.cgu-07__row {
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
margin-top: 6px;
}
.cgu-07__btn {
font: inherit;
font-size: 15px;
font-weight: 700;
color: #12081f;
padding: 14px 30px;
border: none;
border-radius: 9999px;
cursor: pointer;
background: linear-gradient(120deg,#f0e7ff,#dcd0ff);
transition: transform .3s,box-shadow .3s;
box-shadow: 0 14px 34px -14px rgba(220,208,255,.5);
}
.cgu-07__btn:hover,
.cgu-07__btn:focus-visible {
transform: translateY(-2px);
box-shadow: 0 20px 40px -14px rgba(220,208,255,.65);
}
.cgu-07__btn--ghost {
color: #f2f1ff;
background: rgba(255,255,255,.08);
box-shadow: inset 0 0 0 1px rgba(255,255,255,.28);
}
.cgu-07__btn--ghost:hover,
.cgu-07__btn--ghost:focus-visible {
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
}
.cgu-07__btn:focus-visible {
outline: 3px solid #fff;
outline-offset: 3px;
}
.cgu-07__stats {
display: flex;
gap: 34px;
flex-wrap: wrap;
justify-content: center;
margin-top: 20px;
}
.cgu-07__stat {
display: grid;
gap: 3px;
}
.cgu-07__stat dt {
font-size: 11px;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: rgba(242,241,255,.55);
}
.cgu-07__stat dd {
font-size: 17px;
font-weight: 750;
}
@keyframes cgu07-drift {
0% {
transform: translate(0,0) rotate(0deg) scale(1);
}
50% {
transform: translate(4%,-3%) rotate(6deg) scale(1.06);
}
100% {
transform: translate(-4%,3%) rotate(-5deg) scale(1.02);
}
}
@media (prefers-reduced-motion: reduce) {
.cgu-07__sky {
animation: none;
}
.cgu-07__btn {
transition: box-shadow .2s;
}
}.cgu-07-group {
display: block;
width: 100%;
}
.cgu-07,
.cgu-07 *,
.cgu-07 *::before,
.cgu-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgu-07 {
position: relative;
isolation: isolate;
overflow: hidden;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 64px 24px;
font-family: 'Segoe UI',system-ui,sans-serif;
color: #f2f1ff;
background: #07060d;
}
.cgu-07__sky {
position: absolute;
inset: -25%;
z-index: -2;
background: radial-gradient(38% 42% at 20% 25%,oklch(0.6 0.24 300 / .85),transparent 68%),radial-gradient(34% 38% at 78% 20%,oklch(0.7 0.19 200 / .8),transparent 66%),radial-gradient(40% 44% at 70% 78%,oklch(0.65 0.23 345 / .7),transparent 70%),radial-gradient(36% 40% at 25% 80%,oklch(0.72 0.17 150 / .55),transparent 68%),conic-gradient(from 200deg at 50% 50%,#0b0817,#120f22,#0b0817);
filter: blur(42px) saturate(1.15);
animation: cgu07-drift 60s ease-in-out infinite alternate;
}
.cgu-07__grain {
position: absolute;
inset: 0;
z-index: -1;
opacity: .16;
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.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}
.cgu-07__content {
position: relative;
width: min(680px,100%);
text-align: center;
display: grid;
gap: 20px;
justify-items: center;
}
.cgu-07__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .28em;
text-transform: uppercase;
color: rgba(242,241,255,.75);
}
.cgu-07__title {
font-size: clamp(40px,7vw,84px);
font-weight: 850;
letter-spacing: -.03em;
line-height: 1.0;
text-wrap: balance;
text-shadow: 0 2px 40px rgba(0,0,0,.45);
}
.cgu-07__sub {
max-width: 52ch;
font-size: 16px;
line-height: 1.65;
color: rgba(242,241,255,.82);
text-wrap: pretty;
}
.cgu-07__row {
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
margin-top: 6px;
}
.cgu-07__btn {
font: inherit;
font-size: 15px;
font-weight: 700;
color: #12081f;
padding: 14px 30px;
border: none;
border-radius: 9999px;
cursor: pointer;
background: linear-gradient(120deg,#f0e7ff,#dcd0ff);
transition: transform .3s,box-shadow .3s;
box-shadow: 0 14px 34px -14px rgba(220,208,255,.5);
}
.cgu-07__btn:hover,
.cgu-07__btn:focus-visible {
transform: translateY(-2px);
box-shadow: 0 20px 40px -14px rgba(220,208,255,.65);
}
.cgu-07__btn--ghost {
color: #f2f1ff;
background: rgba(255,255,255,.08);
box-shadow: inset 0 0 0 1px rgba(255,255,255,.28);
}
.cgu-07__btn--ghost:hover,
.cgu-07__btn--ghost:focus-visible {
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
}
.cgu-07__btn:focus-visible {
outline: 3px solid #fff;
outline-offset: 3px;
}
.cgu-07__stats {
display: flex;
gap: 34px;
flex-wrap: wrap;
justify-content: center;
margin-top: 20px;
}
.cgu-07__stat {
display: grid;
gap: 3px;
}
.cgu-07__stat dt {
font-size: 11px;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: rgba(242,241,255,.55);
}
.cgu-07__stat dd {
font-size: 17px;
font-weight: 750;
}
@keyframes cgu07-drift {
0% {
transform: translate(0,0) rotate(0deg) scale(1);
}
50% {
transform: translate(4%,-3%) rotate(6deg) scale(1.06);
}
100% {
transform: translate(-4%,3%) rotate(-5deg) scale(1.02);
}
}
@media (prefers-reduced-motion: reduce) {
.cgu-07__sky {
animation: none;
}
.cgu-07__btn {
transition: box-shadow .2s;
}
}/* No JavaScript — four radial-gradient blobs + conic wash on a blurred, slowly-transforming layer; SVG turbulence data-URI supplies the grain. */
/* No JavaScript — four radial-gradient blobs + conic wash on a blurred, slowly-transforming layer; SVG turbulence data-URI supplies the grain. */Here's a working CSS Gradient UI from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Animated Mesh / Aurora Gradient Background
Source: https://codefronts.com/design-styles/css-gradient-ui/animated-mesh-aurora-gradient-background/
A full-viewport aurora built from four drifting radial-gradient blobs, a conic wash and a film-grain overlay — the mesh-gradient look every 2026 landing page wants, hand-written in ~40 lines of CSS with no generator and no canvas.
## HTML
```html
<div class="cgu-07-group">
<section class="cgu-07" aria-label="Animated mesh aurora gradient background demo">
<div class="cgu-07__sky" aria-hidden="true"></div>
<div class="cgu-07__grain" aria-hidden="true"></div>
<div class="cgu-07__content">
<p class="cgu-07__eyebrow">07 · Mesh / aurora background</p>
<h2 class="cgu-07__title">Four blobs.<br>One aurora.</h2>
<p class="cgu-07__sub">This entire sky is four radial-gradients on a slowly drifting layer — no canvas, no WebGL, no generator export. View source; it fits on a screen.</p>
<div class="cgu-07__row">
<button class="cgu-07__btn" type="button">Copy the CSS</button>
<button class="cgu-07__btn cgu-07__btn--ghost" type="button">Read the technique</button>
</div>
<dl class="cgu-07__stats">
<div class="cgu-07__stat"><dt>Layers</dt><dd>4 + grain</dd></div>
<div class="cgu-07__stat"><dt>JavaScript</dt><dd>0 bytes</dd></div>
<div class="cgu-07__stat"><dt>Repaints</dt><dd>compositor-only</dd></div>
</dl>
</div>
</section>
</div>
```
## CSS
```css
.cgu-07-group {
display: block;
width: 100%;
}
.cgu-07,
.cgu-07 *,
.cgu-07 *::before,
.cgu-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgu-07 {
position: relative;
isolation: isolate;
overflow: hidden;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 64px 24px;
font-family: 'Segoe UI',system-ui,sans-serif;
color: #f2f1ff;
background: #07060d;
}
.cgu-07__sky {
position: absolute;
inset: -25%;
z-index: -2;
background: radial-gradient(38% 42% at 20% 25%,oklch(0.6 0.24 300 / .85),transparent 68%),radial-gradient(34% 38% at 78% 20%,oklch(0.7 0.19 200 / .8),transparent 66%),radial-gradient(40% 44% at 70% 78%,oklch(0.65 0.23 345 / .7),transparent 70%),radial-gradient(36% 40% at 25% 80%,oklch(0.72 0.17 150 / .55),transparent 68%),conic-gradient(from 200deg at 50% 50%,#0b0817,#120f22,#0b0817);
filter: blur(42px) saturate(1.15);
animation: cgu07-drift 60s ease-in-out infinite alternate;
}
.cgu-07__grain {
position: absolute;
inset: 0;
z-index: -1;
opacity: .16;
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.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}
.cgu-07__content {
position: relative;
width: min(680px,100%);
text-align: center;
display: grid;
gap: 20px;
justify-items: center;
}
.cgu-07__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .28em;
text-transform: uppercase;
color: rgba(242,241,255,.75);
}
.cgu-07__title {
font-size: clamp(40px,7vw,84px);
font-weight: 850;
letter-spacing: -.03em;
line-height: 1.0;
text-wrap: balance;
text-shadow: 0 2px 40px rgba(0,0,0,.45);
}
.cgu-07__sub {
max-width: 52ch;
font-size: 16px;
line-height: 1.65;
color: rgba(242,241,255,.82);
text-wrap: pretty;
}
.cgu-07__row {
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
margin-top: 6px;
}
.cgu-07__btn {
font: inherit;
font-size: 15px;
font-weight: 700;
color: #12081f;
padding: 14px 30px;
border: none;
border-radius: 9999px;
cursor: pointer;
background: linear-gradient(120deg,#f0e7ff,#dcd0ff);
transition: transform .3s,box-shadow .3s;
box-shadow: 0 14px 34px -14px rgba(220,208,255,.5);
}
.cgu-07__btn:hover,
.cgu-07__btn:focus-visible {
transform: translateY(-2px);
box-shadow: 0 20px 40px -14px rgba(220,208,255,.65);
}
.cgu-07__btn--ghost {
color: #f2f1ff;
background: rgba(255,255,255,.08);
box-shadow: inset 0 0 0 1px rgba(255,255,255,.28);
}
.cgu-07__btn--ghost:hover,
.cgu-07__btn--ghost:focus-visible {
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
}
.cgu-07__btn:focus-visible {
outline: 3px solid #fff;
outline-offset: 3px;
}
.cgu-07__stats {
display: flex;
gap: 34px;
flex-wrap: wrap;
justify-content: center;
margin-top: 20px;
}
.cgu-07__stat {
display: grid;
gap: 3px;
}
.cgu-07__stat dt {
font-size: 11px;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: rgba(242,241,255,.55);
}
.cgu-07__stat dd {
font-size: 17px;
font-weight: 750;
}
@keyframes cgu07-drift {
0% {
transform: translate(0,0) rotate(0deg) scale(1);
}
50% {
transform: translate(4%,-3%) rotate(6deg) scale(1.06);
}
100% {
transform: translate(-4%,3%) rotate(-5deg) scale(1.02);
}
}
@media (prefers-reduced-motion: reduce) {
.cgu-07__sky {
animation: none;
}
.cgu-07__btn {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — four radial-gradient blobs + conic wash on a blurred, slowly-transforming layer; SVG turbulence data-URI supplies the grain. */
```Here's a working CSS Gradient UI from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Animated Mesh / Aurora Gradient Background
Source: https://codefronts.com/design-styles/css-gradient-ui/animated-mesh-aurora-gradient-background/
A full-viewport aurora built from four drifting radial-gradient blobs, a conic wash and a film-grain overlay — the mesh-gradient look every 2026 landing page wants, hand-written in ~40 lines of CSS with no generator and no canvas.
## HTML
```html
<div class="cgu-07-group">
<section class="cgu-07" aria-label="Animated mesh aurora gradient background demo">
<div class="cgu-07__sky" aria-hidden="true"></div>
<div class="cgu-07__grain" aria-hidden="true"></div>
<div class="cgu-07__content">
<p class="cgu-07__eyebrow">07 · Mesh / aurora background</p>
<h2 class="cgu-07__title">Four blobs.<br>One aurora.</h2>
<p class="cgu-07__sub">This entire sky is four radial-gradients on a slowly drifting layer — no canvas, no WebGL, no generator export. View source; it fits on a screen.</p>
<div class="cgu-07__row">
<button class="cgu-07__btn" type="button">Copy the CSS</button>
<button class="cgu-07__btn cgu-07__btn--ghost" type="button">Read the technique</button>
</div>
<dl class="cgu-07__stats">
<div class="cgu-07__stat"><dt>Layers</dt><dd>4 + grain</dd></div>
<div class="cgu-07__stat"><dt>JavaScript</dt><dd>0 bytes</dd></div>
<div class="cgu-07__stat"><dt>Repaints</dt><dd>compositor-only</dd></div>
</dl>
</div>
</section>
</div>
```
## CSS
```css
.cgu-07-group {
display: block;
width: 100%;
}
.cgu-07,
.cgu-07 *,
.cgu-07 *::before,
.cgu-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgu-07 {
position: relative;
isolation: isolate;
overflow: hidden;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 64px 24px;
font-family: 'Segoe UI',system-ui,sans-serif;
color: #f2f1ff;
background: #07060d;
}
.cgu-07__sky {
position: absolute;
inset: -25%;
z-index: -2;
background: radial-gradient(38% 42% at 20% 25%,oklch(0.6 0.24 300 / .85),transparent 68%),radial-gradient(34% 38% at 78% 20%,oklch(0.7 0.19 200 / .8),transparent 66%),radial-gradient(40% 44% at 70% 78%,oklch(0.65 0.23 345 / .7),transparent 70%),radial-gradient(36% 40% at 25% 80%,oklch(0.72 0.17 150 / .55),transparent 68%),conic-gradient(from 200deg at 50% 50%,#0b0817,#120f22,#0b0817);
filter: blur(42px) saturate(1.15);
animation: cgu07-drift 60s ease-in-out infinite alternate;
}
.cgu-07__grain {
position: absolute;
inset: 0;
z-index: -1;
opacity: .16;
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.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}
.cgu-07__content {
position: relative;
width: min(680px,100%);
text-align: center;
display: grid;
gap: 20px;
justify-items: center;
}
.cgu-07__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .28em;
text-transform: uppercase;
color: rgba(242,241,255,.75);
}
.cgu-07__title {
font-size: clamp(40px,7vw,84px);
font-weight: 850;
letter-spacing: -.03em;
line-height: 1.0;
text-wrap: balance;
text-shadow: 0 2px 40px rgba(0,0,0,.45);
}
.cgu-07__sub {
max-width: 52ch;
font-size: 16px;
line-height: 1.65;
color: rgba(242,241,255,.82);
text-wrap: pretty;
}
.cgu-07__row {
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
margin-top: 6px;
}
.cgu-07__btn {
font: inherit;
font-size: 15px;
font-weight: 700;
color: #12081f;
padding: 14px 30px;
border: none;
border-radius: 9999px;
cursor: pointer;
background: linear-gradient(120deg,#f0e7ff,#dcd0ff);
transition: transform .3s,box-shadow .3s;
box-shadow: 0 14px 34px -14px rgba(220,208,255,.5);
}
.cgu-07__btn:hover,
.cgu-07__btn:focus-visible {
transform: translateY(-2px);
box-shadow: 0 20px 40px -14px rgba(220,208,255,.65);
}
.cgu-07__btn--ghost {
color: #f2f1ff;
background: rgba(255,255,255,.08);
box-shadow: inset 0 0 0 1px rgba(255,255,255,.28);
}
.cgu-07__btn--ghost:hover,
.cgu-07__btn--ghost:focus-visible {
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
}
.cgu-07__btn:focus-visible {
outline: 3px solid #fff;
outline-offset: 3px;
}
.cgu-07__stats {
display: flex;
gap: 34px;
flex-wrap: wrap;
justify-content: center;
margin-top: 20px;
}
.cgu-07__stat {
display: grid;
gap: 3px;
}
.cgu-07__stat dt {
font-size: 11px;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: rgba(242,241,255,.55);
}
.cgu-07__stat dd {
font-size: 17px;
font-weight: 750;
}
@keyframes cgu07-drift {
0% {
transform: translate(0,0) rotate(0deg) scale(1);
}
50% {
transform: translate(4%,-3%) rotate(6deg) scale(1.06);
}
100% {
transform: translate(-4%,3%) rotate(-5deg) scale(1.02);
}
}
@media (prefers-reduced-motion: reduce) {
.cgu-07__sky {
animation: none;
}
.cgu-07__btn {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — four radial-gradient blobs + conic wash on a blurred, slowly-transforming layer; SVG turbulence data-URI supplies the grain. */
```How this works
A "mesh gradient" is just several radial gradients with transparent falloff, layered and blurred into each other. Each blob is one background layer positioned independently:
background:
radial-gradient(38% 42% at 20% 25%, oklch(0.6 0.24 300 / .85), transparent 68%),
radial-gradient(34% 38% at 78% 20%, oklch(0.7 0.19 200 / .8), transparent 66%),
radial-gradient(40% 44% at 70% 78%, oklch(0.65 0.23 345 / .7), transparent 70%),
radial-gradient(36% 40% at 25% 80%, oklch(0.72 0.17 150 / .55), transparent 68%),
#07060d;Animation cheats beautifully: instead of moving each layer (unanimatable), the whole layer stack lives on an oversized ::before that slowly translates and rotates — the blobs appear to drift and cross. A tiny SVG turbulence data-URI at low opacity adds grain that kills banding on cheap displays; the headline sits in a normal stacking context above.
Make it yours
- Move blobs by editing each layer's
at x% y%anchor — that IS the mesh editor. - Recolor in oklch and keep lightness 0.6–0.75 so blobs glow without blowing out text contrast.
- Drift speed = the
cgu07-driftduration (90s reads as ambient; under 20s reads as busy). - Delete the grain layer if you already post-process with a texture.
Gotchas — read before shipping
- Oversize the animated layer (inset: -25%) or edges show during the drift.
- Animate transform on the layer stack — individual background-position moves repaint the full surface.
- Always test text contrast at the blobs' brightest crossing point, not the average.
- Grain via SVG data-URI, not a PNG request — zero network, scales infinitely.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by oklch(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 111+.
oklch layers are Baseline 2023; on older browsers supply hsl() fallback stops. The drift is plain transform animation — universal.