04/27
2010
CSS transparency inheritance workaround (PHP & CSS3) (15,351 views)
After many hours reading up on the caveats of transparency; after tabbing through many suggestions found on many websites, blogs and forums; after trying to create visible containers on top of invisible containers, changing positions from relative to absolute and back only to see layout go totally awry, I finally decided to create my own approach to display child elements that do not inherit the parent’s transparency setting.
This is not a fix for every single browser out there and for every possible scenario, but it’s working in IE > 6, Firefox 3+ and our current versions of Safari (4.0.3) and Opera (10.51).
(If you come up with a variation to make it work in additional browsers, please share your findings!)
First, the situation:
We have a background image and we want to make to container on top it semi-transparent (so the background image is still visible), but inside this nested container we have another item (an image, a div, etc) which we DO NOT WANT to be transparent.
The two images side-by-side show the desired result (left, image in nested container NOT transparent) and the actual result (right, image in nested container is transparent):
The code is as follows (simplified):
HTML:
Lorem Ipsum
<p>In id nulla vitae nisi aliquet blandit in facilisis tellus. Duis et mauris eget enim posuere commodo. Aliquam et leo augue. Sed ut diam lacus.</p>read more »
CSS:
.bgdiv { font-family:Arial, Helvetica, sans-serif; height:400px; width:400px; background:#ffffff url('[path-to-image]') top left no-repeat; padding:15px 0 0 0; } #content { min-height:340px; width:300px; background-color:#ffffff; /* for IE 8 - always needs to come first */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; /* for IE */ filter:alpha(opacity=85); /* for FF etc */ opacity:0.85; -moz-opacity:0.85 } .servicebox { width:200px; margin:20px auto; color:#666666; } .servicebox h1 { font-family: Century Gothic,Myriad Pro,Arial,Helvetica,sans-serif; font-size:16px; color:#bf31ad; margin:0 0 12px 0; width:200px; line-height:12px; padding:10px 0; border-bottom:1px solid #bf31ad; } .serviceimg { border:1px solid #bfbfbf; width:200px; overflow:hidden; margin:0; } .servicebox p { font-size:12px; margin:0; padding: 15px 5px 5px 5px; color:#222222; } .servicebox div.more { text-align:center; color:#ffffff; height:20px; width:100px; margin:5px 0 0 100px; font-size:11px; line-height:18px; background:url('[path-to-sprite]') 0 0 no-repeat; } .servicebox div.more:hover { background:url('[path-to-sprite]') 0 -20px no-repeat; color:#2c8819; }
Lines 12-14 are responsible for the transparency, we used -moz-opacity and opacity for Firefox, Safari, Opera, etc, and a filter for IE.
You can see everything that sits on top of (or inside) the "content" div automatically becomes transparent as well, no matter what you do. As mentioned above, we tried all suggestions we could find – to no avail.
Except for these:
IE 7: To make the images contained in the "servicebox"div opaque, simply add
.servicebox {position:relative;}
to the "servicebox"div. This won’t work in Firefox, etc, but it doesn’t hurt the layout either.
To make it work in Firefox, Opera & Safari, we had to make use of the color model in CSS3:
Instead of setting -moz-opacity and opacity for non-IE browsers, we added
#content {background-color: rgba(255, 255, 255, 0.85);}
to the "content" div, where the last part (0.85) sets the transparency/opacity level for that object only.
Although browsers that don’t understand CSS3 should ignore it and simple move on to the next step, we experienced weird behavior when simply adding to the style sheet.
So we tried conditional statements, but then the code didn’t validate and we had trouble with the explicit non-IE condition {sigh}.
The final result was probably the easiest one (naturally rgba only validates against CSS3, see below):
Detect the browser with PHP (very basic) and display the required declarations (or load a browser-specific stylesheet) based on the browser detection result.
<? $isIE6 = 0; $isIE7 = 0; $isIE8 = 0; $ie6 = "MSIE 6.0"; $ie7 = "MSIE 7.0"; $ie8 = "MSIE 8.0"; $browser = $_SERVER['HTTP_USER_AGENT']; if(stristr($browser, $ie6) !== false ) { $isIE6 = 1; // add any styles for IE 6 here // not really necessary // $style = ""; /* to add a browser-specific stylesheet for IE6, simply add this: $style = ""; */ } elseif(stristr($browser, $ie7) !== false ) { $isIE7 = 1; // add any styles for IE 7 here $style = " "; /* to add a browser-specific stylesheet for IE7, simply add this: $style = ""; */ } elseif(stristr($browser, $ie8) !== false ) { $isIE8 = 1; // add any styles for IE 8 here $style = " "; // to add a browser-specific stylesheet for IE8, simple add this: // $style = ""; } else { $isIE6 = 0; $isIE7 = 0; $isIE8 = 0; $style= " "; /* to add a browser-specific stylesheet for non IE6/IE7, simply add this: $style = ""; */ } ?>
Super-short version (active version on Demo page):
<? $browser = $_SERVER['HTTP_USER_AGENT']; $browsers = array("MSIE 6.0","MSIE 7.0","MSIE 8.0"); $styles = array("",".serviceimg2 {position:relative;}",".serviceimg2 {position:relative;}"); $msie= 0; for($x = 0; $x < count($browsers);$x++) { if(stristr($browser, $browsers[$x]) !== false) { $sstyle = $styles[$x]; $msie= 1; } } if($msie == 0 || !$msie) { $sstyle = "#content2 {background-color: rgba(255, 255, 255, 0.85);}"; } $style = " "; ?>
Insert $style (or its output) via shorthand PHP into your HTML code:
<head> [other important things go here] <?=$style;?> </head>
I think this is a lot of work for something that can be fixed using CSS only, without having to result to even conditional includes.
All you need to do is add one extra HTML mark up to achieve the effect. I hope this shows up correctly in this comment.
This content should be opaque
Basically, you simply create the overlay, then add two sub containers, one for the transperant background color (same size as overlay, width 100%, height 100%, top 0px, left 0px should do) and then add another for the actual non-transparent content.
Francis,
the HTML doesn’t show here, sorry. But you can post a link if you like.
The issue we ran into isn’t that simple, though, since the site we’re working on has one fixed background-image, one container that should be transparent and many other containers on top of it that should not be transparent.
[…] This post was mentioned on Twitter by ninanet. ninanet said: CSS transparency inheritance workaround (PHP & CSS3) http://bit.ly/9Yx97I #css #CSS3 #inheritance #opacity #rgba […]
[…] CSS transparency inheritance workaround (PHP & CSS3) […]