Mar 13, 2025

    best way to adjust css background image's opacity

    Introduction

    Opacity is a property in CSS that lets us control the transparency of an element, The value can range from 0 to 1, where 0 being completely transparent and 1 being fully opaque. All elements have a default opacity of 1.

    A common use case is to change the opacity of a background color or the background image for improving the visual appearance of the web page, or to make the text on that background more legible and easier to read and make the text or any other content over the background stand out more.

    But if you try to change the opacity of the container element which has the background and which houses the content that goes on top of the background, You will find out that simply changing the opacity is not enough, when you change the opacity this way, the opacity of the background changes but along with it the opacity of the text or content that goes over the background will also change, and you probably don't want that.

    In this blog we will learn of only one method to achieve the desired behavior. I say only one because I have tried out multiple methods and I have found this one to be the best one as it's also easy to customize it and make reusable component out of it if you are using any frameworks.

    Changing Background Color Opacity

    For this example we will use the following HTML markup :

    	<!-- index.html -->
        <div class="low-opacity-bg">
            <h1>Welcome To NestedBlock</h1>
            <p>Programming blogs that cover everything from beginner tips to advanced techniques</p> 
        </div>
    

    and the following CSS :

    /*styles.css*/
    
    /*...other styles before this*/
    .low-opacity-bg{
        background-image: url("/image.jpg");
    	background-repeat: no-repeat;
        background-size: cover;
    }
    

    This is what our web page looks like :

    example_image_1

    While this looks decent, it would be better if can add a translucent background color or a gradient over the background so the text over it stands out more. Since we already know simply changing the opacity won't work. We have to take a different approach.

    We will first pull out the background color, We will use the ::after pseudo element to achieve this.

    .low-opacity-bg{
        background-image: url("/image.jpg");
        position: relative;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
        background:pink;
        background-repeat: no-repeat;
        background-size: cover;
    }
    

    We are adding an ::after pseudo element to our container,positioning and sizing it to fill the parent and giving it background color.

    But this will not work, the element will go on top of our container making the whole container look pink : example_image_2

    This is because of the stacking context, we can try giving the pseudo element a z-index:-1, but it will not be enough :

    .low-opacity-bg{
        background-image: url("/image.jpg");
        position: relative;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
        background:pink;
        background-repeat: no-repeat;
        background-size: cover;
        /*add z index*/
    	z-index: -1;
    }
    

    Now our container looks like this again:

    example_image_3

    This is because of the z-index, by assigning the z-index of -1 to our pseudo element we are telling it to go behind everything and we are unable to see it.

    This is the most important part of our approach, we will add the property isolation: isolate to our container, this tells the element to not creating a new stacking context, and any changes to the z-index that happens within this container should not affect any other element on the page.

    There are other ways to achieve isolating stacking context but in my experience this is the best approach since it does not cause any side effects on our page. If you are not familiar with this property you can learn more about it here.

    Our updated styles now looks like this :

    .low-opacity-bg{
        background-image: url("/image.jpg");
        position: relative;
    	/* added isolation */
        isolation: isolate;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
        background:pink;
        background-repeat: no-repeat;
        background-size: cover;
        z-index: -1;
    }
    

    and our app now looks like this :

    example_image_4

    Now our background color gets set correctly over our background, and we can also change the opacity of it now and it will work without any issues :

    .low-opacity-bg{
        background-image: url("/image.jpg");
        position: relative;
    	/* added isolation */
        isolation: isolate;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
        background:pink;
        background-repeat: no-repeat;
        background-size: cover;
        z-index: -1;
    	/*change opacity*/
    	opacity: 0.5;
    }
    

    and our div now looks like this :

    example_image_5

    We are now able to change the opacity of the color over the background, you can also use a gradient or any other content you wish using this approach.

    Changing Background Image Opacity

    We will now change the background image's opacity directly instead of adding a color or gradient over it and changing it's opacity. We will be continuing with the same code from the last example to achieve this behavior.

    Our updated styles looks like this :

    .low-opacity-bg{
    	/*removed background image from here*/
        position: relative;
        isolation: isolate;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
    	/*handling background here*/
        background-image: url("/image.jpg");
        background-repeat: no-repeat;
        background-size: cover;
        z-index: -1;
        opacity: 0.7;
    }
    

    We have simply moved the code for handling the background from the container to it's pseudo element and we have removed the background color from the pseudo element.

    Our page now looks like this :

    That's it !, we are now able to successfully change the background image's opacity of any HTML element we want.

    We can also cleanup our code a bit so we (or anyone else in our team) don't have to mess with the pseudo element every time we need to make changes in this code because it does not look very simple at first glance.

    Here is our updated styles :

    .low-opacity-bg{
        --bg-url: url("/image.jpg");
        --bg-opacity: 0.7;
        position: relative;
        isolation: isolate;
    }
    
    .low-opacity-bg::after{
        content: "";
        position: absolute;
        inset: 0;
        height: 100%;
        width: 100%;
        background-image: var(--bg-url);
        background-repeat: no-repeat;
        background-size: cover;
        z-index: -1;
        opacity: var(--bg-opacity);
    }
    

    We are using CSS variables for background image URL and it's opacity, now we only need to modify the container and not the pseudo element anytime we have to make changes to this code.

    Conclusion

    You should now be able to change background image's opacity of any element or adding a translucent color or gradient over it. If you are using a framework and you want to add a reusable component with different background images, you can add the image URL to the element as a data attribute and use it in CSS to achieve this.

    If you have any other doubts or if you have something to add to this don't hesitate to comment it below 😀.

    Share this:

    Category:

    frontend development

    Tags:

    0/3000