2026.10.19 · 4 min · css · browsers · news
CSS mesh gradients: from four fake blobs to one real mesh.
Every mesh gradient in CSS today is a stack of radial-gradient() layers. On 2026.10.14 the CSS Working Group agreed to add real 2D gradients: mesh-gradient() and freeform-gradient(). What was decided, what the draft syntax looks like, and why you should keep your radial stack for now. As of 2026.10.
Every mesh gradient in CSS today is fake. Those soft blob backgrounds behind Stripe-style hero sections are four or more radial-gradient() layers, one per corner, each fading to transparent, hand-tuned until they look right. On 2026.10.14 the CSS Working Group resolved to add real 2D gradients to CSS. It's the first step, not a ship date.
Watch the 60-second version on Instagram.
How the fake works
A mesh-style background today is several background-image layers. Each one is a radial-gradient() placed at a corner that fades out to transparent, so the layers underneath show through. CSS paints the first layer in the list on top.
The rings in the figure stand in for each gradient's fade (the drawing doesn't use gradients). The catch is in the middle of the bottom plate: the layers don't interpolate with each other like a real mesh would. Each one just blends over the ones below it, so where the blobs overlap the colours can turn muddy, and you end up nudging stops and percentages until it stops looking wrong.
/* Today: fake it */
.hero {
background:
radial-gradient(at 0% 0%, red 0, transparent 60%),
radial-gradient(at 100% 0%, blue 0, transparent 60%),
radial-gradient(at 0% 100%, green 0, transparent 60%),
radial-gradient(at 100% 100%, yellow 0, transparent 60%);
}What the CSSWG decided
The request is old. Josh Tumath opened w3c/csswg-drafts#7648 on 2022.08.24, asking for 2D gradients that design tools currently fake by layering radial gradients. On 2026.10.14 the group resolved:
Adopt both freeform and mesh gradients into css-images-5, with concerns noted.
It also agreed to pull the explainer into the CSSWG repo. The issue picked up the "Needs Edits" label the same day, which means the spec text isn't written yet. Everything below is draft syntax.
Two functions, not one
mesh-gradient() is Tab Atkins' proposal from 2026.08.14. You write rows of colour points: commas separate the points in a row, a ; starts the next row, and every row must have the same number of points. Positions are optional; without them the points sit on an evenly spaced grid. The simplest form is four colours, two rows:
/* Proposed (draft, no browser support) */
.hero { background-image: mesh-gradient(red, blue; green, yellow); }freeform-gradient() started as Lea Verou's proposal on 2024.06.10: colours at arbitrary positions instead of on a grid. In Tab's refinement each point is <color> <number> <position>+, and a point with several positions becomes a Catmull-Rom curve instead of a single point. Two parts of that are explicitly not settled. The <number> ("strength") is written as conditional, "if we do want to introduce strength", and on 2026.10.08 someone floated removing line and curve support from the first version.
mesh-gradient() | freeform-gradient() | |
|---|---|---|
| Points | Rows on a grid, separated by ; | Anywhere |
| Positions | Optional, even grid by default | Required, one or more per colour |
| Curves | No | A point with several positions (may be cut from v1) |
| Strength | No | A <number>, if it stays |
| Status | Draft, needs edits | Draft, needs edits |
The concerns that were noted
"With concerns noted" is in the resolution for a reason. The minutes list:
- GPU performance, raised by smfr from WebKit.
- Exact maths and degenerate cases, like two points on top of each other.
- Authoring: a mesh realistically needs a visual editor to write.
- Animation, left as an open question.
- Cost: two functions means implementing everything twice.
No browser ships or prototypes either function. The minutes don't mention one; the only implementations they point to are Inkscape and Illustrator.
What people get wrong
- "CSS already has mesh gradients." The "CSS mesh gradient generators" you find online output stacked radial gradients, the same fake as in figure 1.
- "It's coming soon." A resolution to adopt is the first step. The spec text still needs writing, and nobody has announced an implementation.
- "The syntax is final." Positions,
strengthand curves are all still in discussion. Don't copy a draft example into a style guide. - "I can ship it with a fallback later." If you write
mesh-gradient()today it's an invalid value, and the browser drops the whole declaration.
If you want to experiment, put the radial stack first and gate the draft behind @supports (background-image: mesh-gradient(red, blue; green, yellow)), so today every browser takes the stack.
On a client project I'd keep the four radial layers and a comment pointing at #7648, and revisit when a browser ships mesh-gradient() behind a flag, not before.
The short version
- Today's mesh gradients are stacked
radial-gradient()layers that blend over each other; they don't interpolate. - On 2026.10.14 the CSSWG resolved to adopt
mesh-gradient()andfreeform-gradient()into css-images-5, with concerns noted. mesh-gradient(red, blue; green, yellow): commas split a row,;starts the next, even grid by default.freeform-gradient()places colours anywhere; strength and curves aren't final.- No browser supports either. Keep your radial stack.
Sources: w3c/csswg-drafts #7648, Mesh gradient / Freeform gradient / 2D gradient · Josh Tumath, Mesh gradients in CSS · MDN, radial-gradient() · MDN, Using multiple backgrounds