How to darken an image under text
Short answer
Put a translucent gradient over the image right in background:
<div style="display: grid; place-items: center; height: 180px; background: linear-gradient(rgb(0 0 0 / 0.5), rgb(0 0 0 / 0.5)), url('/media/photo-800x500.jpg') center / cover; color: white; font-size: 28px;">
Summer garden
</div>Backgrounds in the list are stacked: the first one is on top. A gradient of two equal colors gives an even darkening.
Darkening at the bottom
If the text is at the bottom, darkening only the lower part is enough — the image stays more visible:
<div style="display: flex; align-items: end; height: 180px; padding: 16px; box-sizing: border-box; background: linear-gradient(transparent 40%, rgb(0 0 0 / 0.8)), url('/media/photo-800x500.jpg') center / cover; color: white;">
<h3 style="margin: 0;">Summer garden</h3>
</div>Over a regular img
When the image is an <img>, the darkening layer is a pseudo-element of the parent:
<style>
.cover { position: relative; width: 300px; }
.cover img { display: block; width: 100%; height: auto; }
.cover::after { content: ""; position: absolute; inset: 0; background: rgb(0 0 0 / 0.4); }
</style>
<div class="cover"><img src="/media/photo-400x250.jpg" alt="A flower"></div>Common mistake
The whole block is darkened with opacity or filter: brightness(). The text inside fades together with the image — these properties act on the element as a whole with all its content. Darken a separate layer, not the block itself.
Functions used in this recipe
- linear-gradient() — A smooth transition between colors along a straight line — used as a background image.
- background-image — One or more background images: files or gradients.
- ::after — Creates a virtual last child of the element — for icons, marks and decorations after the content.
- filter — Graphic effects on an element: blur, black and white, brightness, shadow by shape.
- position — How an element is positioned: in the normal flow or by offsets.