Tutorial

How to Change a CSS Background Image’s Opacity

CSS

With CSS and CSS3 you can do a lot of things, but setting an opacity on a CSS background is not one of them. However, if you get creative, there are a ton of creative work-arounds you to make it seem like you’re changing the CSS background image’s opacity. Both of the following methods have excellent browser support down to Internet Explorer 8.

Method 1: Use absolute positioning and an image

This method is exactly like it sounds. You simply use absolute positioning on an a normal img tag and make it seem like you used the CSS background-image property. All you have to do is put the image inside of a position: relative; container. Here’s what the HTML markup generally looks like:

<div class="demo_wrap">
  <h1>Hello World!</h1>
  <img src="https://assets.digitalocean.com/labs/images/community_bg.png">
</div>

And here’s what your CSS will look like:

.demo_wrap {
    position: relative;
    overflow: hidden;
    padding: 16px;
    border: 1px dashed green;
}
.demo_wrap h1 {
    padding: 100px;
    position: relative;
    z-index: 2;
}
.demo_wrap img {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: auto;
    opacity: 0.6;
}

The trick here is to absolutely position the img and stretch it so it fills the entire parent container. And to relatively position everything else so that you can set a z-index that pulls it above the img.

Here’s a live demo:

Hello World!

Method 2: Using CSS Pseudo-Elements

This method is seems simple once you see it, and is definitely my preferred method of doing this. Using CSS pseudo-elements of either :before or :after, you a div with a background image and set an opacity on it. Here’s what your HTML markup would roughly look like:

<div class="demo_wrap">
  <h1>Hello World!</h1>
</div>

And here’s what the CSS looks like:

   .demo_wrap {
    position: relative;
    background: #5C97FF;
    overflow: hidden;
}
.demo_wrap h1 {
    padding: 50px;
    position: relative;
    z-index: 2;
}
/* You could use :after - it doesn't really matter */
.demo_wrap:before {
    content: ' ';
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    opacity: 0.6;
    background-image: url('https://assets.digitalocean.com/labs/images/community_bg.png');
    background-repeat: no-repeat;
    background-position: 50% 0;
    background-size: cover;
}

Here again we must move the z-index of content (in this cas the <h1>) above the background pseudoelement, and we must explicitly define the position: absolute; and z-index: 1 on the :before pseudoelement.

The rest of the attributes on the pseudoelement exist to position it to overlap 100% of the parent, and also make use of a clever new CSS property: background-size: cover which sizes the background to cover the element without changing proportions.
Here’s a nice little demo of this method:

Hello World!

Creative Commons License