Browse 100+ curated CSS gradient backgrounds across every type, with copy-ready code, a live generator, guides, and tips. Everything you need to master gradients for the web.
Try a different search term or filter.
Pick your colors, choose a type and direction, and get production-ready CSS in seconds.
CSS provides four core gradient functions. Each has unique strengths -- here is when and why to use each one.
A quick-reference table for every gradient function, its syntax, and key parameters.
| Function | Key Parameters | Support |
|---|---|---|
| linear-gradient() | angle, color-stop, hint | All browsers |
| radial-gradient() | shape, size, position | All browsers |
| conic-gradient() | from angle, at position | Modern |
| repeating-linear-gradient() | Same as linear, auto-tiles | All browsers |
| repeating-radial-gradient() | Same as radial, auto-tiles | All browsers |
| repeating-conic-gradient() | Same as conic, auto-tiles | Modern |
/* Linear: diagonal purple to orange */ background: linear-gradient( 135deg, #667eea 0%, #f093fb 100% ); /* Radial: centered glow */ background: radial-gradient( ellipse at center, #1a1a2e 0%, #0f3460 100% ); /* Conic: color wheel */ background: conic-gradient( from 0deg at 50% 50%, red, yellow, lime, cyan, blue, red ); /* Mesh: layered radials */ background-color: #0d0d0d; background-image: radial-gradient(at 20% 30%, #7c3aed 0px, transparent 50%), radial-gradient(at 80% 70%, #1d4ed8 0px, transparent 50%);
CSS custom properties let you define gradients once and reuse them across your entire codebase. A must-have pattern for any design system or theme.
/* Define once on :root */ :root { --grad-hero: linear-gradient( 135deg, #1847F0, #7c3aed ); --grad-accent: linear-gradient( 90deg, #2CFF6E, #08aeea ); } /* Use anywhere */ .hero { background: var(--grad-hero); } .badge { background: var(--grad-accent); }
/* Light mode defaults */ :root { --grad-surface: linear-gradient( 135deg, #f2f4fa, #e8ecf8 ); } /* Dark mode overrides */ [data-theme="dark"] { --grad-surface: linear-gradient( 135deg, #12121e, #1a1a2e ); } .card { background: var(--grad-surface); }
@property --grad-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; } .btn { background: linear-gradient( var(--grad-angle), #1847F0, #2CFF6E ); transition: --grad-angle .5s; } .btn:hover { --grad-angle: 180deg; }
:root { /* Intent-based naming */ --grad-brand-primary: ...; --grad-brand-secondary: ...; --grad-ui-card: ...; --grad-ui-button: ...; --grad-bg-hero: ...; --grad-bg-section: ...; --grad-state-success: ...; --grad-state-warning: ...; }
Hard-won knowledge from working with CSS gradients in production. Avoid common pitfalls and level up your technique.
red, 30%, blue) tells the browser where to place the halfway transition point, preventing the grey muddy middle common between saturated colors.repeating-linear-gradient, use hard stops: set the same position for two consecutive colors (e.g. blue 20px, red 20px) to get a crisp edge with zero blur.filter: hue-rotate() on the element to animate the entire hue cycle. Combine with animation: shift 4s linear infinite.to right equals 90deg. to bottom equals 180deg. to bottom right equals 135deg. Keywords are more readable; degrees give you precise control for custom-angled gradients.text-shadow for legibility.background-size: 200% 200% with an animated background-position to create a moving gradient without animating colors directly. This is the classic aurora hero effect technique.oklch() in gradients. Transitions through oklch stay perceptually consistent in brightness -- no more dark or desaturated muddy midpoints between two vivid hues.A CSS gradient background is a programmatically generated image created through native CSS functions, requiring no external image file.
Gradients are assigned to the background-image property, not background-color. The browser renders them by interpolating color values across a defined axis, shape, or angle, producing a smooth color transition entirely in code.
Because the browser generates the gradient at paint time, no HTTP request is made — unlike raster backgrounds where the browser must fetch a separate file before rendering can complete.
CSS gradients have no intrinsic dimensions. They scale to fill the element they are applied to, which makes them naturally fluid inside responsive design layouts.
Stripe is a well-known example of this approach in production. The company's hero sections use layered linear-gradient() calls on large containers, avoiding external image requests entirely while maintaining crisp rendering across all screen densities.
CSS provides 4 native gradient functions: linear-gradient(), radial-gradient(), conic-gradient(), and repeating variants of each.
Each type uses a different geometric model for distributing colors. Choosing the wrong type for a layout context produces visual artifacts or unintended blending that cannot be corrected with color stop adjustments alone.
|
Gradient Type |
Geometry |
Common Use Case |
|---|---|---|
|
|
Axis-based |
Section backgrounds, hero overlays |
|
|
Shape-based (circle or ellipse) |
Spotlight effects, radial glows |
|
|
Angle-based around a center |
Pie charts, color wheels |
|
|
Tiled pattern |
Striped or patterned backgrounds |
CSS conic gradients carry a 92/100 cross-browser compatibility score according to LambdaTest data, with full support across Chrome, Firefox, Safari 12.1+, and Edge 79+. IE 11 has zero support for conic-gradient().
Axis-based color distribution:
linear-gradient() transitions colors along a straight line at a defined angle or direction.
Default direction is to bottom (180 degrees) when no direction argument is provided
Accepts deg, turn, and rad angle units in addition to keyword directions like to right
Hard stops created by placing 2 stops at the same position produce a sharp edge with no blend
radial-gradient() radiates color outward from a center point.
Shape and size are independently configurable:
circle maintains equal radii on both axes; ellipse scales to element dimensions (default)
Size keywords: closest-side, farthest-side, closest-corner, farthest-corner
Center position uses the same syntax as background-position
Colors sweep around a center point at defined angles rather than across an axis.
conic-gradient() was the last of the 4 types to achieve full browser support, landing in Chrome 69, Firefox 83, and Safari 12.1. It accepts angle values in deg, turn, and grad units at each color stop — a distinction from the percentage-based stops used in linear and radial variants.
Pie charts and color wheels are the 2 most common use cases, both achievable without JavaScript or SVG.
Tiling behavior is the key difference from standard gradient functions.
Repeating variants (repeating-linear-gradient(), repeating-radial-gradient(), repeating-conic-gradient()) tile the defined pattern across the element instead of stretching a single gradient instance to fill it.
Very small repeat intervals, for example a repeating-linear-gradient set at 2px intervals, can produce aliasing artifacts on high-DPI displays. Testing on physical devices or using Chrome DevTools device emulation catches these before production.
linear-gradient() syntax follows a consistent 3-part structure: an optional direction, at least 2 color stops, and optional position values for each stop.
Full syntax: linear-gradient([direction], color-stop-1, color-stop-2, ...)
Direction accepts 2 formats:
Keyword directions: to right, to bottom, to top left, and similar compass combinations
Explicit angles: 45deg, 0.5turn, 1.57rad
When no direction is specified, the browser defaults to to bottom (equivalent to 180deg). A value of 0deg points upward, and degree values increase clockwise — which is the opposite of standard trigonometric convention. Worth knowing before you spend 10 minutes wondering why 90deg doesn't point up.
Color stops follow the pattern color position, for example red 25% or #3a86ff 100px.
Position units: percentages, pixels, em, or rem
Stops without a position are distributed evenly between the previous and next defined stops
2 stops at the same position (e.g., red 50%, blue 50%) produce a hard edge with no gradual blend
A color hint shifts the midpoint of the transition between 2 color stops.
The syntax places a standalone position value between 2 stops: red, 20%, blue. This tells the browser to reach the midpoint of the red-to-blue blend at the 20% mark rather than the default 50% mark. Useful for making a gradient appear to "pull" toward one side without adjusting the stop positions.
radial-gradient() generates color that spreads outward from a center point, with shape and size independently configurable.
Full syntax: radial-gradient([shape] [size] at [position], color-stop-1, color-stop-2, ...)
|
Parameter |
Options |
Default |
|---|---|---|
|
Shape |
|
|
|
Size |
|
|
|
Position |
Keywords, percentages, absolute lengths |
|
Ellipse vs. circle behavior differs on non-square elements:
An ellipse gradient stretches to match the element's width and height proportions. A circle gradient maintains equal radii on both axes regardless of element dimensions, which means the circular shape will appear off-center if the element is not square.
farthest-corner is the default and produces a gradient that extends until it reaches the element's most distant corner, filling the background fully.
closest-side stops the gradient at the nearest edge. This creates a visible hard edge on the far sides of the element, which is a deliberate design choice rather than a rendering error. Each size keyword produces a visually distinct result on the same element — they are not stylistic variations of the same output.
conic-gradient() distributes colors angularly around a center point, sweeping around the way hands move on a clock face.
Full syntax: conic-gradient([from angle] [at position], color-stop-1, color-stop-2, ...)
The default starting angle is 0deg (top of the element). The default center is 50% 50%. Both can be changed independently.
Color stops in conic-gradient() accept angle values in addition to percentages.
conic-gradient(red 0deg, blue 180deg, red 360deg) produces a half-red, half-blue sweep
conic-gradient(red 0%, blue 50%, red 100%) produces the same result using percentages
Mixing angle units and percentages in the same declaration is valid
Pie chart production:
A 3-segment pie chart requires no JavaScript. The syntax conic-gradient(red 120deg, blue 240deg, green 360deg) divides the circle into 3 equal sectors. Adding border-radius: 50% to the element rounds it into a circle.
The at keyword sets the center point of the sweep, using the same position syntax as radial-gradient() and background-position.
Moving the center off 50% 50% creates asymmetric angular distributions. A conic gradient with at 0 0 places the center at the element's top-left corner, producing a quarter-circle sweep across the element surface. Useful for corner glow effects in card designs.
A color stop defines where a specific color appears within the gradient and how the browser interpolates to neighboring stops.
Color stop syntax: color position — for example, #3a86ff 25% or rgba(0,0,0,0.5) 100px.
3 behaviors control stop placement:
Stops with explicit positions render at exactly that point in the gradient
Stops without positions are auto-distributed evenly between the previous and next defined stops
2 stops placed at identical positions create a hard edge with no gradual transition between them
Stacking 3 or more stops in sequence produces multi-band gradients. The background pattern repeating-linear-gradient(45deg, #eee 0px, #eee 10px, white 10px, white 20px) creates a striped effect using 4 stops without any additional CSS. CSS background patterns built this way require zero image assets and render sharply at all resolutions.
By default, browsers interpolate between stops in the sRGB color space, which can produce muddy mid-tones on transitions between opposite hues — for example, red to blue passing through a desaturated gray-purple zone.
The newer color-mix() syntax and color() function expand interpolation options, including the oklch color space, which produces perceptually uniform gradients without the desaturation artifacts. Browser support for oklch interpolation in gradients sits at around 88% according to State of CSS 2024 data.
A color hint is a position-only value placed between 2 color stops that shifts the blend midpoint.
Syntax: red, 30%, blue — the 30% value is the hint, not a color stop. The browser reaches the midpoint of the red-to-blue transition at the 30% mark rather than the default 50%. This asymmetric acceleration toward one side is a subtle tool. Most developers miss it entirely because it looks identical to a position value until you understand what it does.
Multiple CSS gradients stack as comma-separated values on a single background-image declaration.
background-image: linear-gradient(...), radial-gradient(...), url('image.jpg');
The first declared value renders on top, the last renders at the bottom. This stacking order is the opposite of z-index behavior, which trips people up the first time.
Lower layers only show through upper layers if the upper layers contain transparency.
transparent keyword resolves to rgba(0,0,0,0) — fully transparent black
rgba() and hsla() values with alpha less than 1 produce partial transparency
A linear-gradient(black, black) on top blocks everything beneath it regardless of how many layers are declared below it
A common production pattern: background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url('hero.jpg') overlays a semi-transparent dark scrim over a photograph, creating reliable text contrast without modifying the image file. According to WebAIM's 2024 Million analysis, poor color contrast affects 83.6% of websites — this layered gradient overlay technique directly addresses the most common cause of that failure on image-heavy sections.
background-size, background-position, and background-repeat accept comma-separated values that map to each layer in order.
background-image: linear-gradient(...), url('texture.png');
background-size: cover, 200px 200px;
background-position: center, top left;
The cover applies to the gradient layer; 200px 200px applies to the texture. This per-layer control makes complex CSS animated backgrounds and layered overlay systems manageable without duplicating selectors or adding wrapper elements.
Gradients and url() image references can coexist in the same background-image declaration.
The gradient layers are browser-generated at paint time, so combining them with an image reference does not increase HTTP request count beyond the single image fetch. The gradient layers themselves remain zero-request.
CSS gradients are browser-generated at paint time. They produce zero HTTP requests, unlike raster background images which require a full network round-trip before the browser can render.
That said, gradients are not cost-free. The cost appears at the rendering stage, not the network stage.
Directly animating gradient properties (color values, angle, stop positions) triggers a full repaint on every frame.
At 60 frames per second, that repaint runs continuously. On complex gradients with many color stops or large element dimensions, each repaint consumes measurable CPU time.
The correct approach for animated gradient backgrounds:
Animate background-position on a gradient with background-size: 400% 400% instead of animating the colors directly
Use opacity or transform on a pseudo-element layered over a static gradient
Avoid will-change: background-image — it does not create a compositing layer and provides no performance benefit
Each additional color stop increases the pixel calculation load during paint.
A 3-stop gradient renders noticeably faster than a 10-stop gradient on the same large element. On mobile devices with limited GPU memory, repeating gradients at very small intervals (2-4px) can produce both aliasing artifacts and elevated paint time. Testing on physical low-end Android devices catches these issues before production.
will-change: transform on a pseudo-element, not on the gradient itself, promotes that layer to a composite without forcing gradient recalculation each frame.
CSS gradients scale with their container by default. No background-size: cover workaround is required, unlike raster images where the browser must stretch or crop a finite pixel grid.
Responsive websites see an 11% higher conversion rate than non-responsive equivalents, according to VWO data. Gradient backgrounds that adapt fluidly to layout changes are part of that mobile-first design advantage over static image alternatives.
How stops behave at different screen sizes:
Percentage stops scale with the element's rendered dimensions at every breakpoint
Pixel stops stay fixed regardless of how large or small the container becomes
Mixing both units in one gradient is valid and sometimes useful: pixel-based hard stops can anchor a band while percentage stops handle the surrounding blends
A gradient with hard stops at 50px and calc(100% - 50px) keeps a fixed-width band in the center of an element regardless of the element's total width. That behavior is impossible with percentage-only stops.
Media queries can change gradient direction, color palette, or angle at specific breakpoints without any additional image assets.
.hero {
background-image: linear-gradient(to right, #3a86ff, #8338ec);
}
@media (max-width: 768px) {
.hero {
background-image: linear-gradient(to bottom, #3a86ff, #8338ec);
}
}
The horizontal gradient on desktop becomes vertical on mobile. No image swap, no extra HTTP request.
Stacking a semi-transparent gradient over a photo requires background-size: cover on both the gradient layer and the image layer.
Without matching background-size values per layer, the image scales to fill the container but the gradient layer does not, breaking the visual alignment between the overlay and the photo. Each background-size, background-position, and background-repeat value maps to its corresponding layer in the background-image declaration order.
Poor color contrast is the number 1 accessibility failure on the web, affecting 83.6% of all websites according to WebAIM's 2024 Million analysis. Gradients are a recurring cause because the contrast ratio changes continuously across the gradient surface.
WCAG 2.1 SC 1.4.3 requires a minimum 4.5:1 contrast ratio for normal text and 3:1 for large text (18px+ regular or 14px+ bold). With a solid background, a single contrast check passes the entire element. With a gradient background, every point along the gradient is a potential failure.
Automated tools catch approximately 95% of contrast issues, but the remaining 5% involving gradient and image backgrounds require manual verification (web-accessibility-checker.com, 2024).
Testing approach for gradient backgrounds:
Identify the lightest background color in the gradient range
Run the contrast check between that color and the text color
If the text passes at the lightest point, it passes at every point
Tools that support this: TPGi Colour Contrast Analyser (CCA) samples on-screen pixels directly, including gradient surfaces. Stark in Figma checks contrast during the mockup phase before any CSS is written.
Vestibular disorders affect more than 70 million people globally, making animated backgrounds a real barrier rather than a minor inconvenience (CSS-Tricks).
Animated gradient backgrounds must respect the prefers-reduced-motion media query. Every major browser — Chrome, Edge, Firefox, Safari, and Opera — supports this feature.
@media (prefers-reduced-motion: no-preference) {
.animated-bg {
animation: gradientShift 6s ease infinite;
}
}
The animation only runs when the user has not requested reduced motion. Decorative gradient animations with no informational value should be removed entirely under this query, not slowed down.
Gradients that shift from red to green to indicate status (low to high, bad to good) fail users with color vision deficiencies.
Do not rely on gradient color alone to communicate meaning. Pair the gradient with a text label, icon, or numeric value. This applies to CSS progress bar components, heat maps, and any background that encodes data through color transition.
All 4 CSS gradient types have full support in Chrome 69+, Firefox 83+, Edge 79+, and Safari 12.1+. The -webkit- prefix is no longer needed for linear-gradient() or radial-gradient() in any currently maintained browser.
Over 30% of gradient rendering issues arise in Safari and Internet Explorer, with conic gradients producing double the failure rate compared to linear and radial types (Bomberbot).
|
Gradient Type |
Chrome |
Firefox |
Safari |
IE 11 |
|---|---|---|---|---|
|
|
Full |
Full |
Full |
Partial |
|
|
Full |
Full |
Full |
Partial |
|
|
69+ |
83+ |
12.1+ |
None |
|
Repeating variants |
Full |
Full |
Full |
Partial |
IE 11 has no support for conic-gradient(). For the approximately 0.3-0.5% of users still on IE 11 (StatCounter 2024), a @supports fallback prevents a broken layout.
@supports tests for conic-gradient() support and delivers a linear-gradient() fallback for environments where conic rendering fails.
.element {
background-image: linear-gradient(135deg, #3a86ff, #8338ec);
}
@supports (background: conic-gradient(red, blue)) {
.element {
background-image: conic-gradient(from 45deg, #3a86ff, #8338ec);
}
}
The linear gradient renders everywhere. The conic gradient replaces it only in browsers that support it. No JavaScript, no user-agent sniffing.
Safari had a documented bug with radial-gradient() ellipse rendering prior to version 14.1.
The bug affected ellipse scaling inside flex containers, producing a circular gradient on elements where an ellipse was specified. Testing on Safari 14.0 and below with radial gradients inside display: flex or display: grid parents catches this before shipping. The cross-browser compatibility testing workflow should include physical iOS devices, since Safari on iOS follows the same rendering engine as desktop Safari and inherits the same version-specific bugs.
linear-gradient() distributes color along a straight axis at a defined angle.
radial-gradient() spreads color outward from a center point in a circular or elliptical shape.
The geometry is the main difference. Use linear for directional backgrounds, radial for spotlight or glow effects.
No. CSS gradients are image values and only work on background-image, not background-color.
Setting background-color to a gradient function produces no output. The property does not accept <image> data types.
Use rgba() or hsla() color values with an alpha below 1, or the transparent keyword.
For example, linear-gradient(rgba(0,0,0,0.5), transparent) creates a semi-opaque overlay that fades out. This is the standard approach for text contrast over hero images.
Directly animating gradient color values triggers a full repaint every frame, which is expensive.
The better approach: animate background-position on a gradient with background-size: 400% 400%. This moves the gradient without recalculating it, keeping GPU load low.
This is a color interpolation issue in the default sRGB color space.
Transitions between opposite hues (red to blue, for example) pass through a desaturated midzone. Switching to oklch interpolation using the color() function produces a perceptually cleaner blend.
List them as comma-separated values on background-image.
The first value renders on top. Lower layers need transparent or semi-transparent stops to remain visible. Match background-size and background-position values per layer to keep alignment consistent.
Apply the gradient to background-image, then set background-clip: text and color: transparent on the same element.
The text shape clips the gradient, making the color visible only through the letterforms. Browser support is full in all modern browsers without prefixes.
Linear and radial gradients have full support in all maintained browsers. The -webkit- prefix is no longer needed.
conic-gradient() has no support in IE 11. Use @supports to provide a linear-gradient fallback for environments where conic rendering fails.
Apply the gradient to the body element with min-height: 100vh.
body {
background-image: linear-gradient(135deg, #3a86ff, #8338ec);
min-height: 100vh;
}
This covers the full viewport regardless of content height.
WCAG 2.1 requires a 4.5:1 contrast ratio for normal text. With gradients, test against the lightest background color in the range, not an average.
If text fails at the lightest point, add a semi-opaque overlay or move text to a solid-color container.