ScreenshotNeo

BlogHow-to

CSS Background Image Opacity: How to Adjust It

Learn three reliable ways to adjust a CSS background image’s opacity without fading text, buttons, or other content.

By the ScreenshotNeo team1 October 20266 min read

Use a separate layer for the image. CSS has no standalone opacity property for one background-image layer. Setting opacity on the element fades its text, buttons, and descendants too. For a simple tint, add a semi-transparent gradient or background color. For independent image opacity, put the image on a pseudo-element.

1. Add a translucent gradient overlay

This is the shortest solution when you want to darken or lighten a background while keeping the content fully opaque.

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

The first layer is painted above the image. Change 35% to control the overlay strength:

  • 0%: no tint.
  • 35%: moderate darkening.
  • 100%: the image is completely covered by the overlay color.

Use a white alpha layer to lighten an image:

.hero {
  background:
    linear-gradient(rgb(255 255 255 / 45%), rgb(255 255 255 / 45%)),
    url('hero.jpg') center / cover no-repeat;
}

This uses an alpha-capable background color, the approach documented in MDN’s opacity guidance.

2. Put the image on a pseudo-element

Choose this pattern when the image needs its own opacity, position, animation, clipping, or stacking order.

.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;
}

.card-content {
  position: relative;
  z-index: 1;
}

The pseudo-element is a separate rendering layer, so its opacity does not reduce the opacity of .card-content. pointer-events: none keeps the layer from intercepting clicks. overflow: hidden clips the image to rounded corners.

If the image disappears behind an ancestor, remove the negative z-index and use a normal stacking order instead:

.card {
  position: relative;
}

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

.card-content {
  position: relative;
  z-index: 1;
}

3. Use background-blend-mode for compositing

background-blend-mode blends an element’s background image with its background color or other background layers. It is useful for treatments such as multiply, screen, and overlay; it is not a uniform opacity slider.

.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;
}

Blend modes follow the order of the background-image layers. See MDN’s background-blend-mode reference for the available modes.

4. Complete runnable example

Save this as index.html, place an image named hero.jpg beside it, and open it in a browser.

<!doctype html>
<html lang='en'>
<head>
  <meta charset='utf-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <title>Background image opacity</title>
  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: system-ui, sans-serif;
      background: #111;
    }
    .hero {
      min-height: 60vh;
      display: grid;
      place-items: center;
      padding: 3rem;
      color: white;
      text-align: center;
      background:
        linear-gradient(rgb(0 0 0 / 45%), rgb(0 0 0 / 45%)),
        url('hero.jpg') center / cover no-repeat;
    }
    .hero h1 { margin: 0 0 0.75rem; }
    .hero a {
      display: inline-block;
      padding: 0.7rem 1rem;
      border-radius: 0.4rem;
      color: #111;
      background: white;
      text-decoration: none;
    }
  </style>
</head>
<body>
  <section class='hero'>
    <div>
      <h1>Readable content over an image</h1>
      <p>The overlay changes the image while this text stays opaque.</p>
      <a href='#details'>Read more</a>
    </div>
  </section>
</body>
</html>

5. Choosing the right method

Need Use Why
One consistent tint Gradient or alpha background layer Smallest, responsive implementation
Independent opacity or animation Pseudo-element Image gets its own layer and properties
Multiply, screen, overlay, or another blend effect background-blend-mode Controls compositing behavior
Blend the whole component with content behind it mix-blend-mode It blends the element itself, unlike background-blend-mode

Do not use opacity: 0.35 on the component when only the background should fade:

.hero {
  opacity: 0.35; /* also fades text, buttons, and descendants */
}

6. Opacity values and accessibility

  • Opacity accepts numbers from 0 to 1 or percentages from 0% to 100%.
  • 0 is fully transparent; 1 is fully opaque. Values outside the range are clamped.
  • After adding an overlay, check text contrast against the resulting image. A dark overlay often improves contrast for light text, but verify every responsive crop and state.
  • Keep interactive content above a pseudo-element and set the pseudo-element to pointer-events: none.
  • Do not communicate essential information through the background image alone; provide meaningful text or an accessible alternative.

Opacity behavior and readability considerations are covered in MDN’s opacity documentation.

7. Responsive and visual edge cases

Background positioning changes the perceived opacity

With background-size: cover, different viewport ratios crop different parts of the image. A dark overlay can appear stronger or weaker depending on the underlying colors. Test narrow and wide layouts and adjust background-position where the focal subject moves.

Rounded corners

Apply overflow: hidden to the component when a pseudo-element must follow its border radius.

Stacking contexts

isolation: isolate creates a local stacking context and prevents blend or z-index interactions with unrelated ancestors. If it conflicts with an existing layout, use explicit positioned content and a non-negative layer order.

Animations

Animate the pseudo-element’s opacity when the image should fade independently. Respect reduced-motion preferences:

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

Performance

Large background images still cost network bandwidth and decoding time regardless of opacity. Serve an appropriately sized image, use modern formats where supported, and avoid animating expensive properties unnecessarily. A static overlay adds little CSS complexity; multiple large layered images increase paint work.

8. Troubleshooting

Symptom Cause Fix
Text is faded too opacity is on the parent Move the image to a gradient layer or pseudo-element.
Image is invisible Negative z-index places it behind an ancestor background Remove the negative z-index and raise the content with z-index: 1.
Clicks do not work The overlay receives pointer events Add pointer-events: none.
Rounded corners do not clip the image The parent does not clip overflow Add overflow: hidden.
Blend result looks wrong Blend modes depend on source colors and layer order Try another mode, change the background color, or use a normal alpha overlay.
Overlay has no visible effect Alpha is too low, or the image is already close to the overlay color Increase the alpha value and inspect the computed styles.
Content contrast fails on some screens Image brightness changes across crops Increase overlay strength, use a solid content panel, or change text color.

9. Or skip the browser setup

If you need rendered screenshots of pages that use these CSS techniques, ScreenshotNeo captures the page with one GET request. It accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for all options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests

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

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}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also provides an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf tools. It supports full-page captures with lazy images loaded, CSS selectors, dark mode, custom viewports and device presets, retina scale, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, authorization, geolocation, caching, signed links, asynchronous jobs, bulk capture, usage data, and PDF output.

There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

10. FAQ

Can I set opacity directly on background-image?

No. Use an alpha color layer, a pseudo-element, or a blend mode.

Will a gradient overlay affect child elements?

No. A background layer belongs to the element’s background painting and does not reduce the opacity of its content.

When should I prefer a pseudo-element?

Use one when the image needs independent animation, positioning, clipping, or opacity.

Is background-blend-mode the same as opacity?

No. Blend modes calculate a composite result from colors and layers; they do not apply a uniform alpha value.

How do I make a background image transparent but keep a solid background color?

Use a pseudo-element for the image and leave the component’s normal background color on the parent, or place a semi-transparent image layer above that color.