where's the salt?

04/27
2010

CSS transparency inheritance workaround (PHP & CSS3) (25,343 views)

Transparency Comparison
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 &raquo;

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>

CSS validated

Tags:

Date posted: Tuesday, April 27th, 2010 at 5:00 am (6 years, 11 months ago.)
Posted in: business mix, tech mix
Comments RSS Feed Comments RSS Feed
Reply
Ttrackback
About the author:

Nina Khoury is a software engineer, self-described geek and EVP of ninanet site solutions. She founded one of the first online agencies in Austria in 1997, taught at various universities for seven years and now lives in Sin City - Las Vegas, NV.

4 Responses to “CSS transparency inheritance workaround (PHP & CSS3)”

  1. 1

    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 Adu-Gyamfi on April 27th, 2010 at 1:12 pm
  2. 2

    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.

    nina on April 27th, 2010 at 1:30 pm
  3. 3

    […] 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 […]

    Tweets that mention CSS transparency inheritance workaround (PHP & CSS3) -- Topsy.com on April 27th, 2010 at 2:02 pm
  4. 4

    […] CSS transparency inheritance workaround (PHP & CSS3) […]

    30 Useful Web-Based Applications for Designers | Most Inspir | AboutBrowsers.info on April 29th, 2010 at 10:42 am

Leave a Reply


search

Categories

Send this to friend