By jmohr


2011-02-14 21:30:38 8 Comments

Is it possible to set the opacity of a background image without affecting the opacity of child elements?

Example

All links in the footer need a custom bullet (background image) and the opacity of the custom bullet should be 50%.

HTML

<div id="footer">
    <ul>
        <li><a href="#">Link 1</a></li>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Link 3</a></li>
        <li><a href="#">Link 4</a></li>
        <li><a href="#">Link 5</a></li>
    </ul>
</div>  

CSS

#footer ul li {
    background: url(/images/arrow.png) no-repeat 0 50%;
}  

What I've Tried

I tried setting the opacity of the list items to 50%, but then the opacity of the link text is also 50% - and there doesn't seem to be a way to reset the opacity of child elements:

#footer ul li {
    background: url(/images/arrow.png) no-repeat 0 50%;
    /* will also set the opacity of the link text */        
    opacity: 0.5;
}

I also tried using rgba, but that doesn't have any effect on the background image:

#footer ul li {
    /* rgba doesn't apply to the background image */
    background: rgba(255, 255, 255, 0.5) url(/images/arrow.png) no-repeat 0 50%;
}

14 comments

@kaleazy 2018-01-10 22:26:43

Another option is CSS Tricks approach of inserting a pseudo element the exact size of the original element right behind it to fake the opaque background effect that we're looking for. Sometimes you will need to set a height for the pseudo element.

div {
  width: 200px;
  height: 200px;
  display: block;
  position: relative;
}

div::after {
  content: "";
  background: url(image.jpg);
  opacity: 0.5;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  position: absolute;
  z-index: -1;   
}

@Stickers 2017-01-15 16:06:45

You can use CSS linear-gradient() with rgba().

div {
  width: 300px;
  height: 200px;
  background: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.5)), url("https://i.imgur.com/xnh5x47.jpg");
}
span {
  background: black;
  color: white;
}
<div><span>Hello world.</span></div>

@Sean Pianka 2017-03-15 21:37:29

Thank you, this worked wonderfully for me and would be the accepted answer had I asked this question first.

@rockyraw 2017-04-27 22:45:32

this is a great answer!

@Squapl Recipes 2019-05-28 15:45:29

this is the clean solution for my situation too. kudos

@Jotan 2019-11-27 12:58:16

what a hack. Nice!

@Reyraa 2013-06-20 12:31:53

Unfortunately, at the time of writing this answer, there is no direct way to do this. You need to:

  1. use a semi-transparent image for background (much easier).
  2. add an extra element (like div) next to children which you want the opaque, add background to it and after making it semi-transparent, position it behind mentioned children.

@Jakir Hossain 2015-02-24 07:15:47

#footer ul li
     {
       position:relative;
       list-style:none;
     }
    #footer ul li:before
     {
       background-image: url(imagesFolder/bg_demo.png);
       background-repeat:no-repeat;
       content: "";
       top: 5px;
       left: -10px;
       bottom: 0;
       right: 0;
       position: absolute;
       z-index: -1;
       opacity: 0.5;
    }

You can try this code. I think it will be worked. You can visit the demo

@Mr Griever 2011-02-14 21:46:15

If you are using the image as a bullet, you might consider the :before pseudo element.

#footer ul li {
}

#footer ul li:before {
    content: url(/images/arrow.png);
    filter:alpha(opacity=50);
    filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
    opacity:.50;
}

@Hussein 2011-02-14 21:48:16

Filter is only an IE solution

@thirdender 2013-08-31 18:34:16

I think this is probably the best solution. It is a pure CSS solution. It's also possible to hack IE7 support using *zoom: expression( … ); (see :after and :before css pseudo elements hack for IE 7), but IE7 is finally becoming passé.

@Zied Hamdi 2014-05-17 08:51:09

You can put the image in the div:after or div:before and set the opacity on that "virtual div"

div:after {
  background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/owl1.jpg);
  opacity: 0.25;
}

found here http://css-tricks.com/snippets/css/transparent-background-images/

@user 2014-02-02 23:36:15

#footer ul li {
  position: relative;
  opacity: 0.99;
}

#footer ul li::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -1;
  background: url(/images/arrow.png) no-repeat 0 50%;
  opacity: 0.5;
}

Hack with opacity .99 (less than 1) creates z-index context so you can not worry about global z-index values. (Try to remove it and see what happens in the next demo where parent wrapper has positive z-index.)
If your element already has z-index, then you don't need this hack.

Demo of this technique.

@zVictor 2014-05-03 10:18:01

Do you know why we need to set a less than 1 value for opacity? Is it a cross-browser solution?

@user 2014-05-03 14:55:28

@zVictor yes, this is w3c-standardized behavior. See Understanding CSS z-index: The stacking context.

@2ToneKenobi 2012-08-02 23:37:13

Take your image into an image editor, turn down the opacity, save it as a .png and use that instead.

@Alex 2012-11-07 15:56:21

Hmm... i just downvoted, but look at this accepted answer: stackoverflow.com/a/6502295/131809 upvoted 10 times, and pretty much identical.

@RobW 2012-11-28 21:17:34

This is a good option, no idea why so many downvotes. If I could upvote this twice I would. A child element of a partially opaque parent element is going to be partially opaque, and should be. All "workarounds" are bugs that should eventually be fixed.

@mystrdat 2012-12-11 15:44:32

It is not a "good" option as it fires +1 http request and needs to load additional data.

@brad 2013-02-22 04:47:21

@mystrdat You're already downloading the image, this isn't an extra request.

@mystrdat 2013-02-25 13:21:40

@brad You don't need to download an image at all, that's the point.

@brad 2013-03-02 21:17:31

@mystrdat But he is already downloading the arrow image. You haven't provided a non-image solution, so that was my point. He's already downloading the arrow image, it might as well come as needed, which would not be an extra request. I'm not understanding where you're coming from.

@mystrdat 2013-03-05 16:54:06

@brad I apologize, turns out I've read the question wrong now that I checked again.

@mystrdat 2013-03-05 17:00:07

This will work of course, but as for opacity, I would vote for using the image inside a separate span/div inside the li tag and just applying opacity to it instead of the solution above (or pretty much all of them here) as that leaves some fine animation options opened and doesn't require any hardcode resource editing.

@master_gracey 2013-07-11 03:16:47

What if you're working with dynamically updated images? Poor solution.

@Ionică Bizău 2013-08-31 17:53:32

What about Linux users? We don't have Photoshop. I edited your answer. :-)

@abalter 2013-09-20 20:23:37

This is not the right answer. It works in some sense, but does not allow one to play around with the opacity except for making a slew of images. This should be able to be done with css.

@cptnk 2014-02-11 16:19:12

On the other hand this is quite usefull when you create modal windows.

@Mark Lalor 2015-08-25 04:53:24

Well, the sad but straight truth!

@lyubeto 2013-02-21 09:40:09

The "filter" property, needs an integer for percentage of opacity instead of double, in order to work for IE7/8.

filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);

P.S.: I post this as an answer, since SO, needs at least 6 changed characters for an edit.

@code-sushi 2012-12-12 01:31:13

To really fine-tune things, I recommend placing the appropriate selections in browser-targeting wrappers. This was the only thing that worked for me when I could not get IE7 and IE8 to "play nicely with others" (as I am currently working for a software company who continues to support them).

/* color or background image for all browsers, of course */            
#myBackground {
    background-color:#666; 
}
/* target chrome & safari without disrupting IE7-8 */
@media screen and (-webkit-min-device-pixel-ratio:0) {
    #myBackground {
        -khtml-opacity:.50; 
        opacity:.50;
    }
}
/* target firefox without disrupting IE */
@-moz-document url-prefix() {
    #myBackground {
        -moz-opacity:.50;
        opacity:0.5;
    }
}
/* and IE last so it doesn't blow up */
#myBackground {
    opacity:.50;
    filter:alpha(opacity=50);
    filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
}

I may have redundancies in the above code -- if anyone wishes to clean it up further, feel free!

@thirdender 2013-08-31 18:41:49

It's unnecessary to target each browser separately, just use the browser prefixes inside a single selector block. With the browser prefixes, the browser will only use only the appropriate CSS property. As time goes on and the syntax for that property becomes standardized, browser vendors will drop support for the prefixes and use the CSS property without any prefix (for example, Firefox dropped support for -moz-border-radius in Firefox 13 and just looks for the standard border-radius property now). IE7 and IE8 are a different story, but that's just IE :-p

@code-sushi 2014-05-19 22:03:16

I'd like to know who down voted this and why, please. The vote is useless without informative feedback. I'd like to be able to improve my answers. If it was just because the info was outdated please check the date. :) Thanks.

@BoltClock 2014-08-31 06:47:52

@code-sushi: If the downvote occurred at around the same time as your comment, consider that it might have been from someone else who happened to agree with thirdender's comment (notice the upvotes on the comment itself). I did not vote on your answer but I have to agree - I'd like to add that 1) KHTML will never see the -khtml-opacity because it doesn't understand the media query, rendering it useless 2) IE is more stable than you think; it won't "blow up" just because you add non-IE prefixes to a rule that applies to IE. The problem, at the time you faced it, must have come from elsewhere.

@code-sushi 2014-09-02 19:49:01

My original answer was from nearly 2 years ago and the down vote occurred recently, like this year. I was just curious. As for the IE comments they pertained to 7 when that still needed support; I'm pretty sure it's OK now in most cases to ignore IE 7 these days. Thanks for your feedback.

@Francisco 2012-11-15 15:15:59

I found a pretty good and simple tutorial about this issue. I think it works great (and though it supports IE, I just tell my clients to use other browsers):

CSS background transparency without affecting child elements, through RGBa and filters

From there you can add gradient support, etc.

@Francisco 2015-01-07 19:57:27

Well, it won't work directly. You would need to put a div as aparent element with background-color: (255,255,255,0.5) for instance

@Hussein 2011-02-14 21:41:17

This will work with every browser

div {
 -khtml-opacity:.50; 
 -moz-opacity:.50; 
 -ms-filter:"alpha(opacity=50)";
  filter:alpha(opacity=50);
  filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
  opacity:.50; 
}

If you don't want transparency to affect the entire container and its children, check this workaround. You must have an absolutely positioned child with a relatively positioned parent.

Check demo at http://www.impressivewebs.com/css-opacity-that-doesnt-affect-child-elements/

@nsantorello 2012-02-06 16:44:26

I think you need to change the ” quotes in the above code to " in order for it to work when straight copy-pasted.

@govinda 2012-05-14 19:58:33

is this answer still the best solution people have found to the problem of: "how to make a child element not inherit the parent element's CSS opacity value"? I need the child to really be a child.. and in the document flow... and also do not want to bring in javascript/flash for this; prefer pure CSS.

@govinda 2012-05-14 21:11:28

I have 50% opaque parent <li>'s containing child images which I want 100% opaque. Setting the <li> to position:relative; and the img to position:absolute; does NOT allow me to override the inherited opacity on the img, and I can't use absolute positioning for the <li>'s themselves (that's a mess ;-). In Javascript I tried imgs[i].style.opacity = '1';, but that also does not work to override the inherited opacity. If I understand correctly, I also can't use rgba because I need to affect the imgs themselves, not just a background color. Anyone have a recommendation for me?

@BoltClock 2014-08-31 06:41:13

This entire answer makes no sense. The given code, on top of being precisely what the asker does not want to do because it doesn't work, does not match the description, or the link. I'm having a very hard time understanding why so many people have upvoted it.

@lharby 2019-04-25 09:52:30

If the question was 'How to set 50% transparency on an element', this would be a good answer.

@Undefined 2011-02-16 01:07:26

Just to add to the above..you can use the alpha channel with the new color attributes eg. rgba(0,0,0,0) ok so this is black but with zero opacity so as a parent it will not affect the child. This only works on Chrome, FF, Safari and....I thin O.

convert your hex colours to RGBA

@Torsten Walter 2012-08-02 23:41:18

This won't work with the background-image as requested by the OP.

@Minkiele 2011-02-14 21:39:32

If you have to set the opacity only to the bullet, why don't you set the alpha channel directly into the image? By the way I don't think there is a way to set the opacity to a background image via css without changing the opacity of the whole element (and its children too).

Related Questions

Sponsored Content

16 Answered Questions

28 Answered Questions

[SOLVED] How do I give text or an image a transparent background using CSS?

  • 2009-04-30 09:00:02
  • Stijn Sanders
  • 1513415 View
  • 2218 Score
  • 28 Answer
  • Tags:   html css opacity

8 Answered Questions

[SOLVED] Can you set a border opacity in CSS?

  • 2010-10-31 05:48:53
  • mcbeav
  • 574581 View
  • 387 Score
  • 8 Answer
  • Tags:   css opacity

7 Answered Questions

[SOLVED] Opacity of div's background without affecting contained element in IE 8?

2 Answered Questions

[SOLVED] Setting opacity on only background image with rgba()

3 Answered Questions

[SOLVED] CSS opacity and child elements

Sponsored Content