I'm currently on parental leave till September 1st. Until then, I will not be available to read comments, e-mails, tweets and Facebook messages.

If you are interested in my writings, please subscribe to my RSS feed and follow me on Twitter.

CSS background transparency without affecting child elements, through RGBa and filters

Looking at the design of most web pages today, almost exclusively all of them include some semi-transparency of elements. However, getting the desired effect in CSS is harder than one might think.

The problem

If we want an element to have a semi-transparent background, and let whatever is behind it shine through, we have two options:

  • Using CSS and opacity
  • Creating a 24-bit PNG background image

The problem with using opacity in CSS, besides the annoying syntax to cater to all web browsers, is that not only the background of the element will have transparency, but all of its child elements as well. This means that any text within will have the same opacity, which I would dare to venture is very seldom the result one wants. You can cater to this problem with creating redundant elements, some tricky CSS positioning and such, but really, it’s a mess.

The problem with PNG images is, beside a superfluous HTTP request, that images are way, way more larger in file size than one or two lines of CSS code – especially considering that the image has to be a bit larger to avoid serious memory leak issues with 24-bit PNG images with alpha transparency in Internet Explorer.

The solution!

Therefore, I can happily offer an alternative for you: RGBa colors. The beauty in this is that you declare the normal RGB values + values for the level of transparency you want, resulting in a very easy way to declare transparency for a color. Making this happen with CSS, with a fallback for those web browsers that doesn’t support it, would look like this:

	.alpha60 {
		/* Fallback for web browsers that doesn't support RGBa */
		background: rgb(0, 0, 0);
		/* RGBa with 0.6 opacity */
		background: rgba(0, 0, 0, 0.6);
	}

The transparency will only be applied to the background – fantastic, isn’t it?! :-)

A little caveat

Shockingly enough (erm), no version of Internet Explorer supports RGBa colors (i.e. not IE 6, IE 7 or IE 8 at the time of this writing). However, and lucky for us, in year 2000 Microsoft went crazy with implementing various filters in IE. One of them are the gradient filter, and what we can do is use that and just define the same start and end color. “Ok, but how do I get the transparency”, you might be thinking now. The answer to that is that you will declare that as part of the color hex value. A CSS gradient filter achieving the same effect as the CSS code above would look like this:

	.alpha60 {
		filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
	}

As you can see, it is actually declared as part of an 8-digit hex value, where the first two numbers is the alpha hex value, the next two is Red, and so on. The difference between how we do it with RGBa is that the hex value will range from 0 to 255, just as any color value. So, how do we convert an alpha level of 0.6 to its hex value?

This where a little Math comes in the picture. Basically, we take our desired alpha level, 0.6, and multiplies it with 255 – then we convert that result into hex. One very easy way to do this is make use of Google’s Search Features, and just search google for 0.6 * 255 in hex. Unfortunately, though, Google’s calculator seems to only handle integers, hence 0.3 * 255 in hex won’t give you a result.

An alternative, or quicker way altogether, is to use the beauty of JavaScript. Just open up Firebug and type this into the console:

	// Replace 0.6 with your desired alpha level
	Math.floor(0.6 * 255).toString(16);

99 is then corresponding to 0.6, and becomes the first two digits of the start and end colors for the gradient filter.

Combining it all

With all techniques learned above, let’s put it together in a working CSS rule:

	.alpha60 {
		/* Fallback for web browsers that doesn't support RGBa */
		background: rgb(0, 0, 0);
		/* RGBa with 0.6 opacity */
		background: rgba(0, 0, 0, 0.6);
		/* For IE 5.5 - 7*/
		filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
		/* For IE 8*/
		-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
	}

NOTE! In addition to this, you have to declare background: transparent for IE web browsers, preferably served via conditional comments or similar!

Web browser support

RGBa support is available in:

  • Firefox 3+
  • Safari 2+
  • Opera 10

Filters in Internet Explorer are available since Internet Explorer 5.5.

This means that this will work for virtually everyone!

Acknowledgements

Thanks to RGBa Browser Support and Bulletproof, cross-browser RGBA backgrounds, today for the information and inspiration.

Thanks to Emil Stenström and Pelle Wessman for coming up with countless alternatives for hex conversion, and explaining basic math to stupid me. :-)

52 Comments/Reactions

  • #1 Gustaf Forsslund
    January 11th, 2010 at 13:10

    Ah, so that’s where those hex codes went. :) I figured you had something like this going on. Great idea and well done. I will surely use this quite soon.

  • #2 Florent V.
    January 11th, 2010 at 13:29

    In my tests, the opaque background fallback doesn’t work in IE6 and IE7. Probably not in IE8 either, but i didn’t check.

    By the way, did you test this solution for know issues with DirectX filters? Like necessity to have hasLayout=1, text that doesn’t render like the rest of the page’s text, and more?

  • #3 Emil Stenström
    January 11th, 2010 at 13:35

    Great article Robert. Will surely come to use in some of my coming projects. I’m sick an tired of having to use Photoshop when switching background colors of my site.

    And thanks for the link, I did nothing :)

  • #4 Gunnar Franklin
    January 11th, 2010 at 15:46

    Great post!
    Another crappy thing about IE is that if you set opacity or a gradient by setting this gradient-filter on a table-cellbackground for instance. The text you put inside this element will be rendered badly. You will see the difference if you use a gradient with the same color from start to end and put at text above it. If you do the same thing with just a plain background-color and no filter the text will render much more smoothly with antialias.
    I guess PNG is the safest alternative. But most boring and tedious…
    /gun-R

  • #5 Robert Nyman - author
    January 11th, 2010 at 16:11

    Gustaf,

    Yes, that explains my new-found hex fetish, right? :-)

    Florent,

    Thanks for pointing that out! For IE, through conditional comments or similar, the background has to be set to transparent (I have updated the blog post).

    In Lea’s blog post, she lists a number of possible shortcomings. And yes, having layout is necessary, there are some text problems (varying on context) etc.

    At the end of the day, though, I think it’s about mindset: as with any CSS in IE, you could either see it as a possibility (with some kinks to work out), or as a potential problem.

    Emil,

    Exactly, I think this can become really useful!

    Gunnar,

    Thanks!
    Absolutely, there are some drawbacks when it comes to rendering, with various results. I guess it’s all about weighing pros and cons together; the text might not be identical, but it will perhaps be good enough.

  • #6 Morgan Roderick
    January 11th, 2010 at 16:44

    Great post Robert!

    One thing to keep in mind for this approach, is that rendering in IE slows down to a crawl (if that’s even possible) when you’re using filters.

    Depending on your context, you might be killing your client-side performance if you start using filters. On the other hand, if your page is relatively simple, then this technique might just be the ticket!

    Knowing when to use which technique for IE seems to be key for success these days.

  • #7 Robert Nyman - author
    January 11th, 2010 at 17:30

    Morgan,

    Thanks!
    And yes, filters might have that effect in IE, but not all the time – it’s all about testing in the applicable context.

    And yes, IE testing and experience is definitely key. :-)

  • #8 Webdev Weekly #1 | samuli.hakoniemi.net
    January 13th, 2010 at 0:37

    [...] CSS background transparency without affecting child elements, through RGBa and filters [...]

  • #9 Paul
    February 15th, 2010 at 23:00

    Works perfick! Had previously thought that IE visitors would be stuck with a less pretty version. Thanks, (now to get those rounded corners working….)

  • #10 Robert Nyman - author
    February 16th, 2010 at 11:26

    Paul,

    Yes, the rounded corners are a little bit more tricky…

  • #11 biziclop
    February 25th, 2010 at 11:40

    I use this variaton, which fits into one declaration block:

    .transparentoid {
    background: #FF8040; /* solid color */
    background: rgba(255,128,64,0.125); /* transparent color */
    background: transparent !ie; /* clear solid background for ie */
    zoom:1; /* required for the filters */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040); /* IE5.5-7 */
    -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040)"; /* IE8 */
    }

  • #12 Robert Nyman - author
    February 25th, 2010 at 13:48

    biziclop,

    Absolutely. Personally, though, I try to stay away from CSS hacks in my main CSS code.

  • #13 biziclop
    February 26th, 2010 at 14:54

    Actually, my example shows solid background in IE8, because i didn’t test it :) , so don’t use it.

    This is the fixed example, which shouldn’t be used too, because ie9 may break it:

    .transparentoid {
    background: #FF8040; /* solid color */
    background: rgba(255,128,64,0.125); /* transparent color */
    background: transparent\9; /* clear solid background for ie */
    zoom:1; /* required for the filters */
    -ms-filter:”progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040)”; /* IE8 */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040); /* IE5.5-7 */
    }

    This example is more futureproof (apply the .MSIE class to the body tag somehow, or put it into a conditional css)

    .transparentoid {
    background: #FF8040; /* solid color */
    background: rgba(255,128,64,0.125); /* transparent color */
    }
    .MSIE .transparentoid {
    background: transparent;
    zoom:1; /* required for the filters */
    -ms-filter:”progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040)”; /* IE8 */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#20FF8040, endColorstr=#20FF8040); /* IE5.5-7 */
    }

    And one more thing, filters disable the font smoothing in explorer where they are applied, so you must choose your fonts carefully.

  • #14 Robert Nyman - author
    February 26th, 2010 at 15:49

    Absolutely, the font issue in Internet Explorer is one of it’s biggest problems, so be wary.

  • #15 Using CSS instead of images when coding your web design | RefreshTheNet
    April 21st, 2010 at 11:47

    [...] CSS Back­ground Trans­parency With­out Affect­ing Child Ele­ments, Through RGBa And Filters [...]

  • #16 CSS Transparency Sources | [Re]Encoded.com
    May 9th, 2010 at 19:05

    [...] browsers. These techniques will get you started, but it is not as simple as it seems. According to Robert Nyman, you may encounter a problem with a child element’s [...]

  • #17 Transparenzwert für den IE berechnen « F-LOG-GE
    May 12th, 2010 at 14:49

    [...] Robert Nyman beschreibt eine Methode, die schnell in Firebug funktioniert. In der dortigen Konsole gibt man eine kleine Zeile Javascript ein. Zur Umrechnung eines 30%igen Transparenzwertes (opacity: 0.3) lautet die Zeile: Math.floor(0.3 * 255).toString(16); [...]

  • #18 Me
    May 30th, 2010 at 20:57

    Very cool trick, helped me lots :D

  • #19 Shane
    June 23rd, 2010 at 13:44

    Exactly what I needed, thanks Robert!

  • #20 Robert Nyman - author
    June 26th, 2010 at 19:50

    Me, Shane,

    Great!

  • #21 fadi Kashou
    July 3rd, 2010 at 10:09

    Amazing one
    thank u

  • #22 Evgeny
    July 21st, 2010 at 12:38

    Or instead of using a gradient filter, you can use the Alpha filter directly. Has this syntax: progid:DXImageTransform.Microsoft.Alpha(sProperties).

    More info in the documentation http://msdn.microsoft.com/en-us/library/ms532967(VS.85).aspx

  • #23 cheminguyen
    July 27th, 2010 at 20:33

    It works like a charm! Thank you so much!!!!

Write a comment

Twitter reactions

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview