CSS Guru: Clever CSS Tricks: Opacity

If you've ever wondered how to get a semi-transparent background box behind text using CSS without also making the text semi-transparent (and without resorting to absolute positioning or background images), wonder no more!  I've figured out a neat CSS trick to make this effect possible.

Today's installment of 'CSS Guru' is brought to you by the letter C, the letter S, another letter S, and the numbers #000; with special guest stars filter,-moz-opacity, and opacity.  



Thursday March 12 12:0 PM
3232 Blog     RSS Feed RSS
The 3232 Design Blog is here to help you with your small business marketing and graphic design needs. If you feel your needs are not being met, please post a comment and it will be answered in the order in which it was received.
CSS Guru: Clever CSS Tricks: Opacity
RSS Feed

If you've ever wondered how to get a semi-transparent background box behind text using CSS without also making the text semi-transparent (and without resorting to absolute positioning or background images), wonder no more!  I've figured out a neat CSS trick to make this effect possible.

Today's installment of 'CSS Guru' is brought to you by the letter C, the letter S, another letter S, and the numbers #000; with special guest stars filter,-moz-opacity, and opacity.  

Tiny Planets - 03/29/10
How to fly - 01/05/10

Show all blog entries

 

While I was working on the redesign for The Unincorporated Man last week I invented a nice CSS effect that I'd wondered about before but never had to figure out.  The background is fairly dark, and I wanted hovering semi-opaque boxes above it containing light-colored text.  Unfortunately, part of the background is also very light so I wanted this box dark, but when you add opacity to a div layer it applies the effect to everything in that layer.  Normally you'd set up an absolutely positioned box with some opacity on it, and then lay another div box on top and make sure the height and width match.    But I need my text fully opaque, and the boxes couldn't have a predefined size, and I didn't want to use an image for the background of this darker box.  How to accomplish this?

The trick is in using z-index and a container div.  The outside container defines any borders for the box, and inside the box are two sibling div layers, one with a lower z-index that has the background color and opacity, and another with a higher z-index containing the text.  

The outer container has position: relative, the width, and whatever placement on the page you want, float, absolute, anything.  it just needs position set so the inner div layers' positions are relative to it.  

"What the hell are you talking about?" you say.  Good question.  Allow me to digress.

When you give a div layer a position (either absolute or relative), it takes it's position cues from the first parent it finds that has a position defined.  So a div layer with absolute positioning inside a div layer without position will be absolutely positioned to the body of the document.  If you give the outer div layer a position, then the inner div layer will be absolutely positioned inside the outer div layer.

For example, let's say you have a div that is centered on your page without position defined.  Inside that is a div with absolute position top: 0 and left: 0.  This inner div will appear in the upper left corner of the page.  But if you give the outer div a position: relative, then the inner div layer will appear in the upper left corner of that div.

OK?  Can we move on?

Here's the opacity trick: You have your outer div with relative position, and two inner divs.  The outer div css looks like this: style="border: 1px solid green; overflow: hidden;".  The overflow is the key to this trick.  One of the inner divs is absolute positioned and has a background color of solid black and opacity of 35, a z-index of 1 and a height and width of 100%.  This positions the div in the upper-left corner and it extends beyond the left and right sides of the outer div though you can't see that because the outer div has its overflow hidden.

Then you have a div with the text in it.  This text div has the padding for the box, and all the content.  This div, since it is relatively positioned, will sit in the upper-left corner of the box, and the z-index will ensure placement above the background div layer.

Because this second content div is relatively positioned it will determine the size of the outer div; the outer div will grow with it, revealing more of the semi-transparent background as it does.

Here's the entire code block:

<div id="outerDiv" style="position: relative; border: 1px solid green; width: 500px;">

<div id="semiTransparentDiv" style="position: absolute; background-color: black; filter:alpha(opacity=35);-moz-opacity:.35;opacity:.35; height: 100%; width: 100%; z-index: 1;"></div>

<div id="contentDiv" style="position: relative; z-index: 2; padding: 10px; color: white; font-weight: bold;">here's where the text goes.  Height is determined by this text.  As this content box grows, so does the outer div layer. This content is not semi-transparent, or you would barely be able to read this text.</div>

</div>

Check it out in action here.

 

Comments
Nice CSS - Zainab, Monday, June 22 2009, 07:41 AM
Hey its a gr8 way of doing the opacity work.

Thank You - David Trammell, Friday, August 14 2009, 09:57 PM
Thank you so much. I have been looking for this solution for several days now and you have made it so clear and, provided a simple and perfect example. Thank you again. David Trammell

IE6 wierdness - Simon, Thursday, October 8 2009, 06:59 AM
Firstly, nice article and thanks for sharing. Whilst your opacity technique works in IE6 on www.theunincorporatedman.com, I have noticed some IE6 wierdness on the example link you provided at: www.3232design.com/misc/opacityTest.html. On your example, the 'semiTransparent' Div does not fill the entire 'outer' Div making the text within the 'content' Div unreadable. I've uploaded a screenshot showing this in IE6: http://mooch.pwp.blueyonder.co.uk/IE6_opacity_wierdness.jpg Thought I'd mention it. I've also noticed your example doesnt use [overflow: hidden] on the style applied to the 'outer' Div. I know in an ideal world we would all burn IE6 to a horrible death and move on but it is still widely used sadly.

Re: Ie6 wierdness - Richard, Thursday, October 8 2009, 05:57 PM
Holy crap, you're right. WTF? I could have sworn it used to work. IE6 steadfastly refuses to acknowledge a height in percentage. Well, the outer div now has overflow: hidden, and the background div is set to 10000px height. I'd probably do that via a conditional comment for IE6 only. Thanks for pointing this out. UPDATE: I just checked, and the reason it's right on IE6 is I'm doing exactly that: there's an overflow:hidden on the outer div, and the inside bg layer has a height specified. I hate IE6.

Add Your Comment:
Your Name:
Email Address or URL:
Title of Comment:
Comment Body: