Non-Transparent Elements Inside Transparent Elements

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>
</div>
And this is how you style it:
.bar {
height: 4em;
padding-top: 2em;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
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;
}









1
Nice one, Chris. You’ve always got more ‘trickery’ up your sleeve.
Stumbled!
Comment by Armen — December 8, 2007 @ 3:00 am
2
A much easier hack is to just set the background to a very small square of transparent png. Eg:
#bar{
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.
Tom
Comment by Tom — December 8, 2007 @ 4:44 pm
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.
Comment by Chris Coyier — December 8, 2007 @ 6:47 pm
4
Much more useful having the text staying opaque!!
Well done.
Comment by Jermayn Parker — December 11, 2007 @ 8:11 pm
5
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.
Comment by Alex — December 15, 2007 @ 6:12 am
6
safari seems to render it differently than in Firefox
Comment by ulee — December 16, 2007 @ 5:03 pm
7
just what i need!
beautiful
Comment by mo — January 14, 2008 @ 4:33 am
8
Good job! been trying to get my head around this for a long time….
Comment by will — January 14, 2008 @ 4:40 am
9
Will this work on images? I need to make an image non transparent in my opacity div
Comment by Jamie — January 15, 2008 @ 2:30 am
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.
Comment by Chris Coyier — January 15, 2008 @ 7:39 am
11
thank you
Non-Transparent Elements Inside Transparent Elements
is working with ie7 but nit with Mozilla
Please help
Comment by harminy — March 17, 2008 @ 2:27 am
12
Thank to share..I need sample non-Transparant image inside Transparent element bg….
Comment by Peter — April 10, 2008 @ 3:56 am
13
#bar{
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!
-Yep
Comment by Yep — April 25, 2008 @ 9:19 am
14
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…
Bye
Comment by Twiny — April 30, 2008 @ 9:15 am
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
please…
Comment by empe — May 15, 2008 @ 2:59 am
16
I have the same request as empe - I want transparent text, but opaque background. Is this possible?
Comment by black swan — May 15, 2008 @ 4:24 pm
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:
Comment by Chris Coyier — May 15, 2008 @ 7:21 pm
18
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.
http://www.karneval-berlin.de/de/
Comment by black swan — May 16, 2008 @ 7:05 am
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.
Comment by Chris Coyier — May 16, 2008 @ 7:19 am