The short version
- Dark mode gradients should be redesigned for the dark theme, because the same saturated colours that look balanced on white look harsh and glaring on a dark background.
- On dark grounds, lower the chroma of gradient colours, keep bright colour to small areas, and use a near black tinted towards your brand hue instead of pure black.
- Swap gradients between themes by storing their colours in CSS custom properties and redefining them inside a prefers-color-scheme: dark media query.
- The CSS light-dark() function chooses between two colours based on the color-scheme in effect, which keeps both values next to each other.
- Dark gradients band more visibly than light ones, so a light layer of grain is worth adding in dark mode.
On this page
Dark mode gradients look best when you give them their own colours rather than reusing the light theme's. On a dark ground the eye adapts and every saturated colour seems brighter, so a gradient that felt calm on white starts to glare. Lower the chroma, keep vivid colour to small areas, tint the ground instead of using pure black, and switch the values with prefers-color-scheme or light-dark(). The depth stays; the glare goes.
Why light theme gradients fail in the dark
Three things change when the page goes dark. Large bright areas become the brightest thing in the room, which reads as glare rather than colour. Shadows stop working, so gradients that relied on darkening edges for depth lose it. And the steps between dark tones get easier to see, so subtle gradients start to band. Dark mode design covers the wider theme; this page is about the gradients.
Five rules for dark mode gradients
- 1
Tint the ground
Use a near black that leans towards your hue, such as
#0b0a14for violet brands, instead of#000000. Pure black makes colour look pasted on. - 2
Lower chroma
Pull saturation down by roughly a third for large areas. In OKLCH, keep the hue and reduce the C value.
- 3
Shrink the bright part
Let vivid colour occupy a corner or a glow, and let most of the surface sit close to the ground.
- 4
Lift, do not shadow
Show elevation with slightly lighter surfaces and gradients that brighten towards the top, since shadows disappear on dark grounds.
- 5
Add grain
Fine noise breaks up the visible steps in dark blends. Grainy gradients has the recipe.
Switching gradients with prefers-color-scheme
Store gradient colours, not whole gradients, in custom properties. Then the dark theme only has to redefine the colours, and every component that uses them updates. This is the same pattern described in CSS variables for theming.
:root {
color-scheme: light dark;
--ground: #faf8ff;
--glow: #c4b5fd;
--glow-2: #f9a8d4;
--hero: radial-gradient(circle at 80% 15%, var(--glow) 0%, transparent 45%),
radial-gradient(circle at 10% 90%, var(--glow-2) 0%, transparent 50%),
var(--ground);
}
@media (prefers-color-scheme: dark) {
:root {
--ground: #0b0a14;
--glow: #4c1d95;
--glow-2: #1e3a8a;
}
}
.hero {
background: var(--hero);
}Notice the dark glows are deeper, not brighter. On a dark ground a colour only needs to be a little lighter than its surroundings to read as light.
Using light-dark()
The light-dark() function returns its first colour in a light scheme and its second in a dark one. It needs color-scheme: light dark on the element or an ancestor, and it is supported in current Chrome, Edge, Safari and Firefox. It keeps both values on one line, which makes reviewing a palette easier.
:root {
color-scheme: light dark;
}
.card {
background: linear-gradient(
180deg,
light-dark(#ffffff, #1a1530) 0%,
light-dark(#f5f3ff, #0b0a14) 100%
);
color: light-dark(#1e1b2e, #e9e5f5);
}Supporting a manual theme toggle
Many sites let people override the system setting. Put the choice on the root element and scope your variables to it. The media query handles the default; the attribute wins when someone chooses.
:root[data-theme="dark"] {
color-scheme: dark;
--ground: #0b0a14;
--glow: #4c1d95;
--glow-2: #1e3a8a;
}
:root[data-theme="light"] {
color-scheme: light;
}Retuning a gradient for dark mode
Here is the same brand gradient adjusted stop by stop. Working in OKLCH makes this predictable, because lightness and chroma are separate numbers; OKLCH explained shows why.
oklch(98% 0.01 295)Dark theme
oklch(15% 0.03 295)Change
oklch(85% 0.09 295)Dark theme
oklch(35% 0.15 295)Change
oklch(84% 0.10 350)Dark theme
oklch(40% 0.12 265)Change
Light theme
oklch(45% 0.20 295)Dark theme
oklch(82% 0.09 295)Change
radial-gradient(circle at 80% 15%, oklch(35% 0.15 295) 0%, transparent 45%), radial-gradient(circle at 10% 90%, oklch(40% 0.12 265) 0%, transparent 50%), linear-gradient(oklch(15% 0.03 295), oklch(15% 0.03 295))Text on dark gradients
Light text on a dark gradient usually has plenty of contrast, but check it where the gradient is brightest, not where it is darkest. A headline in #e2e8f0 on #0b0a14 is far above the 4.5:1 that WCAG asks for body text; the same headline over a bright violet glow may not be. Avoid pure white body text on near black as well: very high contrast causes halation for some readers, so a soft off white is kinder. Colour contrast and accessibility has the numbers.
Avoid in dark mode
- Pure black ground with saturated stops
- The light theme gradient, darkened
- Large areas of neon colour
- Pure white paragraphs
- Smooth dark gradients with no grain
Do
- A tinted near black ground
- A separate set of dark stops
- Colour as light from one corner
- Off white text, around
#e9e5f5 - A fine noise layer to hide banding
For more dark palettes, dark gradient backgrounds has a set to copy. And for social posts and slides, where you cannot test every line by hand, Gradiently's Auto ink picks light or dark type per line from the Mark's own palette, and the Mark moves its calmest area behind the words, so a dark design never puts a headline on its brightest glow.
Questions people ask
How do I change a gradient in dark mode?
Put the gradient's colours in CSS custom properties and redefine them inside @media (prefers-color-scheme: dark). The gradient updates wherever it uses those variables.
Can I use light-dark() inside a gradient?
Yes, for each colour stop, since light-dark() returns a colour. It needs color-scheme: light dark on the element or an ancestor.
Why do my gradients look too bright in dark mode?
Eyes adapt to dark screens, so saturated colours seem stronger. Lower the chroma, darken the stops and keep bright colour to small areas.
Should dark mode use pure black?
Usually not for gradients. A near black tinted towards your brand hue makes colours blend naturally and reduces harsh contrast.
Why does my dark gradient show stripes?
Dark tones sit close together in 8 bit colour, so steps become visible. Add a light grain layer and avoid heavy compression.
Written by Gradiently
The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.
See our profile