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 -

<href="http://www.blogger.com/">
<img class="top" src="topimage.jpg" />
<img class="bottom" src="bottomimage.jpg" />
</a>

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 a.top:hover 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">
<span>
<a href="./">
<div>
<img class="imgmenu" src="donate.jpg" alt="Make a Donation"/>
</div>
<span>
<img class="imgbgmenu" src="donatebgtab.jpg" alt="Make a Donation"/>
</span>
</a>
</span>
</div>

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]

2 comments:

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'.