Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

CSS cannot apply opacity to only a background-image layer. The opacity property affects the entire element, including its text, buttons and child elements. To make a background image translucent while keeping content fully opaque, use a semi-transparent background layer, a positioned pseudo-element, or (for compositing effects) background-blend-mode.

Why opacity fades your text too

This code changes the opacity of the whole .hero element:

.hero {
  opacity: 0.35;
}

The browser composites the element and all of its descendants at 35% opacity. Therefore headings, paragraphs, links, buttons and the background image all become translucent. There is no separate background-image-opacity property.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Opacity accepts a number from 0 to 1, or a percentage from 0% to 100%. Zero is fully transparent and one (100%) is fully opaque; values outside that range are clamped.

#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Method 1: Add a translucent gradient layer

For a simple dark or light tint, add a color layer before the image in the background shorthand. Background layers are painted in listed order, with the first layer on top.

.hero {
  color: white;
  background:
    linear-gradient(rgb(0 0 0 / 35%), rgb(0 0 0 / 35%)),
    url("hero.jpg") center / cover no-repeat;
}

The black layer is 35% opaque, so the image is darkened while the text remains unaffected. Increase the alpha value for a stronger tint, or reduce it for a lighter effect.

Use a light overlay

.hero {
  color: #111;
  background:
    linear-gradient(rgb(255 255 255 / 55%), rgb(255 255 255 / 55%)),
    url("hero.jpg") center / cover no-repeat;
}

A white alpha layer lightens the image. You can use any color, including a brand color:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
.hero {
  background:
    linear-gradient(rgb(20 80 160 / 45%), rgb(20 80 160 / 45%)),
    url("hero.jpg") center / cover no-repeat;
}

Use a separate overlay color and image declarations

.hero {
  background-color: rgb(0 0 0 / 35%);
  background-image: url("hero.jpg");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

This form is useful when a framework or component system keeps color and image values in separate custom properties. The alpha-capable color is still a background layer, not element opacity.

Method 2: Put the image on a pseudo-element

Use a pseudo-element when the image needs independent opacity, animation, positioning or clipping. The pseudo-element is a separate composited layer, so changing its opacity does not affect the content in the card.

.card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: white;
}

.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: url("card.jpg") center / cover no-repeat;
  opacity: 0.35;
  pointer-events: none;
}

position: relative establishes the containing block for inset: 0. isolation: isolate keeps the component’s stacking context self-contained, and overflow: hidden clips the image to rounded corners when the card has a border radius.

Keep content explicitly above the image

If the negative z-index places the pseudo-element behind an ancestor and it disappears, avoid the negative layer and assign explicit stacking levels:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
.card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url("card.jpg") center / cover no-repeat;
  opacity: 0.35;
  pointer-events: none;
}

.card__content {
  position: relative;
  z-index: 1;
}

The overlay cannot intercept clicks because of pointer-events: none; links and buttons remain usable.

Animate the image without fading content

.card::before {
  transition: opacity 220ms ease, transform 220ms ease;
}

.card:hover::before {
  opacity: 0.55;
  transform: scale(1.04);
}

Only the pseudo-element animates. Respect users who request reduced motion:

@media (prefers-reduced-motion: reduce) {
  .card::before {
    transition: none;
  }
}

Method 3: Use background-blend-mode for compositing

background-blend-mode blends an element’s background images with one another and with its background color. The mode follows the same layer order as background-image. This is useful for multiply, screen, overlay and similar treatments, but it is not a direct opacity slider: the result depends on the image’s colors and the selected mode.

Rank #3
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
.hero {
  background-color: rgb(0 0 0 / 35%);
  background-image: url("hero.jpg");
  background-blend-mode: multiply;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

Try screen for a lightening effect, or overlay for stronger contrast. Preview real content at several viewport sizes because blend results vary substantially between photographs, illustrations and flat-color images.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

background-blend-mode versus mix-blend-mode

background-blend-mode affects the element’s own background layers. mix-blend-mode blends the entire element, including its text and children, with content behind it. Use mix-blend-mode only when that whole-element interaction is intentional.

Which technique should you choose?

Requirement Recommended technique Why
Uniform dark or light tint Alpha gradient or background color Shortest markup and predictable responsive behavior
Independent image opacity, animation or clipping Pseudo-element Image is a separate layer from content
Multiply, screen or overlay treatment background-blend-mode Provides compositing modes rather than simple transparency
Blend the complete component with what is behind it mix-blend-mode Intentionally affects the whole element

Accessibility and visual quality checks

  • Check contrast after the overlay. A dark layer often improves light text, while a light layer can make dark text harder to distinguish. Test the actual image behind every important label and control.
  • Do not use opacity to communicate disabled state alone. Pair reduced opacity with a clear state, such as a disabled attribute or text, so the result is not ambiguous.
  • Preserve interaction. Give pseudo-element overlays pointer-events: none and keep interactive content in a higher stacking layer.
  • Provide meaningful alternatives. A decorative CSS background needs no alternative text. If the image conveys information, include that information in HTML rather than relying on the background.
  • Test forced colors and high-contrast modes. Decorative imagery may disappear, so text and controls must remain understandable without it.

Responsive and component patterns

Custom properties for themeable opacity

.hero {
  --hero-tint: rgb(0 0 0 / 35%);
  background:
    linear-gradient(var(--hero-tint), var(--hero-tint)),
    url("hero.jpg") center / cover no-repeat;
}

.hero--light {
  --hero-tint: rgb(255 255 255 / 55%);
}

Keep the image URL and layout rules stable while changing only the tint token for themes or variants.

Combining a gradient with an image

.hero {
  background:
    linear-gradient(90deg, rgb(0 0 0 / 70%), rgb(0 0 0 / 10%)),
    url("hero.jpg") center / cover no-repeat;
}

A gradient with different alpha values can preserve detail on one side while creating a readable text area on the other. It still leaves descendants fully opaque.

Rounded cards and image bleed

.card {
  border-radius: 1rem;
  overflow: hidden;
}

Apply clipping to the component that owns the pseudo-element. If shadows or absolutely positioned badges must extend outside the card, use a nested wrapper for clipping instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common failures

Text is still translucent

Search for opacity on the component or an ancestor. Remove it and move the image to a gradient layer or pseudo-element. Also check that a utility class has not applied an opacity value later in the cascade.

The pseudo-element covers the text or blocks clicks

Set pointer-events: none, place the content in a positioned child with z-index: 1, and keep the component isolated with isolation: isolate.

The image vanishes

A negative z-index can place the pseudo-element behind an ancestor’s background. Use the explicit z-index: 0/z-index: 1 pattern instead, or remove the negative z-index and raise the content layer.

The overlay does not cover the whole component

Ensure the component has position: relative and the pseudo-element has inset: 0. A parent with no defined height may collapse; give the component content, padding or a minimum height.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The blend looks unlike the design mockup

Blend modes are image-dependent. Try another mode, adjust the background color alpha, or use a gradient overlay when you need a repeatable tint.

The overlay works but the image is pixelated

Opacity does not change image resolution. Supply an appropriately sized source, use background-size: cover deliberately, and inspect the result at the largest expected viewport and device-pixel ratio.

Or skip the browser setup

If you need a rendered reference image for a CSS change, ScreenshotNeo can capture the page with one request. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before the shot. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers report the page verdict and billing result.

After you publish the page, capture it with cURL (see the ScreenshotNeo documentation for all parameters):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

In this example, replace the URL with your page. The same endpoint works from Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Or Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also provides an MCP server for Claude, Cursor and other MCP clients, plus full-page and element captures, device presets, custom CSS and JavaScript, waits, request blocking, PDFs, async jobs and bulk capture. One thousand screenshots per month are free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Practical testing checklist

  1. Confirm the element itself and its ancestors do not set opacity.
  2. Choose a gradient layer for a fixed tint, or a pseudo-element for independent image behavior.
  3. Verify the image layer order: overlay first, image second.
  4. Check text and control contrast over the lightest and darkest image areas.
  5. Test keyboard focus and pointer interaction when using pseudo-elements.
  6. Inspect narrow, wide and high-density viewports.
  7. Capture the final page at representative sizes if visual regression checking is part of your workflow.

Frequently Asked Questions

Can I write background-image: opacity(0.5)?

No. CSS filters and opacity functions do not provide a background-only alpha declaration. Use an alpha color layer or a pseudo-element.

Does the gradient overlay change the text color?

No. The overlay is a background layer. It changes the pixels behind the content, while the text remains at its declared color and opacity.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use an extra HTML overlay element instead of ::before?

Use a real element when the layer has semantic content or needs independent scripting. For a decorative image layer, a pseudo-element avoids extra markup.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.