Grow your CSS skills. Land your dream job.

Non-Transparent Elements Inside Transparent Elements

Published by Chris Coyier

Reader Shane left a comment:

If using transparency on a block element it makes the text inside transparent as well. Is there a way I can prevent that from happening? I tried putting the text in another div and setting the opacity to 100%, but that didn't do the job. Although, logically, I thought it would!


Logically, that makes sense to me to. Is that how it works in practice? Of course not. This is, in my opinion, a major failing of CSS. People just expect that this is possible. It's a very common effect in print design. Unfortunately, it's just not so easy on the web. Here is one way out of this mess.

First, you create a bar making sure to use the CSS settings for all browsers. Here is the bar:

<div class="bar">
  <h2>Some mild-mannered text trapped inside a bar.</h2>

And this is how you style it:

.bar {
  height: 4em;
  padding-top: 2em;
  opacity: 0.5;
  background: black;
  border-top: 3px solid #ccc;
  border-bottom: 3px solid #ccc;
  margin-top: 5.0em;

This is where you notice that the text inside the bar as taken on the transparency of the bar itself. You don't want that, it's making the text hard to read! So you get smart and apply 100% transparency to the text inside the div. Doesn't work right?

You'll have to resort to some trickery.

As far as I know, there is just no way to force those child elements to be an less transparent than their parent element. And therein lies the solution. What if that child element wasn't technically a child element.

As you likely know, just because an element occupies the same space as another element, doesn't make one a child of the other. That's the beauty of CSS positioning. So the trick to getting our non-transparent text into a transparent div is just to put that text outside of the div and push it visually inside with some CSS positioning.

Here is how we'll do it:

<h2 class="ontop">Haha! I'm free of my transparent prison.</h2>
<div class="bar"></div>

Notice the class applied to the text. Now you're going to have to do whatever you need to do with CSS positioning to get it where it needs to be. Negative margins are a popular way to do this. Here I just set the top position:

h2.ontop {
  position: relative;
  top: 4.7em;

View Demo


  1. Permalink to comment#

    Nice one, Chris. You’ve always got more ‘trickery’ up your sleeve.


  2. Permalink to comment#

    A much easier hack is to just set the background to a very small square of transparent png. Eg:

    background: url('black50.png');

    Sure it’ll take a browser a few nanoseconds longer to load but it saves hassle. I keep a library of different transparency pngs in the most common colours for when I’m designing.


  3. @Tom: That’s a nice little trick! That actually would work perfectly here with the bar solution since it’s a solid color. Really, utilizing image transparency instead of CSS transparency is a good solution to any version of this problem. It kind of opens the door to needing to use PNG hacks to guarantee results but that’s fine.

  4. Much more useful having the text staying opaque!!
    Well done.

  5. Alex
    Permalink to comment#

    A PNG would provide better compatibility (you have to use a filter: statement for IE6, but you’re already doing that anyway), but the better CSS3 method is just to use RGBA colours (e.g. background: rgba(0,0,0,0.5); will get you black at 50% alpha), that gets rid of any inherited opacity.

    • Cowgirl
      Permalink to comment#

      Neat solution!
      This solution also works when you don’t know the size of the element you’re working with, it is easy and fast.
      Thanks for the hint!

  6. ulee
    Permalink to comment#

    safari seems to render it differently than in Firefox

  7. Permalink to comment#

    just what i need!
    beautiful ;)

  8. will
    Permalink to comment#

    Good job! been trying to get my head around this for a long time….

  9. Jamie
    Permalink to comment#

    Will this work on images? I need to make an image non transparent in my opacity div

  10. @Jamie: Sure, it’ll work for images, perhaps it’s even easier since you typically know the exact height and width of images so you know exactly how much offset you will need.

  11. harminy
    Permalink to comment#

    thank you

    Non-Transparent Elements Inside Transparent Elements
    is working with ie7 but nit with Mozilla
    Please help

  12. Peter
    Permalink to comment#

    Thank to share..I need sample non-Transparant image inside Transparent element bg….

  13. Yep
    Permalink to comment#

    background: url(‘black50.png’); /* <– Much better, more versatile */

    Just used that, and Yep, by using it, you do not have to worry one bit about nested divs inheriting the transparency of any parent div. Thanks a bunch!


  14. Twiny
    Permalink to comment#

    Some will say that im a pain in the ***, i already had this problem, solved it, but…
    there’s always a but.

    Here is what i did not solve :
    what if you have a div which contains a paragraph, and of course, you need to apply transparency to div’s background and keep the paragraph’s text non-transparent ?
    You will tell me, easy : use the method you used before !
    You just can’t if you choose to size your div with your paragraph element’s size, unfortunately i have to (web is dynamic !)

    I thought i could re-write a second time the paragraph’s content, over the first (that takes transparency) so i would have some non-transparent text; but i’m not happy with having two times the same content in my Html code…

    So if anyone has an idea on how to fix this, i’d be glad to hear it…


  15. hi dude,

    i want the box with opacity but text inside content is without opacity.

    i want color of text is white, and the result of box with opacity is the color of text is not white


  16. black swan

    I have the same request as empe – I want transparent text, but opaque background. Is this possible?

  17. @empe: That’s what this article explains how to do.

    @black swan: You are asking for the opposite thing. Fortunately, this is easier. Just set the opacity of the text, not it’s container. As in:

    p.transparent-text {
        opacity: 0.5;
  18. black swan

    Thanks for your reply, but I don’t think I explained myself properly in my last post.

    I have a background picture, and text with a background colour on top of that. When I try to make the text transparent, the color of the background colour shows through – but I want the *background picture* to show through.

    An example of the effect I want is shown at the website below, but that is using graphic files, not css. I am not sure if what I am aiming for is possible using css, but when I came across your thread I thought it wouldn’t hurt to ask.

  19. @black swan: Yes I see what you mean now. That’s not gonna happen with CSS. That is a knockout, not transparency. Pretty neat effect though.

  20. rhythm

    Do you think it is possible to use this to create a transparent hover effect?.. I have seen one with java script. its pretty.

  21. Krists

    Please delete my previous comment.


    [div style=”border: 1px solid black;”]
      [div style=” float:left”]bla bla bla..[/div]
      [div style=”background-color: #91E391; opacity: 0.2″ ]{whitespace here}[/div]

    ..another good way how to get the same effect?

  22. hachaifair
    Permalink to comment#

    Actually the behavior of inheriting transparency is perfectly logical.
    You specify in your css that some block is not entirely opaque, you don’t specify the opacity of only it’s background (which you could do with css3 rgba colors or a transparent png as previously said). In practical terms, the whole block (including the text) is painted on a separate canvas, then this canvas is drawn over the parent block with the specified opacity.

    This is exactely like layers in drawing softwares, if you specify the opacity of the layer, you affect everything inside that layer (including sublayers). If you want something drawn over it with more opacity, you create a separate layer over it to put your opaque content (which is exactely what you did with your additional div).

  23. muztang
    Permalink to comment#

    nice men ;)

  24. Permalink to comment#

    is there a way to make it so EVERY image i ever post on my blog will not go transparent automatically. I’m VERY new to this so laments terms would be greatly appreciated.

    At the moment i only have 1 picture on my blog but it’s background is white and it being see-through really makes it harder to understand

  25. anthony alexander
    Permalink to comment#


    exactly, ever since they introduced the opacity attribute ive used this technique. except i use a container div and relatively position the elements then give each its own opacity. i thought this was obvious

  26. Permalink to comment#

    Using RGBA is a snap, thanks! But is there an easy hack for IE6/IE7?

  27. The png works better for me too, at least when all you want to do is to put a transparent background for your container (image, text, image(s) + text, etc…).

  28. Matt
    Permalink to comment#

    I like the PNG idea, but how exactly does one create a PNG image with 50% transparency? I’ve created such an image in Paint Shop Pro, but when I save it as a PNG the image is saved with no transparency.

  29. Joey
    Permalink to comment#

    I tried the PNG trick. works well in firefox, not working in IE 6….

  30. An angry Micky
    Permalink to comment#

    Well, well, well, looks like this little trick may be useful for some of us… but I’m trying to use it on a div that should slide in & out and it doesn’t work at all :/ who the hell said “yeah, nested divs should follow the transparency”?? That’s stupid, godammit.

    • You cannot use this “trick” when you are attempting to slide objects within a container using an “overflow:hidden” declaration — true. However, you can also work around this problem, simply by creating a pseudo :after or :before element, making it relative position to the parent, then adjust its opacity and place it with CSS accordingly. Worked like a charm for my use-case.

  31. Dallin
    Permalink to comment#

    I visit your site all the time. Thanks all the good content! It has helped me become a better programmer and saved me lots of time!


  32. AM

    You can also assign a 1px x 1px transparent image to the div, so you can forget about relative/absolute positioning.

  33. AM

    This is maybe an old post, but assigning a color to the div like rgba(255,255,255,0.5) also does the trick (just figured it out)

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".