How to make a background image transparent in CSS

How to change background-image opacity in CSS without affecting text | HTML/CSS

When building a website, you may often want to put a background image on an HTML <div> that also contains text or other content.

And to make the text stand out, you want to change the opacity of that background image in CSS so that it’s semi-transparent. But you’ve tried, and you can’t change the opacity of the background image without also affecting the text or other child elements!

What can you do? Not to worry– this article will give you some practical solutions to controlling your background image opacity.

So, first, the bad news…

There’s no CSS property that you can use to change the opacity of only the background image.

Unlike background colors, which allow you to adjust the alpha channel to control opacity, it simply doesn’t exist for the background-image property. Maybe someday?

In the meantime, let’s take a look at just why changing the opacity will affect text or other content in that element. Then we’ll go over workarounds you can use.

Opacity changes on a parent will get inherited to child elements.

For example, let’s say you have a div element with some text inside, and you have set the background-image on the parent .hero element.

<div class="hero">
    <h1>Cute kittehs everywhere!</h1>
</div>

Then you adjust the opacity of the parent to try to make the background image semi-transparent, like this:

.hero {
    background-image: url('https://placekitten.com/1200/800');
    opacity: 0.75;
}

Opacity is automatically inherited by child elements, so when you adjust the opacity of the parent element, it will affect all child elements in that parent layer. (This is similar to how z-index is also inherited.)

So you will end up with all the elements, both background image and text, having that reduced opacity.

Background image in the parent with reduced opacity affecting the text
Definitely not what we want to see!

Solution: Put the background image into a pseudo-element of the parent.

To fix this issue, we need to put the background image into a child element of the parent. This will ensure that the background image and the text content will be on their own “layer” in the parent. You can then control each layer’s opacity without affecting each other!

One approach you can use is to put the background-image styles in a pseudo-element of the parent element.

.hero {
    position: relative; 
    height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.hero::before {    
      content: "";
      background-image: url('https://placekitten.com/1200/800');
      background-size: cover;
      position: absolute;
      top: 0px;
      right: 0px;
      bottom: 0px;
      left: 0px;
      opacity: 0.75;
}

h1 {
  position: relative;
  color: #ffffff;  
  font-size: 14rem;
  line-height: 0.9;
  text-align: center;
}

Since the pseudo-element is a sort of child of the parent, you can change the opacity of it without affecting the text content.

To make that pseudo-element the same size as the parent, you’ll have to absolutely position it and set its top, right, bottom, and left values to zero so it doesn’t collapse. Also, as a pseudo-element, it needs to have the content property set, otherwise it won’t show up on the page.

(You can also put the background image into its own child element, but using a pseudo-element helps keep the HTML simplified.)

Then for the text, which we have in the <h1> tag, you will need to set it to position: relative so that it will be on top of the pseudo-element and background image. If you don’t explicitly set the position property, it will be hidden underneath the absolutely positioned pseudo-element in the z-index layer stack.

Lastly, don’t forget to set the parent to position: relative to keep the child within bounds!

Now, the text will still be at a default opacity of 1, and the reduced opacity setting will be limited to the background image in the pseudo-element.

Reduced opacity background image

I have the code for the above example in a Codepen— feel free to play around with it!

Alternative solution: add an overlay with reduced opacity and background-color on top of the background image.

Another solution is instead of changing the opacity of the background image, you add an overlay with a semi-transparent background color on top of the background image.

The HTML markup will be the same as the previous solution. In the CSS, you can set the background-image directly in the parent element, with no opacity change.

The pseudo-element of the parent will then contain the semi-transparent background-color.

This is accomplished by setting the background-color property using the rgba() syntax, where the first three characters are the RGB color numbers, and the last number is the alpha or transparency setting. We’re using 0,0,0 for the RGB color, which translates to black.

An alpha value can range from 0 (0% opacity) to 1 (100% opacity). So our value of 0.25will result in an overlay of 25% opacity.

Here’s what that will look like in the code:

.hero { 
    position: relative; 
    height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-image: url('https://placekitten.com/1200/800');
    background-size: cover;
}

.hero::before {
    content: "";
    position: absolute;
    top: 0px;
    right: 0px;
    bottom: 0px;
    left: 0px;
    background-color: rgba(0,0,0,0.25);
}

The result will look like this:

Background overlay in pseudo-element

And here’s the Codepen for this overlay solution!

Both solutions have a very similar-looking result. The first solution has a background image set at 75% opacity. And the second solution adds a black overlay at 25% opacity. So they’re not quite the same, but they are similar.

The overlay solution is also handy if you want to add a toned color to the background image. Here’s what that would look like if we set the overlay background-color to rgba(152, 66, 211, 0.63):

Purple background overlay
Want to learn how to build a website?

I'm making a course that will teach you how to build a real-world responsive website from scratch!

Learn more

Comments

M
Muhamed Mangasuba
Apr 13, 2020 at 1:18 am

would like to learn

Reply

Write a Comment

at
Reply