Wednesday, March 11, 2009

Web developing a:hover and IE6

Good old Internet Explorer 6 still finding ways to foul things up. In this instance a simple image switch using CSS.

This should be cake and in fact it is for Firefox, Opera and, surprisingly, IE7. You set up some simple code like -

<img class="top" src="topimage.jpg" />
<img class="bottom" src="bottomimage.jpg" />

and then style it so that the a:hover .top disappears and a:hover .bottom appears. As I say cake. Except IE6 won't allow classes to appear after hover. Now of course it's possible to do etc. but that means duplicating all the links which is inelegant.

So wrap the top image in a div and the bottom image in a span then you can use a: hover div and a:hover span. Yay!

Except it still doesn't work in IE6 and IE7 loses the link.

IE7 was an easy fix - style the a element as a block. IE6 was more tricky. First off IE6 doesn't recognise display:none, and visibility: hidden keeps the space where the image is. So I use _z-index with the IE6 only modifier. Also Ie6 doesn't even recognise a:hover unless it calls a hasLayout element so I add in a quick border: 0px. Lo and behold it switches over, but doesn't switch back.

Turns out it's all to do with position. If you set a position on an element within the a element that is also postioned IE6 refuses to rescind the a:hover state, so remove that, check evrything stays where it is and there we go.

with some extra containers the HTML looks like this

<div id="menu">
<a href="./">
<img class="imgmenu" src="donate.jpg" alt="Make a Donation"/>
<img class="imgbgmenu" src="donatebgtab.jpg" alt="Make a Donation"/>

with CSS of

#menu {margin: auto; height: 2.4em; width: 49em; background-color: #EEE}
#menu a {display: inline-block; width: 6.25em; height: 2.2em; text-align: center; line-height: 2.2em; zoom:1; *display: inline; _height: 2.2em; text-decoration: none; color: #1FB25A; zoom: 1;}
.imgmenu {width: 6.25em; *top: 0em; zoom: 1;}
.imgbgmenu {width: 6.25em; *top: 0.05em; zoom: 1;}
#menu a:hover {border: 0px;}
#menu a span {display: none; _z-index: -1;}
#menu a:hover div {display: none; _z-index: -1;}
#menu a:hover span {display: block; _z-index: 0;}

Happily switches between the two in IE6/7 FF and Opera while keeping the link.

[Additional - Oh and yes I know I have a block element (div) inside an inline element (a), which is a no-no, but to blunt I just don't bloody care anymore]


kentr said...

Nice trick, but I leave wondering why it didn't work for you to use background images.

Quick fix to the block / inline thing is to just use another random inline tag (like b) instead of the div tag.

FlipC said...

Quite right that you could use a b or an em inline element instead of a div I still think in hierarchical terms that such things aren't 'containers'.

As for background-images the trouble is that until CSS3 you can't alter their sizes, so if you want the container to be a percentage to maintain proportions with the rest of the page the image is chopped, repeated, or gains 'padding'.