Simple cross-browser CSS transparency

Simple cross-browser CSS transparency

Posted 23 March 2009 by Russ in CSS. Tags: , .

CSS transparency can be a pain, particularly in legacy browsers like IE6. This article covers a simple technique to achieve cross-browser transparency without JavaScript or an HTC fix.

Whilst there are different ways of achieving transparency, such as the HTC fix for PNG images, when you simply need an element on your page to be semi-transparent so that you can see the background behind, the approach below should serve you well.

Each of these examples uses the image below, which is shown here as a refererence:

Photo of leaves used as an example

Transparent background and content

All modern browsers recognise the opacity filter so this is our starting point. IE uses a different style declaration to the rest of our target browsers so our basic CSS class for a transparent element looks like this:

.transparent {
	background: #FFF;
	opacity: .50;
	filter: alpha(opacity=50);
	width: 100% !important;
	}

The background and opacity values could be anything you need but I’m setting these to white and 50% by default as this give us an effect that works well in may situations. The two opacity declarations are for different browsers: filter for IE, opacity for everybody else. The need for a width declaration is an odd one; without it, IE6 doesn’t invoke the filter so make sure you have a width set.

Here’s an example showing the background image and a paragraph of text overlaying it with the default 50% tranparency:

<p class="transparent">This text is inside a paragraph element with the classname .transparent and should have a transparency value of 50%. The opacity should change when you roll over it.</p>

This text is inside a paragraph element with the classname .transparent and should have a transparency value of 50%

You could say that there’s an issue with this though in that although we’ve achieved a transparent background, we’ve also made the text inside the block transparent too. You could equally say this is exactly what you want; for example you might want the transparency to change on rollover, which could simply be achieved by adding the the following psuedo class that adjusts the opacity on rollover (I’ve added a cursor for good measure):

.transparent:hover {
	opacity: .80;
	filter: alpha(opacity=80);
	cursor: pointer;
	}

(If you’re looking to do this for IE6 you’ll need to make sure the :hover pseudo class is on a link element rather than a paragraph or any other element.)

This text is inside a paragraph element with the classname .transparent and should have a transparency value of 50%. The opacity should change when you roll over it.

Setting the opacity of the element makes the whole element – background and content – transparent, so we need another solution if we want a transparent background and opaque text.

Transparent background, opaque content

As shown above, setting the opacity of the element makes the whole element transparent so any child elements will be transparent too. So if we want opaque elements showing on top of transparent elements, we need to keep the two elements in their own node in the DOM.

In the example above, we had a single transparent paragraph element with text. As the text is a node of the paragraph, the transparency is inherited but the same would apply to any nodes in more complex markup. Take a look at the wireframe here:

Wireframe of example 1

The content element is a child of the transparent element and is therefore itself transparent. What we need is something like this:

Wireframe of what we want

As the content element is not a child of the transparent element, it will be fully opaque. All that’s left to do is style this so that the content sits on top of the background element, which we can achieve reliably by adding a wrapper around both elements as follows:

Wireframe of what we'll need to achieve this effect

The semantic XHTML for this should be something like this:

<div class="transparent_wrapper">
<div class="transparent transparent_bgrd"></div>
<p class="opaque_content">The text is inside a paragraph with the classname .opaque_content and should be opaque on top of the transparent background elemnent.</p>
</div>

The empty div inside the wrapper will contain the transparent background and the content element (in this case a paragraph but this could be any element) needs to be positioned on top of the background, which we can achieve with CSS as follows, which I’ll go through step by step…

The transparent background element

The background (colour or image, depending on your needs) needs to sit under the content so we start off by setting its position absolutely. By default browsers assume an absolute element should sit 0 from the top and left so we don’t need to declare these properties, however we do need to ensure that the background appears underneath the content, so we set the z-index to be 1.

Assuming we want to reuse this technique for a multitude of designs and layouts, we need to make sure the background scales as the content size increases. To do this we set a 100% height for modern browsers, and a pixel value for IE6, which struggles with the 100% declaration (I’ve used 9000px here which will more than comfortably cover anything I need). We can do this in one selector by declaring 100% as the height first with the !important declaration. After this we add the pixel value for IE6. Modern browsers will obey the !important declaration but IE6 incorrectly ignores it, so we’ve achieved everything we need without any complicated hacks.

.transparent_bgrd {
	position: absolute;
	z-index: 1;
	width: 100%;
	height: 100% !important;
	height: 9000px;
	}

The opaque content element

The content element is simple. It simply needs to overlay the background element within the wrapper, which we can achieve simply by setting a higher z-index value and a relative top position of 0px. We could use absolute positioning but the benefit of using relative positioning is that the wrapper (and therefore the 100% height transparent background element) will scale according to the height of the content.

.opaque_content {
	position: relative;
	top: 0;
	z-index: 2;
	}

Wrapping it all up

The wrapper acts as a bounding box for the two child elements. The first thing to do with the wrapper is to set it to position:relative to ensure that the child elements will take coordinates according to this wrapper element. For IE6 to render the background reliably when the content scales, we also set the height of the wrapper to 100% and set the overflow value to hidden to ensure whatever remains of the 9000px setting declared in the background element is hidden from view.

We also want to ensure that the wrapper can be used for any content

.opaque_content {
	position: relative;
	top: 0;
	z-index: 2;
	}

Here’s the updated example using this approach:

 

The text is inside a paragraph with the classname .opaque_content and should be opaque on top of the transparent background elemnent.

Download and customise the source code

The background image used in the examples above is only 125px high, so obviously it’s not good enough to use as a background image on large elements; it’s simply used here as an example. You could just as easily use a background colour instead of an image. I find the best approach is to keep the core styles in my master stylesheet and then add specific styling to each element that uses it. You can grab the complete set of examples and core code in the source code for this example.

Browser compatibility

Browsers * Fully tested
Firefox 3 Yes
Firefox 2 Yes
Internet Explorer 8 Beta Yes
Internet Explorer 7 Yes
Internet Explorer 6 Yes
Safari 3 Yes
Google Chrome 1 Yes
Opera 10 Yes

2 Responses to “Simple cross-browser CSS transparency”

  1. Stephen Siu

    03. Jun, 2009

    Wow, thanks a lot for the tutorial. I’m working on a site that requires an image background with content overlayed on top over an opaque shade. This helped a lot in understanding how to make it happen.

    Reply to this comment
  2. Shelly

    17. Jan, 2010

    Thankyou so much for this article!

    Reply to this comment

Leave a Reply