CSS Tutorials

Beyond 2 Colors: The Complete Guide to CSS Gradients [2026]

Linear gradients are boring. Learn how to master Conic, Radial, and Mesh gradients using modern CSS syntax. Stop using images for backgrounds.

By NineProo Team · 2026-02-07

Most developers learn linear-gradient(red, blue) and stop there. But if you look at modern sites (Stripe, Vercel, Apple), they rely on Conic and Radial gradients to create depth, metallic textures, and pie charts.

This guide takes you from "Junior Gradient" to "Senior Shader".


πŸš€ Visual Gradient Builder

Stop guessing percentages. Visually drag-and-drop color stops to create complex Linear, Radial, and Conic gradients.

Launch Gradient Tool ->


1. The Underrated conic-gradient

Introduced recently, conic-gradient rotates colors around a central point. Use Case: Pie Charts, Color Wheels, and "CD Reflection" effects.

/* A perfect Pie Chart in one line */
.pie-chart {
  background: conic-gradient(purple 0% 25%, blue 25% 60%, green 60% 100%);
  border-radius: 50%;
}

2. Hard Stops for Patterns

You don't need SVG for simple stripes. If you set two color stops to the _same position_, the browser renders a hard line.

/* Warning Tape Pattern */
.warning {
  background: repeating-linear-gradient(45deg, yellow 0px, yellow 10px, black 10px, black 20px);
}

3. Stacking Gradients

You can layer multiple gradients on a single element. The first one defined is on top.

.complex-bg {
  background: 
    /* Semi-transparent Linear Gradient on Top */
    linear-gradient(rgba(0, 0, 0, 0.5), transparent),
    /* Solid Radial Gradient on Bottom */ radial-gradient(circle at top right, purple, blue);
}

4. Performance: Gradient vs. Image

A 4K background image is 2MB-5MB. A complex CSS gradient is 200 bytes. Always prefer gradients for abstract backgrounds. They render on the GPU and scale infinitely without pixelation.

Pro Tip: Managing Presets

Don't rewrite your brand gradients every time. NineProo Library allows you to:

1. Design a gradient in Gradient Tool. 2. Save it to your "Brand Kit". 3. Copy the CSS variable (e.g., var(--gradient-primary)).

Conclusion

Gradients are the most efficient way to add texture to the web. Master the 3 types (Linear, Radial, Conic) and you can delete half your image assets.


Color Interpolation: Where Gradients Go Wrong

The browser interpolates colors in sRGB color space by default. This creates the infamous "muddy grey area" in the middle of two complementary colors (e.g., red to cyan).

/* Blue to orange: dirty brown in the middle */
.bad-gradient {
  background: linear-gradient(to right, blue, orange);
  /* sRGB interpolation passes through grey */
}

Modern Fix: in oklch

CSS Color Level 4 introduces in-gradient color space control. oklch interpolation follows perceptual brightness, keeping vivid midpoints:

/* oklch: vivid, perceptually uniform transition */
.vivid-gradient {
  background: linear-gradient(to right in oklch, oklch(50% 0.3 264), oklch(68% 0.25 60));
}

The interpolation hint in oklch keeps the gradient vibrant no matter what colors you combine. Browser support as of 2026: Chrome 111+, Safari 16.2+, Firefox 113+.


Animated Gradients: The Right Way

The naΓ―ve approach β€” transitioning background β€” doesn't work:

/* ❌ Doesn't animate β€” background cannot be transitioned */
.btn {
  background: linear-gradient(135deg, purple, blue);
  transition: background 0.3s; /* IGNORED by browsers */
}

Use the background-position trick instead:

/* βœ… Smooth gradient animation via background-size + position */
.btn {
  background: linear-gradient(135deg, #8b5cf6, #3b82f6, #8b5cf6);
  background-size: 200% 200%;
  background-position: 0% 50%;
  transition: background-position 0.5s ease;
}

.btn:hover {
  background-position: 100% 50%;
}

For a continuous loop animation (like the aurora effect):

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

.animated-bg {
  background: linear-gradient(270deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
  background-size: 400% 400%;
  animation: gradient-shift 8s ease infinite;
}

> [!WARNING] > Animating background-position triggers Paint (not just Composite), so it does consume resources. Use it for hero sections, not for frequently-repeated components like cards in a list.


Gradient Text

The background-clip: text technique clips a gradient to the text shape:

.gradient-heading {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent; /* Fallback for non-webkit */
}

> [!NOTE] > Need a full gradient text tool with live preview and CSS export? Use Gradient Text Tool to generate and customize these in seconds.


Gradient Textures & Patterns

Pure CSS can replicate many background textures using only gradients.

Checkerboard

.checkerboard {
  background-color: #e5e5e5;
  background-image:
    linear-gradient(45deg, #ccc 25%, transparent 25%),
    linear-gradient(-45deg, #ccc 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ccc 75%),
    linear-gradient(-45deg, transparent 75%, #ccc 75%);
  background-size: 20px 20px;
  background-position:
    0 0,
    0 10px,
    10px -10px,
    -10px 0px;
}

Diagonal Stripes

.stripes {
  background: repeating-linear-gradient(-45deg, #f3f4f6, #f3f4f6 10px, #e5e7eb 10px, #e5e7eb 20px);
}

Dot Grid

.dot-grid {
  background-color: #f8f8ff;
  background-image: radial-gradient(circle, #a0aec0 1px, transparent 1px);
  background-size: 24px 24px;
}

These are all zero KB β€” they render entirely on the GPU. Use them instead of background image files for UI textures.


Brand Gradient System with CSS Custom Properties

For consistent brand gradients across your codebase:

:root {
  /* Brand palette */
  --c-purple: #8b5cf6;
  --c-blue: #3b82f6;
  --c-pink: #ec4899;
  --c-teal: #14b8a6;

  /* Named gradient tokens */
  --gradient-primary: linear-gradient(135deg, var(--c-purple), var(--c-blue));
  --gradient-accent: linear-gradient(135deg, var(--c-pink), var(--c-purple));
  --gradient-success: linear-gradient(135deg, var(--c-teal), var(--c-blue));
  --gradient-hero: linear-gradient(180deg, #0f0f23 0%, #1a1a3e 100%);
}

/* Usage anywhere */
.btn-primary {
  background: var(--gradient-primary);
}
.badge-premium {
  background: var(--gradient-accent);
}
.hero-section {
  background: var(--gradient-hero);
}

This makes global brand updates a single-line change, and ensures all gradients are consistent across components.


Browser Support & Edge Cases

| Feature | Chrome | Firefox | Safari | Edge | | :----------------------- | :----- | :------ | :----- | :--- | | linear-gradient | 26+ | 16+ | 7+ | 12+ | | radial-gradient | 26+ | 16+ | 7+ | 12+ | | conic-gradient | 69+ | 83+ | 12.1+ | 79+ | | in oklch interpolation | 111+ | 113+ | 16.2+ | 111+ | | repeating-* | All | All | All | All |

The Safari Prefix Trap

As of Safari 15.4+, background-clip: text works unprefixed. But for older Safari (14–15.3), you still need -webkit-background-clip:

.gradient-text {
  -webkit-background-clip: text; /* Safari <15.4 */
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

Gradient Accessibility: Contrast Over Gradients

When text sits over a gradient background, the contrast varies across the text. The WCAG requirement applies to the worst-case position β€” the part of the gradient where the contrast is lowest.

/* This gradient fades to white β€” text on the right side may fail */
.hero {
  background: linear-gradient(to right, #7c3aed, #ffffff);
  color: #ffffff;
}

/* Fix: ensure text only sits over the dark portion */
.hero-content {
  max-width: 50%; /* Only occupies the purple half */
}

/* Or: add a scrim behind text */
.hero-text {
  background: linear-gradient(to right, rgba(0, 0, 0, 0.4), transparent);
  padding: 1rem 2rem;
}

> [!IMPORTANT] > WCAG requires 4.5:1 contrast ratio for normal text. Test your text against the lightest part of the gradient to ensure it passes everywhere.

> Check Contrast Ratios


Common Gradient Mistakes

| Mistake | Problem | Fix | | :------------------------------------------------------- | :-------------------------------------- | :------------------------------------------- | | Mid-point grey mud | Complementary colors create grey center | Use in oklch interpolation | | Transitioning background | Doesn't animate | Use background-position shift instead | | Only using linear gradients | Design feels flat | Mix radial and conic for depth | | Hard stop without planning | Stripe looks accidental | Use exact 50% values for intentional bands | | High-opacity gradient over text | Text unreadable | Ensure contrast at worst-case gradient point | | Forgetting -webkit- prefix for background-clip: text | Broken on older Safari | Always include both prefixed and unprefixed |


The Full CSS Gradient Reference

| Function | Use Case | Since | | :---------------------------- | :---------------------------------------- | :---------- | | linear-gradient() | Fade between 2+ colors in a straight line | CSS3 | | radial-gradient() | Circular/elliptical burst from a center | CSS3 | | conic-gradient() | Rotation around a point, pie charts | CSS4 (2019) | | repeating-linear-gradient() | Infinite striped patterns | CSS3 | | repeating-radial-gradient() | Repeating rings or targets | CSS3 | | repeating-conic-gradient() | Repeating angular patterns | CSS4 |

Every gradient function accepts the same color stop syntax: color percentage or color length. The gradient engine calculates midpoints automatically unless you specify them.


Conclusion

Gradients are the most efficient way to add texture to the web. Master the 3 types (Linear, Radial, Conic), learn the oklch interpolation trick for vivid midpoints, and build a token system that makes global brand updates a one-line change.

Start Mixing: > Build Complex Gradients > Create Gradient Text