CSS Mesh Gradient Technique

Build linear, radial, and conic CSS gradients with a visual editor. Drag color stops, pick presets, and copy ready-to-use CSS, Tailwind, or custom property output.

CSS Mesh Gradient Technique with layered radial gradients

Layering multiple radial gradients with transparent edges creates the soft, blended look of a mesh gradient using nothing but standard CSS background-image values. Each layer contributes a colored blob at a specific position, and the layers blend where they overlap. No special CSS feature is required: comma-separated background-image values stack radial gradients from front to back.1

The key is transparency: each gradient layer uses rgba() or oklch() colors with alpha values below 1 for the outer stops, letting lower layers show through in the overlap regions.2 The result resembles the smooth multicolor mesh gradients from design tools like Figma, built entirely in CSS without SVG or canvas. Consequently, mesh gradients work in all modern browsers without polyfills. Building on this, adjusting the radial size and position of each layer controls how far each color blob extends and where the blended overlap regions appear on the element.

What this page covers

  • 3 to 6 gradient layers fewer looks like a flat two-tone blend, more adds cost without visible improvement
  • Transparent outer stops each radial-gradient layer must fade to transparent at its edge for layers below to show through

Opens the CSS Gradient Builder with this page's checklist shown at the top of the tool.

Open in the tool →

Layering multiple radial-gradient() values

CSS accepts comma-separated background-image values. Each value renders as a separate layer, with the first value on top and subsequent values below. For a mesh effect, each layer is a radial-gradient() positioned at a different point with a color that fades to transparent at its edges. The number of layers determines the complexity of the mesh: three layers produce a simple blend, while five or six layers create the rich, organic look associated with design tool mesh gradients.

A three-blob mesh uses three layers: radial-gradient(circle at 30% 40%, oklch(0.75 0.2 250 / 0.8) 0%, transparent 60%), followed by two more layers at different positions with different colors. The browser composites the layers using the normal blend mode by default.3 Consequently, overlapping regions show additive blending through the alpha channel: where a blue blob at 0.8 opacity overlaps a red blob at 0.7 opacity, the result is a purple region. Controlling each blob's alpha at the center stop adjusts how saturated the overlap regions appear. The number of layers determines the complexity of the mesh: three layers produce a simple blend, while five or six layers create the rich, organic look associated with design tool mesh gradients. Positioning the blobs at slightly irregular intervals rather than on a strict grid prevents the pattern from reading as geometric.

Using transparent stops to reveal lower layers

The outer stop of each radial gradient must use a transparent or low-alpha color for the mesh effect to work. A gradient from a solid color to transparent(oklch(0.7 0.2 250)) fades to nothing at its outer edge, revealing the layers below.2 Without transparency in the outer stop, each layer covers all layers beneath it completely and the mesh effect disappears. Choosing a base background color that matches the average hue of the gradient blobs prevents the uncovered regions from appearing as a mismatched background that clashes with the overall mesh composition.

Adjusting blend coverage

The percentage position of the transparent stop controls how far each blob extends before fading. Moving the outer stop from 60% to 80% makes the blob cover more of the element before fading to transparent. Moving it to 40% makes a smaller, more concentrated blob. Pair the stop position with an alpha value below 0.5 at the center to create an even softer blend where the overlap regions between blobs sit at similar perceived brightness, preventing any one blob from appearing to sit perceptually on top of the others in the stack.

Yet very small blobs with an outer stop below 30% may leave large uncolored regions between blobs that break the mesh illusion and reveal the underlying background in unflattering patches. Furthermore, the base background color of the element shows through in regions not covered by any blob, so set a background-color that complements the gradient blobs to control the mesh's overall tone. For dark-mode mesh gradients, reducing the chroma of each blob to 0.05 or below and keeping lightness between 0.12 and 0.25 produces a subtle atmospheric texture that reads as depth rather than as a set of colored circles floating on a dark surface.

Adjusting radial size and position for intersection blends

Each layer's radial size and center position determines where blobs overlap. Positioning two blobs within 20% to 30% of each other on both axes creates a visible overlap region where the colors blend. Positioning them farther apart produces isolated color pools with minimal blending. Using oklch() colors with consistent lightness values across all blobs produces a mesh where no single color dominates perceptually, keeping the overall composition balanced.

Building a mesh grid

A systematic approach places blobs at grid positions: 25% 25%, 75% 25%, 25% 75%, and 75% 75% for a four-blob mesh. Each blob uses a different hue and covers a radius large enough to overlap with its neighbors, typically 40% to 60% of the element size. Starting with a four-blob grid lets you validate that the color relationships read as intended before layering in additional complexity, and adjusting the radius of every blob by the same percentage keeps the overlap ratios consistent as the mesh grows or shrinks across breakpoints.

The overlap regions at the grid intersections show blended colors from two or more layers. Adding a fifth blob at the center pulls the mesh together visually and eliminates any uncolored region near the element midpoint. Using oklch() colors with consistent lightness values across all blobs produces a mesh where no single color dominates perceptually. For hero sections that need the mesh to feel organic rather than grid-based, offsetting each blob from its grid position by a random small percentage breaks the rigid symmetry and produces a more natural distribution.

Controlling mesh blob positions with CSS custom properties

CSS custom properties make mesh gradient blob parameters configurable without editing the gradient function directly. Declaring custom properties for each blob's x position, y position, and size at the component level lets you adjust each blob through a single variable block. Applying all three parameters as custom properties reduces the multi-layer gradient to a readable template where the circle center and outer radius reference the variables.

Animating blob positions with @property creates a flowing mesh that shifts color pools smoothly over time.4 Registering each position property as type number (representing a percentage) allows @keyframes to interpolate between positions without the discrete snap behavior that untyped custom properties produce. A four-blob mesh with independently animating positions produces a slow, aurora-like surface motion with no JavaScript.

Limiting animation to prefers-reduced-motion off

Wrapping the @property animation in @media (prefers-reduced-motion: no-preference) respects the user's system-level motion preference.5 Users who have enabled reduced motion see the static mesh gradient, while users without that preference see the animated version. This pattern applies to any CSS gradient animation and is a baseline accessibility requirement for production deployments. Combining this media query with the @property registration ensures that only browsers supporting both features run the animation, providing a clean fallback to the static gradient in older browsers and respecting user preferences simultaneously.

When to use this

Use mesh gradients for hero backgrounds, card surfaces, and decorative panels where a single-direction gradient feels too simple. On small elements the blending area is often too tight to read as a mesh rather than a smeared color, so see where your mesh blobs actually overlap at the size you plan to ship before committing to the effect.

Examples

Hero section background with four-color mesh

Place four radial blobs at 25% 25%, 75% 25%, 25% 75%, 75% 75%. Use oklch colors with hues 90 degrees apart for adjacent blobs. Set the outer stop to transparent at 60% for each layer. Add a base background-color matching the darkest gradient tone.

Card surface with a subtle two-color mesh

Use two overlapping blobs, one at 30% 30% and one at 70% 70%. Keep alpha values at 0.3 to 0.5 for a muted effect that does not compete with card content. The blending midpoint between the blobs creates a natural focal point for the card layout.

Dark-mode mesh gradient for a sidebar panel

Use oklch colors with lightness below 0.25 and chroma below 0.1 for dark surface blobs. High-chroma blobs look neon on dark backgrounds rather than atmospheric. Reduce chroma to 0.05 to 0.08 for subtle depth without color noise.

Sources
  1. 1.

    W3C, "CSS Backgrounds and Borders Module Level 3," w3.org, July 2024. https://www.w3.org/TR/css-backgrounds-3/#background-image

  2. 2.

    CSS-Tricks, "radial-gradient()," css-tricks.com, July 2025. https://css-tricks.com/almanac/functions/r/radial-gradient/

  3. 3.

    W3C, "Compositing and Blending Level 1," w3.org, March 2024. https://www.w3.org/TR/compositing-1/

  4. 4.

    Mozilla Developer Network, "@property," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/CSS/@property

  5. 5.

    Mozilla Developer Network, "prefers-reduced-motion," developer.mozilla.org, June 2026. https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion

FAQ

Three to six layers produce a convincing mesh effect. Fewer than three produces a simple two-tone blend rather than a mesh. More than six adds processing cost without visible improvement in most cases, as the overlapping blobs become indistinguishable from a flat gradient at the center.

The most common cause is missing transparency in the outer stops. Each radial-gradient layer must fade to transparent at its edge for the layers below to show through. Replace the outer stop color with transparent or an rgba()/oklch() value with alpha close to 0. Without transparency, each layer obscures all layers below it.

Yes. The technique uses only comma-separated background-image values and radial-gradient() with rgba() or oklch() transparency. These features have been available in all major browsers for several years. No special flags, polyfills, or new CSS features are required. CapyToolkit lets you preview the layered result in real time, which is useful for dialing in blob positions and opacity values before writing the CSS.

Each blob position and size controls its contribution. Position two blobs close together to create a strong blend region between their colors. Move them apart to isolate the colors with only a small overlap. Reduce the outer stop percentage (say from 60% to 40%) to tighten each blob and reduce overlap. Increase it to spread each blob and intensify the blending region.

Yes. oklch() with an alpha channel: oklch(0.7 0.2 250 / 0.8) sets lightness, chroma, hue, and opacity. Using oklch() colors with consistent lightness across all blobs keeps the mesh perceptually balanced regardless of hue. This is harder to achieve with hex or rgb() values where different hues have different perceived brightness.

Additional resources

Guides

CSS Gradient Text with background-clip Apply a CSS gradient to text using background-image and background-clip: text. Browser support, fallback strategy, and live examples with the gradient builder. Animating CSS Gradients with @property Animate CSS gradient stops smoothly using @property custom properties. Browser support, fallback patterns, and OKLCH hue-rotation animations. CSS Mesh Gradient Technique Build mesh-style gradients in CSS using multiple layered radial-gradient() values on the same background-image. No SVG or canvas required. Tailwind CSS v4 Gradient Utilities Complete guide to Tailwind v4 gradient utilities. bg-linear-to-r, bg-radial, bg-conic, from-*, via-*, to-*, and in-oklch modifier reference. CSS Gradient Borders Apply CSS gradient borders using border-image or background-clip masking. Both techniques, browser support comparison, and border-radius workaround. OKLCH Interpolation in CSS Gradients Use OKLCH color space interpolation in CSS gradients with the in oklch modifier. How it eliminates grey midpoints and improves perceptual smoothness. CSS Gradients for Dark Mode UI Design CSS gradients for dark mode using reduced chroma, lower lightness stops, and prefers-color-scheme media queries. Practical patterns for UI surfaces. CSS Background Patterns with Gradients Build repeating CSS background patterns using gradient functions and background-size. Stripes, grids, dots, and diagonal tile techniques without images. Glassmorphism with CSS Gradients Implement the glassmorphism effect with CSS gradients, backdrop-filter blur, and translucent stops. Browser support and performance considerations. CSS Gradient Rendering Across Laptop and Phone Displays How CSS gradients render on the Dell XPS 16, iPhone 17 Pro, MacBook Air M4, MacBook Pro M4 and Galaxy S25: P3 color stops, OKLCH interpolation, OLED blacks and the browser engine each device runs.