The short version
- The quickest gradient overlay in CSS is a second background layer: list the gradient before url() in background-image so it sits on top.
- For an img element, put the gradient on a ::before or ::after pseudo-element of a positioned wrapper.
- background-blend-mode and mix-blend-mode turn a gradient overlay into a colour wash that tints the image rather than covering it.
- Hero images set as CSS backgrounds are discovered later than img elements, so an img with an overlay usually loads faster above the fold.
- Overlays meant to carry text should be darkest behind the words and transparent elsewhere, not an even dark film over the whole photo.
On this page
The simplest gradient overlay CSS is a layered background: background-image: linear-gradient(rgb(2 6 23 / 0.6), rgb(2 6 23 / 0)), url(photo.jpg). Layers listed first are drawn on top, so the gradient sits over the photo. When the image is an <img> element, put the gradient on a pseudo-element instead, and when you want the colour to tint the photo rather than cover it, add a blend mode. Each method suits a different job.
Method 1: a layered background
background-image accepts a comma separated list. The first value is the top layer. Gradients and images mix freely, and each layer can have its own size and position if you list those properties in the same order. This is the right choice for decorative images where no alt text is needed.
.banner {
background-color: #0f172a; /* shows until the photo loads */
background-image:
linear-gradient(to right, rgb(15 23 42 / 0.9) 0%, rgb(15 23 42 / 0.6) 40%, rgb(15 23 42 / 0) 70%),
url("/images/workshop.jpg");
background-size: cover;
background-position: center;
color: #f8fafc;
}url() in your own background-image.The top and bottom bars suit galleries where a title sits at the top and a credit at the bottom. The vignette draws the eye inward without carrying text. The brand tint is a strong look for team pages and event banners; gradient overlays covers when each feels right from a design point of view.
Method 2: a pseudo-element over an img
Content images belong in <img> elements: they get alt text, responsive srcset, lazy loading and early discovery by the browser. A background gradient cannot sit over an <img>, so wrap it and put the gradient on the wrapper's pseudo-element.
<figure class="overlay">
<img src="/images/harbour.jpg" alt="Fishing boats moored in a small harbour at dusk"
width="1920" height="1080" fetchpriority="high">
<figcaption>Harbour Days, 14 to 16 June</figcaption>
</figure>.overlay {
position: relative;
margin: 0;
isolation: isolate;
}
.overlay img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.overlay::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(to top, rgb(2 6 23 / 0.75), rgb(2 6 23 / 0) 60%);
pointer-events: none;
transition: opacity 250ms ease-out;
}
.overlay figcaption {
position: absolute;
inset: auto 1.5rem 1.5rem;
z-index: 1;
color: #f8fafc;
}
.overlay:hover::after { opacity: 0.6; }isolation: isolate keeps the overlay's stacking inside the figure. The overlay can fade on hover because it is its own layer.Background layer
- One element, one declaration
- No alt text, so decorative images only
- Found late by the browser, which can slow a hero
- Overlay cannot fade without animating the whole background
img plus pseudo-element
- A wrapper and a few more lines
- Proper alt text and responsive
srcset - Discovered early;
fetchpriority="high"helps the main image - Overlay opacity transitions cheaply
For a hero image that is the largest thing on screen, the second method usually wins on loading speed. Optimising images for the web explains why the browser finds <img> elements sooner than CSS backgrounds.
Method 3: blend modes for colour washes
A plain overlay sits on the photo like tinted glass. A blend mode mixes the gradient into the photo's own light and dark, which looks more like the photo was shot in that colour. Use background-blend-mode for layered backgrounds and mix-blend-mode on a pseudo-element over an <img>.
multiplyWhat it does
Good overlay for
screenLightens; black areas take the colourGood overlay for
overlayWhat it does
Good overlay for
colorKeeps the photo's light, replaces its colourGood overlay for
soft-lightWhat it does
Good overlay for
color with a two colour gradient is the quickest web duotone./* Duotone wash on a layered background */
.duotone {
background-image:
linear-gradient(135deg, #1e1b4b 0%, #f472b6 100%),
url("/images/portrait.jpg");
background-size: cover;
background-blend-mode: color;
}
/* The same idea over an img element */
.overlay--wash::after {
background: linear-gradient(135deg, #1e1b4b, #f472b6);
mix-blend-mode: color;
}background-blend-mode blends layers of one element. mix-blend-mode blends an element with whatever is behind it, here the photo.The full technique, including how to pick the two colours, is in the duotone effect.
Overlays that keep text readable
The most common mistake is an even dark film over the entire photo, say 50 percent black. It dulls the image everywhere and still may not be dark enough behind the words. Shape the overlay instead: darkest under the text, clear where the photo matters.
- 1
Decide where the words go
Bottom left for captions, left third for hero copy, centre for a single line.
- 2
Point the gradient at them
Use
to topfor bottom text,to rightfor left text, or a radial centred on the words. - 3
Stop early
Fade to fully transparent by 60 to 70 percent so most of the photo stays untouched.
- 4
Check the worst case
Measure contrast where the photo is brightest behind a letter. Colour contrast and accessibility lists the ratios.
Eased scrims with many stops look smoother than a two stop fade; the method is in transparent gradients in CSS.
Overlays without the guesswork
On a website you tune each overlay by hand. For social posts, banners and slides, Gradiently skips the step: a Mark knows where your words are and deepens or lifts its own colours behind them, and photos can be tinted in the Mark's colours as mono, duotone or a wash, and with Pro the design resizes to every format in one step, with no overlay to rework.
An event banner at website hero size, with the background calming behind the words instead of a hand tuned overlay.
Questions people ask
How do I put a gradient over a background image in CSS?
List the gradient before the image in background-image: linear-gradient(rgb(0 0 0 / 0.5), transparent), url(photo.jpg). The first layer is drawn on top.
How do I add a gradient overlay to an img element?
Wrap the image in a positioned element and put the gradient on its ::after pseudo-element with position: absolute and inset: 0.
What is the difference between background-blend-mode and mix-blend-mode?
background-blend-mode blends the background layers of one element. mix-blend-mode blends a whole element with what is behind it.
How dark should an image overlay be for text?
Dark enough that the text passes contrast checks at the brightest point behind it. Shape the gradient so it is darkest there and clear elsewhere.
Can I animate a gradient overlay on hover?
Yes. Put the overlay on a pseudo-element and transition its opacity, which is cheaper than animating the background itself.
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