Internet Explorer Bug Fix: Disappearing Positioned Anchors

A while back when I was working on developing the jQuery popout tutorials, I ran across a significant and annoying bug in Internet Explorer 6 and 7. Specifically, Internet Explorer does not respect the height and width properties of block-level, absolutely positioned anchor tags if they contain no content (or if that content has been moved or removed).

Instead of your anchors being the size you’ve specified, the size of the clickable area is limited to the size of the content inside the anchor. And therefore, if your anchor is “empty” (either because it’s an empty anchor tag, or you’ve used “display: none” or a negative margin to hide the content), your anchor tag’s clickable area is zero!

Let me explain a bit of what I mean. Let’s say I have a website with a very stylized banner at the top of the page, and I’ve decided to load the banner as a background image. However, in order to play nice with search engines and keep my SEO high, I’m still going to use an <h1> tag for my banner text, and then just hide its content. I also want a portion of my banner to be clickable, so I can let users get back to my homepage that way.

So let’s say this is my banner image:

As you can see, the banner contains some fancy text, and I want that fancy text to act like a regular hyperlink and take people back to the front page.

I might write some XHTML that looks like this:

<h1><a href="/"><span>This Is My Website</span></a></h1>

And some CSS to show the banner, make a portion clickable, and hide the text:

h1 {
	width: 800px;
	height: 200px;
	background: #fff url(mybanner.jpg) no-repeat; }
h1 a {
	position: absolute;
	top: 25px; // Move the anchor above the clickable area.
	left: 50px;
	display: block;
	width: 700px;
	height: 125px; }
h1 a span {
	display: none; }

My background image is on my h1 tag, because it contains my full banner. I’ve then moved my anchor tag to sit right over the text in my image, and then hidden the text inside of the anchor tag so as not to distract from my lovely artistry. The result could be conceived thusly:

So my clickable area is sitting directly over my image’s text, effectively turning it into a hyperlink. So we should be good, right? Well, in all browsers but Internet Explorer, we are. Unfortunately, because of the bug mentioned above, the anchor in IE has a clickable area of zero – my link might as well not even be there.

So what’s the workaround? Well, there are several.

Apply a Border

If, somehow, a border around your otherwise “invisible” anchor tag works well for your design, then rejoice! Your work is nearly done. Setting a border on the anchor tag forces Internet Explorer to recognize the width and height of the anchor, thereby giving it clickable area again. This fix was discovered while trying to debug the problem: adding a border to find out where the anchor was sitting on the page made it magically show up again. Go figure. So if you’re able to use a border (and perhaps chose a border color that blends into your background image?), this is the easiest fix of the bunch.

Put an Image In the Anchor

Another option is to simply not try to hide the contents of your anchor at all. If you simply put the image you’re trying to overlap into the anchor tag itself, you can bypass this whole messy affair:

<h1><a href="/"><img src="mybanner-text.jpg" /></a></h1>

Of course, that defeats the purpose of having a nice big <h1> tag at the top of your page for the search engines to find. As a result, this is my least favorite solution of the bunch.

Use a Background Image

While debugging, I also discovered that using a background color on the anchor tag forced IE to notice the width and height of the anchor. Of course, that also obscured the text to which I was trying to link and obliterated my hopes for an invisible link. However, it turns out that background images also force IE to recognize the size of the anchor.

At first, I figured the best solution would be to simply slice up my banner and attach the clickable portion of the image as a background on my anchor:

h1 a {
	background-image: url(mybanner-slice.jpg); }

And that solution is inelegant, but effective. But then I discovered that a transparent image works just as well! So then I created a 1px by 1px transparent gif and used that as my background instead:

h1 a {
	background-image: url(transparent.gif); }

So even if the background color is transparent to human eyes, Internet Explorer can see and recognize the image as being present and thus will respect our height and width. In fact (and this gets a little strange), the image doesn’t technically even have to exist for this technique to work! If I tell IE that there’s a background image, but it can’t find the background image, it’ll still find our anchor size:

h1 a {
	background-image: url(fake_image.gif); }

Now, I realize that this Internet Explorer bug only happens in a very specific use-case (absolutely positioned, empty anchors), but I’ve stumbled across it more than once in my work, so hopefully someone out there will find this workaround useful as well! Also, I should point out that none of these workarounds have any negative effect in any non-IE browsers, so go nuts!

13 Comments

  1. Bruce Williams said:

    Does it work correctly on IE8?

  2. Phil Nash said:

    Rob,

    I don’t believe this is a problem if you use the Phark method of image replacement. Even better, the method requires no extra, meaningless span and when a screen reader comes across your page the title will be read out (they ignore display:none).

    <h1><a href=’/'>Title%lt;/a><h1>

    h1{
    position:relative;
    width:800px;
    height:200px;
    }

    h1 a{
    position:absolute;
    top: 25px;
    left: 50px;
    display:block;
    width: 700px;
    height: 125px;
    text-indent:-9999px
    }

    This is untested, as I’ve just written it out here, but give it a go and see if it solves the problem.

  3. Rob Glazebrook said:

    Hi Phil,

    I hadn’t learned of the Phark method yet… appreciate you sharing! That is a lot better than having a non-semantic span in the markup.

    Unfortunately, the same problem applies to this method: the area isn’t clickable in IE6 or IE7. Luckily, applying a background to the anchor still seems to fix the problem.

    Thanks for sharing!

    Oh, and Bruce: I don’t have a copy of IE8 installed on any of my machines. I should probably fix that at some point.

  4. On November 20, 2008
    11:34AM

    Chris Coyier said:

    I literally ran into this problem just yesterday. I think the issue at hand is that you need to trip hasLayout for IE 5/6/7.

    The trick (totally worked for me) is:

    h1 a { display: inline-block; }

    Put that right BEFORE the rest of your h1 a stuff and it should fix it. Even though you set it back to display block, hasLayout has been “tripped”.

  5. rom said:

    Brilliant dude, worked a treat!! My whole design was all about absolute positioned anchors - first time. I always work with Firefox because of the debuggin features, tried it on IE, nearly cried…AWESOME

  6. Sarcasticshrub said:

    Good stuff. I haven’t positioned my H1 A absolutely before. Most sites have had the header & link right at the very top of the page.

    I’d recommend IETester for your IE tweaking. Has IE5.5 through IE8b2.

    http://www.my-debugbar.com/wiki/IETester

  7. Danny said:

    What about setting the Span to “visibility: hidden”, rather than “display: none”? Since invisible elements still take up space on the page, I would expect the clickable area to be unchanged.

    That’s just off the top of my head, though; I haven’t tested anything!

  8. Alejandro said:

    I dont know if you did the same in your original code, but the code shown doesnt close the tag, but open another one instead.

  9. Garrick Cheung said:

    @Danny
    I think setting span to visiblity:hidden; or display:none; is bad for SEO.

    Have you tried:
    h1 {
    width: 800px;
    height: 200px;
    background: #fff url(mybanner.jpg) no-repeat;
    position:relative;
    }
    h1 a {
    position: absolute;
    top: 25px; // Move the anchor above the clickable area.
    left: 50px;
    display: block;
    width: 700px;
    height:0px;
    padding-top: 125px;
    overfow:hidden;
    }

    Overflow:hidden hides anything outside of the height/width dimensions while padding-top pushes the content to where it can not be seen. This method shouldn’t be bad for SEO.

  10. On December 03, 2008
    12:23PM

    Brendan Cullen said:

    What I do for logos (that I’m pretty sure I stole from SimpleBits :D) is to put a 150dpi “clean” version of my logo in the anchor, so when viewed without styles and/or for printing, I can show a nicer logo. Then I give it a width of 0 to hide it away:

    #logo img {
    display: block;
    width: 0;
    }

    I think this would solve your “Put an Image In the Anchor” problem, since you could still put your text in the H1.

  11. Darek Rossman said:

    Ive never had this problem before…i use phark to negatively indent any text inside my anchor, this is much more accessible.

    What works for me, is instead of using an H1, i use a DIV with an Anchor inside of it…the outter div gets the logo as a background img with a defined width and height. Absolutely position your div, and set the anchor to display:block with text-indent: -9999px

    Assuming the parent of your outter div has relaive position, everything should work fine with out extra rules or markup.

    Logo Link

    #logoImg{
    position: absolute;
    top: xx;
    left: xx;
    width: xx;
    height: xx;
    }

    #logoImg a{
    display: block;
    text-indent: -9999px;
    height: 100%;
    }

    Now this should work, as i use it on many of my sites, but i could be wrong on the code, as i cant check it atm…

    You could also just put everything into an anchor element, logo for bg img and set it to display block with a width and height…position as necessary….either way, its very simple to do and shouldnt require any workarounds…its always worked as expected for me….if this doesnt work ill check when i get home and let you know

  12. Darek Rossman said:

    Yea I checked and it should work…

    I think your original problem was that you were hiding the span inside the anchor, which did make the anchor empty…

    On my site I use an anchor and absolutely position it over top of my logo, and everything works as expected.


    a {
    position: absolute;
    display: block;
    height: xx;
    width: xx
    text-indent: -9999px;
    }

    This works in my case as my logo img is a background img inside another div…it’s pretty accessible too, its essentially like using an image map to define clickable areas, but the code is clean and semantic…

    tho by no im sure youve solved the problem an then some as this post is a couple weeks old. Anyway…maybe it helps

  13. On December 07, 2008
    12:26AM

    Rick said:

    Adding a border works well. You set “border-color: transparent” ( or “border: 1px solid transparent”).

Leave a Comment