TV version (Display Regular Site)

Skip to: Navigation | Content | Sidebar | Footer


Weblog Entry

A Bit of Transparency

August 23, 2004

PNG files would make transparency effects a snap, except for one tiny little quirk: support for the format is great in every browser but one. Unless, of course, you resort to using some of the hacks and workarounds now available.

A List Apart ran Cross-Browser Variable Opacity with PNG: A Real Solution almost two years ago, and since that time other methods have come to light offering similar solutions of varying stripes to work around Windows IE’s lack of Alpha transparency support. (1, 2)

Since I’m a fan of valid code, I generally haven’t bothered messing around with the proprietary solutions, and the extra weight of an .htc behavior file is a bit more than my personal preferences can handle.

When it came time to code certain elements of the new design of this site, I knew what I wanted to do: tile a 1-pixel, transparent PNG on :hover for advanced browsers to add a nicely transparent screen, and hide that effect from IE to pretty much ignore a :hover state. As I coded I realized I could use two images, one for browsers that knew how to handle PNG properly, and one for IE.

There are two spots where you can see these effects come into play — the logo in top left corner of the header displays a very faint blue screen on mouseover (which is subtle enough to be missed, which is okay by me), and the three big content panels on the home page do the same with a more obvious red screen.

The markup is basic enough, although an extra <span> was necessary to pull it off:

<ul id="contentNav">
 <li class="li2"><a href="/projects/">
  <span>Projects</span>
 </a></li>
</ul>

By layering the elements one over top of the other, three overlapping planes were created which I could use to manipulate imagery (from the bottom up: the li, a, and span elements). The label of each panel shouldn’t be covered by the :hover effect so it sits on the top plane (the span), the transparent screen is applied to the middle plane (the a) but only on :hover, and the toned photo that makes up the background of each panel is applied directly to the li behind the rest of them.

With a nod to Jon Hicks’ 3D box model example, this is more or less how the panels are constructed: (well, actually, on the live site the background image is instead applied to the ul, not the li, but I’m simplifying… stay with me here)

Pseudo-isometric 3D view of link layering

The corresponding CSS sets up the containing boxes, places the images, and positions everything just so:

#contentNav {
 position: relative;
}
#contentNav li {
 list-style: none;
 padding: 0;
 margin: 0;
 position: absolute;
 width: 231px;
 height: 94px;
 background: url(../i/ice/contentnav-panels.gif) 0 0 no-repeat;
}

#contentNav li a:link, #contentNav li a:visited {
 width: 231px;
 height: 94px;
 display: block;
}
html>body #contentNav li a:hover {
 background: transparent url(../i/ice/alpha-red-dr.png);
}

#contentNav .li2 a span {
 width: 56px;
 background: url(../i/ice/contentnav-projects.gif) no-repeat;
}

The html>body filter on the :hover rule ensures IE doesn’t get any fancy ideas about the PNG, and everyone’s happy.

Well, except for the fact that there’s no feedback when the link is hovered in IE, a result I wasn’t happy with. I tried setting a solid background color on :hover and block the background image, but that seemed excessive. Then I remembered an old-school hack for semi-transparency, using an on/off pixel screen to create a checkered, pseudo-transparent GIF. Check it out:

(caveats: these inline examples not BMHed, won’t work in IE5, and you’ll need to visit the site and have your browser grab the custom style sheet to get the hover effect. They’re not pixel-perfect either, but you get the idea.)

The panel on the left is what Safari/Firefox/Opera users should see. The panel on the right is how IE sees it (regardless of which browser you’re using). The left is preferable, but the right is a decent enough downgrade that I’m happy with it. (On an LCD monitor there’s even a bonus optical shimmering effect that was unintentional, but kind of neat.)

Because of the filter that keeps the PNG away from IE, not much more was needed than to throw an alternate rule into the mix for IE, just before the latter rule that immediately over-rides it in every other browser:


#contentNav li a:hover {
 background: transparent url(../i/ice/alphafake-red.gif);
}
html>body #contentNav li a:hover {
 background: transparent url(../i/ice/alpha-red-dr.png);
}

Of course if I hadn’t got all of this working, I suppose I could have gone the high-bandwidth route and just thrown out a brand new pre-rendered GIF on the :hover state for each panel. But this way keeps the pipes unclogged, and that’s a good thing.

(And I’d be remiss not to point out that CSS3’s opacity property is gaining support. But I wouldn’t consider generally useful for production work quite yet, hence the images.)


Reader Comments

August 23, 02h

Prehaps you should use the same stacked method on the main mezzoblue logo, as in IE with the GIF, the logo gets all blerted out (is that even a word? lol)

Good work though :)

Apparently (think i read it on ie blog) MS are fixing PNG transparency in the next update (whenever that will be - longhorn - 2006 or beyond)

David says:
August 23, 02h

I find this saves a few bytes and has the same filtering effect as html>body:

#contentNav li a:hover {
background: transparent url(../i/ice/alpha-red-dr.png) !important;
background: transparent url(../i/ice/alphafake-red.gif);
}

IE doesn’t support !important and so the second rule overwrites the first, whereas Mozilla, Opera et al recognise that the first rule is the one to use and disregard the second. Unless anyone knows any different?

August 23, 02h

Great technique Dave, though I just want to point out that it would have been possible to get this exact effect without using any CSS hacks. It’s really quite simple. It would just require using the great, but underused, HTTP content negotiation. eg. by using Apache Multiviews.

That way, you give the same rule to each and every browser and leave it up to the server to decide whether the browser prefers PNG or GIF. So, IE would get the GIF and, AFAIK, Mozilla, Opera and Safari would all get the PNG. Other, lesser known browsers would also get what they prefer, whatever that may be.

4
Dante says:
August 23, 03h

What about just using IE7? (dean.edwards.name/ie7/)

August 23, 08h

I’m getting to the point where I am saying “screw it” when it comes to IE. I mean it is easier to make a site accessible to the blind than it is for an IE user.

Nicely organized article. I like what you did to the 3D box model. You’re the first I’ve seen to actually put it to practical use.

August 23, 08h

Imagine if Wal-Mart or Ikea had a security guard standing in front of their shops and saying “screw it” to anyone not wearing bright-red shoes. My guess is that a lot of people would get offended by that. Why can I not buy this garden-chair while wearing orange, green or white shoes? What does a garden chair have to do with the color of my shoes in the first place?

Well - nothing.

But, this is what you get if you stop supporting people using IE. If you have a website that sells garden chair, but stop 95% of the visitors at the front door, you have failed to reach this website’s goal (to sell chairs - not browsers).

—-

Dave, Interesting article.

August 23, 09h

A good reminder of the on-off pixel trick, I’d forgetten about that one!

re - forgetting about IE, you can’t forget about it, but you can sometimes - most of the time - just say “well, the site works in IE without this visual frippery, lets just give pretty stuff to complient browsers”

Dave in fact wrote an article about that.

However if you can get something working in IE and its not going to take really that much work, then do it.

I’m in general against using behaviors, unless I have to. Generally I find they are very unreliable in complex enviroments, but for a simple CSS menu, or similar, they usually work fine.

One thing - why do people insist on saying IE is 95% of the trafic on the net? Its just not true, its closer to around 80-85% overall (of cource this is an average, site specific ones may differ).

Anyhow - great article Dave, it shows a nice way of getting around the most annoying missing stylistic feature in IE.

Scott says:
August 23, 09h

Couldn’t you have used gifs and used background:position to change the images and make it accessible for all browsers?

Jim Amos says:
August 23, 09h

Good use of PNG. I was also wondering, at first, as to why you didn’t use pre-rendered gifs on a sliding position. But if bandwidth is the priority then that makes sense. How much difference does it actually make though? Just curious.

And in case you haven’t tired of hearing it yet - great work on the redesign. Nice to see mezzoblue going back to it;s roots with the cool blue.

Dave S. says:
August 23, 09h

“Couldn’t you have used gifs and used background:position to change the images and make it accessible for all browsers?”

What’s so inaccessible about it? Which browsers?

But the second to last paragraph addresses your question; I just didn’t completely spell out that I meant using background-position to swap images, and now I have.

August 23, 09h

Scott: It seems like a suitable solution to me, quite accessible I’d say. I agree with Gregory about the article, very enjoyable.

Josh S says:
August 23, 10h

I love the idea of using PNG files, but it just doesn’t seem to work well enough yet. IE doesn’t work right with them, Firefox’s scroll bar slows to a crawl, and if they can’t get it right then I am doubtful about Safari and Opera.

Scott says:
August 23, 11h

I know this is accessible but it’s alot easier to use background-position with gifs to me :). But to each his own.

Jeremy says:
August 23, 11h

Thats an excellent way to explain how to get a really great hover effect on a site. I may have to use this tip in the latest design of my site, I really enjoy it.

August 24, 05h

Great post, Dave.
There’s an easier way of doing it, though.
The power of !important will do the trick.
Example:
#menu li a:hover {
background: transparent url(‘images/image.png’) no-repeat top left !important;
background: transparent url(‘images/image.gif’) no-repeat top left;
}
The first rule will count for all browsers which support !important, while the last one counts for IE, since IE always goes for the last occurance of a rule.

16
Tao says:
August 24, 07h

It seems there are visual discrepancies between Safari and Firefox in the way they composite transparant images. Have a look at http://www.taospace.com/transparancy.jpg to see what I mean. This is really too bad as (at least in this case) the result of Firefox is unacceptable, whereas Safari does it perfectly.

In this test the cloud image has variable transparancy throughout and it is displayed on top of a gradient background.

baohx says:
August 24, 08h

Lately, I’ve just been using a filter for all of my sites on the server end. If it detects that the user is using IE, it’ll recode img tags that have png’s in the src to output the mutilated-for-IE code.

August 24, 12h

Tao - That is actually due to the differences in gamma reporduction in firefox and Safari.

Photoshop also screws the pootch when it comes to writing png gamma chunks. Correct gamma chunks still show too dark in Safari (it seems to ignore them and do its own correction).

So firefox is actually probably rendering the file correctly, given the gamma info in the file. Safari tends to be darker, because of its wierd gamma treatment.

Oh and also - why anyone would use gif’s at all for non-animation files when png comes out smaller everytime I don’t know.

August 25, 08h

I’m just wondering do any browsers support MNG? ( i think its called that ) MNG is the animated PNG isn’t it?
I’d love to use MNG for motion files i’d think they’d be smaller and have alpha to boot!
It’s been a yea ror so since i’ve been on the web dev scene i look to come back now :)

August 25, 08h

Damon I think Mozilla does, but it ised to only with an extension. Maybe that’s changed (or I remember wrongly.. both posible).

However no-one really uses the format. Its not a particularly well developed format atm, but yes.. in theory if could be smaller than gifs, but its not right now.

static png vs gif tho.. thats a different story. Check out this article for a good comparison:
http://twilightuniverse.com/blog/archives/2004/2/12/11/ping/

August 26, 10h

Not that either of us is the first to grok this concept, but I think it’s interesting when people stumble upon basically the same idea at around the same time without influencing each other.

This is almost exactly the same technique I’ve got going for the upcoming redesign of my personal site.

Love your latest, by the way. Best yet.

22
Michael Watts says:
August 27, 01h

If you are going to use different code for IE anyway why not use a 1px Gif and take advantage of IE’s poprietry Transparency/Opacity CSS filter?

One would expect that this would give a better result whilst still keeping thigns trim….

August 27, 02h

funnily enough I’d attempted this a few days before reading this article, howver it seems that IE has trouble if the image is tiled over a larger area, in my case it is applied all the time - not just on hover. You can see it in effect here:
http://foxhill-bank.org.uk/ietransindex.html

I dont suppose anyone knows why IE runs so slowly with this on?

Twyst says:
August 29, 01h

I had a similar problem when designing http://ballisticzen.org - I wanted nice round edges, with soft shadows. PNG seemed to be the answer.

In every browser, apart from IE, it worked fine, as we all know. So I attempted to use several of the IE-specific Filter hacks to get transparency. Wow, what a mangled mess that was.

First major problem: Any text links, if overlaid on a CSS-filtered PNG, became unclickable.

Second major problem: Rather than tile the image, or crop it, it resizes the entire image to fit into the dimensions you set. So using single-image rollovers is out.

So, I came up with a solution - it wouldn’t have worked for this instance, sadly, but it IS a viable solution:

First, I used TweakPNG to set a specific background color that IE will display rather than transparency, and removed the gamma chunk, so all browsers render it consistantly.

Then, I used a CSS hack to switch the nice textured background to a solid color for IE only, that matches the background color I set above.

*Poof!* Following your MOSe concept - IE gets something usable, fairly attractive, but all other modern browsers get that little bit more.

You can snag TweakPNG here: http://entropymine.com/jason/tweakpng/

25
David P says:
September 05, 12h

I don’t know if someone else already posted this link but there is a (ugly) way for webdesigners to make PNG-files show transparency for IE6+ users. For more information, read here: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q294714

Mark says:
September 07, 04h

The CSS opacity property will rock when properly supported. I use it (in combination with the -moz-opacity property) on my header bar. Using Firefox, find a page on my site that requires scrolling, and scroll down.

On a different subject, you might find using a larger PNG than 1px square better. Josh S claims Firefox scrolling slows to a crawl (not here), and this may be the problem. I remember using a 1px wide gradient background on a site many moons ago, and NS4 took ages to tile it across the page.