CSS Tutorials

The 'Apple Style' Explained: Mesh Gradients in CSS [2026]

Why does every modern SaaS use Mesh Gradients? Learn how to recreate the Apple/Stripe aesthetic using pure CSS radial layers, avoiding heavy WebGL libraries.

By NineProo Team · 2026-02-07

In 2020, Apple released Big Sur, and the web changed forever. Flat colors died. Mesh Gradients were born.

From Stripe to Linear to OpenAI, the "Ethereal Glow" is the defining aesthetic of premium SaaS. But you don't need a 2MB WebGL library to do it. You just need to understand Radial Layering.


🚀 Design Mesh Gradients

Layer complex linear and radial gradients to build professional mesh backgrounds in seconds.

Launch Gradient Tool ->


The "Fake Mesh" Technique

Real mesh gradients requires vector interpolation (like in Illustrator). In CSS, we fake it by stacking Radial Gradients.

Imagine 4 spotlights hitting a wall from different corners.

.aurora-bg {
  background-color: #000000;
  background-image: 
    /* Top Left: Purple */
    radial-gradient(at 0% 0%, hsla(253, 16%, 7%, 1) 0, transparent 50%),
    /* Bottom Right: Blue */
    radial-gradient(at 100% 100%, hsla(225, 39%, 30%, 1) 0, transparent 50%),
    /* Center: Glow */ radial-gradient(at 50% 50%, hsla(339, 49%, 30%, 1) 0, transparent 50%);
}

Performance: Pure CSS vs. WebGL

Many developers reach for Three.js to create fluid backgrounds. Don't. WebGL initializes a canvas context, consumes 30-50MB of RAM, and drains battery.

Pure CSS Gradients:

Animating the Mesh

To make it "live," animate the background-position. _Note: This is expensive. Use sparingly._

@keyframes aurora {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.live-mesh {
  background-size: 200% 200%;
  animation: aurora 10s ease infinite;
}

Pro Tip: Glass Over Mesh

The "Premium SaaS" look is achieved by placing a Glassmorphism card _over_ a Mesh Gradient. The blur helps blend the gradient colors even further, hiding any banding artifacts.

Workflow:

1. Generate Mesh Background (using Gradient Tool). 2. Generate Glass Card (using Glass Tool). 3. Profit.


Dark Mode Mesh Gradients

Mesh gradients on dark backgrounds flip the formula. Instead of radiating light colors outward, you radiate slightly brighter tints from dark bases.

/* Light mode mesh */
body {
  background:
    radial-gradient(at 30% 20%, hsla(260, 100%, 70%, 0.6) 0px, transparent 50%),
    radial-gradient(at 80% 60%, hsla(190, 100%, 65%, 0.5) 0px, transparent 50%), #f8f7ff;
}

/* Dark mode mesh */
@media (prefers-color-scheme: dark) {
  body {
    background:
      radial-gradient(at 30% 20%, hsla(260, 80%, 35%, 0.6) 0px, transparent 50%),
      radial-gradient(at 80% 60%, hsla(190, 80%, 30%, 0.5) 0px, transparent 50%), #0a0a12;
  }
}

> [!TIP] > On dark backgrounds, reduce the hsl lightness to 30–40% and reduce the alpha to 0.4–0.6. Too-bright spots on dark create harsh contrast that reads as "aura" rather than "mesh."


SVG Mesh: When CSS Isn't Enough

CSS radial gradients create smooth blobs but can't replicate the true warped-mesh look of tools like Figma's mesh gradient or Adobe's freeform gradient. For those, you can use an SVG filter.

<!-- SVG mesh that actually distorts the gradient geometry -->
<svg viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="turbulence">
      <feTurbulence
        type="turbulence"
        baseFrequency="0.015"
        numOctaves="3"
        seed="5"
        result="noise"
      />
      <feDisplacementMap
        in="SourceGraphic"
        in2="noise"
        scale="60"
        xChannelSelector="R"
        yChannelSelector="G"
      />
    </filter>
  </defs>

  <!-- Gradient circles distorted by the turbulence filter -->
  <g filter="url(#turbulence)">
    <circle cx="250" cy="200" r="250" fill="hsla(260, 80%, 65%, 0.7)" />
    <circle cx="580" cy="380" r="230" fill="hsla(190, 90%, 60%, 0.6)" />
    <circle cx="100" cy="500" r="200" fill="hsla(320, 80%, 65%, 0.5)" />
  </g>
</svg>

Embed the SVG as a background image via url() for zero JavaScript overhead:

.hero {
  background-image: url('/mesh-gradient.svg');
  background-size: cover;
}

Performance: CSS vs. SVG vs. Canvas

| Method | File Size | Rendering | Animation | Complexity | | :-------------------- | :----------- | :----------- | :----------- | :--------- | | CSS radial gradients | ~200 bytes | GPU (fast) | Easy | Low | | Inline SVG + filter | ~1–3 KB | CPU filter | Moderate | Medium | | Canvas / WebGL | 0 bytes (JS) | GPU shader | Full control | High | | Exported PNG (1440px) | 150–400 KB | Decoded once | None | None |

The verdict for most projects: Use CSS gradients. They're composited on the GPU, scale infinitely with zero file size, and animate smoothly. Reserve SVG filters for hero sections where you need authentic mesh distortion.


Workflow: From Tool to Production

The typical mesh gradient workflow with NineProo:

1. Design the palette — Use Color Palette Tool to generate a 3–5 color array that shares complementary hues 2. Build the gradient — Drop the colors into Gradient Tool and switch to Radial mode. Layer 3–4 color stops at different center positions 3. Preview over content — Place a text block over the gradient and run it through Contrast Checker to verify readability 4. Add the glass card — For the premium SaaS look, generate a frosted panel in Glass Tool and layer it over the mesh

/* Final production pattern */
.hero {
  /* 1. Mesh background */
  background:
    radial-gradient(at 20% 30%, hsla(260, 80%, 65%, 0.6) 0px, transparent 55%),
    radial-gradient(at 75% 15%, hsla(320, 80%, 65%, 0.5) 0px, transparent 55%),
    radial-gradient(at 55% 80%, hsla(190, 80%, 60%, 0.4) 0px, transparent 55%), #f0efff;
  min-height: 90vh;
  display: grid;
  place-items: center;
}

/* 2. Glass panel on top */
.hero-card {
  background: rgba(255, 255, 255, 0.25);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: 20px;
  padding: 3rem;
}

Accessibility Considerations

Mesh gradients are backgrounds — they should never carry meaning. All content placed over them must meet WCAG contrast requirements.

The Moving Target Problem

Because a mesh gradient shifts across the viewport, text contrast varies by position. The safe approach:

1. Test the lightest part of your gradient — if text passes there, it passes everywhere 2. Add a scrim overlay — a subtle linear-gradient(rgba(0,0,0,0.2), transparent) at the top darkens just enough to lock in contrast without destroying the mesh aesthetic 3. Avoid thin fonts — weights below 400 require higher contrast ratios per WGAG 2.1

.hero {
  /* Mesh base */
  background: radial-gradient(at 20% 30%, hsla(260, 80%, 65%, 0.8) 0px, transparent 50%), #f0efff;
  position: relative;
}

/* Scrim to guarantee text readability */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.35);
  pointer-events: none;
}

Inspiration: Real-World Mesh Gradient Use Cases

Mesh gradients appear in the most successful digital products of the last five years. Here are concrete reference patterns you can study and adapt.

Apple M-Series Product Pages

Apple uses a very tight mesh — almost monochromatic, with barely-perceptible color variation — the gradient shifts from cool silver-grey at the top to a warm champagne at the bottom. The restraint is what makes it premium.

Reverse-engineer it:

.apple-style {
  background:
    radial-gradient(at 50% 0%, hsla(220, 20%, 92%, 0.6) 0px, transparent 60%),
    radial-gradient(at 100% 100%, hsla(35, 30%, 88%, 0.5) 0px, transparent 60%), #f2f1f0;
}

Stripe's Marketing Pages

Stripe's gradients are aggressive — loud purples and blues that grab attention on the hero, fading to white by the time you reach the first content block.

.stripe-style {
  background:
    radial-gradient(at 15% 50%, hsla(269, 100%, 65%, 0.8) 0px, transparent 50%),
    radial-gradient(at 85% 30%, hsla(214, 100%, 60%, 0.7) 0px, transparent 50%),
    radial-gradient(at 50% 100%, hsla(290, 100%, 70%, 0.4) 0px, transparent 60%), #ffffff;
}

Vercel's Dashboard

Vercel's aesthetic is "dark, futuristic, minimal." Their mesh is a barely-visible shift from deep navy to dark indigo.

.vercel-style {
  background:
    radial-gradient(at 0% 0%, hsla(214, 60%, 16%, 0.8) 0px, transparent 40%),
    radial-gradient(at 100% 100%, hsla(260, 40%, 10%, 0.6) 0px, transparent 50%), #050914;
}

Animated Mesh Gradient: The Smooth Approach

For landing pages where you want subtle motion without Canvas/WebGL:

@keyframes mesh-flow {
  0%,
  100% {
    background-position:
      30% 20%,
      80% 60%,
      50% 50%;
  }
  33% {
    background-position:
      20% 40%,
      65% 25%,
      40% 75%;
  }
  66% {
    background-position:
      45% 15%,
      90% 70%,
      60% 30%;
  }
}

.animated-mesh {
  background:
    radial-gradient(
      ellipse 40% 40% at var(--x1, 30%) var(--y1, 20%),
      hsla(260, 80%, 65%, 0.6),
      transparent
    ),
    radial-gradient(
      ellipse 40% 40% at var(--x2, 80%) var(--y2, 60%),
      hsla(190, 80%, 60%, 0.5),
      transparent
    ),
    #f0efff;
  background-size:
    100% 100%,
    100% 100%,
    100%;
  /* Animate via CSS custom properties (requires JavaScript for smooth interpolation) */
}

For a pure CSS version, the background-position trick:

.mesh-animated {
  background:
    radial-gradient(ellipse 600px 400px at top left, hsla(260, 80%, 65%, 0.7), transparent),
    radial-gradient(ellipse 500px 400px at bottom right, hsla(190, 80%, 60%, 0.6), transparent),
    #f0efff;
  background-size: 200% 200%;
  animation: mesh-drift 12s ease-in-out infinite alternate;
}

@keyframes mesh-drift {
  from {
    background-position:
      0% 0%,
      100% 100%,
      center;
  }
  to {
    background-position:
      40% 30%,
      60% 70%,
      center;
  }
}

> [!TIP] > Use animation-timing-function: ease-in-out and long durations (8–15s) to keep the motion ambient and non-distracting. Short, snappy animation draws attention — ambient motion adds life.


Conclusion

You don't need to be a 3D artist to design modern backgrounds. Layer your lights. Blur the result.

Start Designing: > Build Linear & Radial Gradients > Add Glass Overlay