November 17, 2009 3

Roy.G.Biv alpha

By in css

I was recently on a project that called for a translucent background color over a an image similar to this:

rgba http://www.flickr.com/photos/yeowatzup/ / CC BY 2.0

Of course, being the conscientious web developers we are, we want to be as semantic as possible with our markup. This means that text should be marked up as text and not flattened into the image, forever to remain hidden from the world of web spiders, search engines, assistive technologies, and mash-up artists. We give the text a background color to keep the text readable over the background image but we still want the background image to be slightly visible through the text area. Before RGBa, we would resort to a 1 x 1px translucent PNG but this adds additional overhead (both with the extra HTTP request, the maintenance of the image should the color change, and a PNG fix for IE6). Another option would be the CSS opacity property. Unfortunately, the opacity property applies to an element and all of its descendants. This means the text itself would become translucent as well, something we would like to avoid if possible. So, let’s use some RGBa!

First, add the standard RGB background color so the text block will still be legible in browsers that don’t support RGBa:

  div {
    background: rgb(100, 100, 183);
  }

Now we can enhance this for conforming browsers:

  div {
    background: rgba(100, 100, 183, .75);
  }

We now have support in Firefox 3+, Webkit (Safari 3+, Chrome 1+). What about that other browser? To add support for IE6-IE7, we need to use IE’s proprietary filter property. As this is a proprietary property, it should be included via an IE-only stylesheet referenced using Conditional Comments.

  div {
    background:transparent;
    filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#BF6464B7,endColorStr=#BF6464B7);
    zoom: 1;
  }

A bit of an explanation is in order. First we set the background to transparent which overrides the solid color rgb declaration. Next we apply IE’s proprietary filter. Notice we set the startColorStr and the endColorStr to the same values. These values are not your standard HEX values. Instead of 0xRRGGBB, the first 2 digits are the alpha transparency. Converting our 75% into HEX (.75 * 255 –> 191.25 –> 0xBF). Lastly, we apply the zoom property to trigger hasLayout on the element. This is required for the filter to take effect.

Keen observers will note that the filter property is not supported in IE8 standards mode. As IE8 now properly follows the CSS grammar, we must add the vendor prefix and quote the value. The hasLayout trigger is no longer needed.

  div {
    background:transparent;
    -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#BF6464B7,endColorstr=#BF6464B7)";
  }

Combined, we have our main CSS:

  div {
    background: rgb(100, 100, 183);
    background: rgba(100, 100, 183, .75);
  }

and IE’s CSS:

  div {
    background:transparent;
    filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#BF6464B7,endColorStr=#BF6464B7);
    -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#BF6464B7,endColorstr=#BF6464B7)";
    zoom: 1;
  }

We have now achieved cross-browser, CSS-only (no PNGs needed), alpha transparency!

 
 

Tags: ,

3 Responses to “Roy.G.Biv alpha”

  1. Steve Horn says:

    Nice tip! Transparent div over an image thing is something I’ve had to do a few times. This is a much better approach than what I was using.

  2. pen says:

    great fix – for some reason my rgb just wouldnt work in IE6 – and I didn’t want an image instead. Your fix has sorted it, though Im a bit clueless how to calculate other alpha values, I know the color is easily changed.

    “These values are not your standard HEX values. Instead of 0xRRGGBB, the first 2 digits are the alpha transparency. Converting our 75% into HEX (.75 * 255 –> 191.25 –> 0xBF)..”

    Any guidance on that appreciated. Thanks!

  3. jasonkarns says:

    RGB values in CSS are declared in the range 0-255 for each color (R: 0-255, G: 0-255, B: 0-255). HEX values are the same 0-255 values but converted to hexadecimal (base 16). Rather than 0-9, the digits are 0-F (where F in HEX is equal to 15 in decimal). So 0xFF (prefix 0x denotes a HEX number) is 255 (the highest value that can be represented with 2 HEX digits).

    So let’s say we want black with an opacity of 50%. The standard rgba notation is (0, 0, 0, .5) where the alpha is specified as a decimal percentage. To convert that to HEX, we first need to rescale the percentage (which is on a scale of 0-100) to a scale of 0-255. Multiplying .5 by 255 will give you 127 (rounded down to nearest whole number). Now we just need to convert 127 from decimal to HEX, which can be done with your nearest scientific calculator (or Google). 127 = 0x7F

    Hope this helps!

Leave a Reply

You must be logged in to post a comment.