Internet Explorer Bug Fix: Disappearing Positioned Anchors

Published November 19, 2008 by CSS Newbies.

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!

37 Responses

  1. Phil Nash (reply)

    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.

  2. Rob Glazebrook (Author) (reply)

    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.

  3. Chris Coyier (reply)

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

  4. rom (reply)

    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

  5. Danny (reply)

    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!

  6. Alejandro (reply)

    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.

  7. Garrick Cheung (reply)

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

  8. Brendan Cullen (reply)

    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.

  9. Darek Rossman (reply)

    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

  10. Darek Rossman (reply)

    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

  11. webweaver (reply)

    Craaazy! I was tearing my hair out for a whole day on a bug similar to this, and this page provided a solution.

    I had an absolutely-positioned span inside an absolutely-positioned span inside an anchor link – jQuery tooltip madness with curved corners – and in both IE6 and IE7 the inner span was resolutely refusing to display any background at all. I was basically trying to do “sliding doors” with absolutely positioned divs. Works in FF, not in IE.

    Your article showed me that it was the anchor tag causing the problems, not the absolutely positioned spans themselves. Move them outside the a tag, tweak the jQuery to reference them in their new location and WOOHOO! It works! And it’s only taken me (literally) 12 hours to figure out the solution and make it work.

    Thanks for your help!

  12. rajf (reply)

    Very useful article. I encounter this more and more as I’ve begun refencing images in HTML rather than backgrounds for buttons. This allows me scale the image along with text.

    Link

    The cost is an extra div but hey I get the effect I want.

    Probably better to refernece a transparent gif rather than a fake URL to avoid generating 404 errors.

  13. AJ (reply)

    Another perpetration of the myth…an H1 tag should go in the
    Header. NOT. Why do so many people think that is a great idea? H1 shows that it’s the most important and relevant heading for your content. Ideally, it should contain the main keyword that you are optimizing your page for,and that keyword should also be contained within the filename, and within the first paragraph or so of your main content. Oh yes, and the title of course.

    Assuming you want to optimize your page correctly, that is.

    As a matter of interest…do you want THIS page to rank well for the word bug, or for something like “IE bug fix”? If you used “IE bug fix” as your first tag for the post, then your SEO plugin would pull that keyphrase for your first meta tag keyword, instead of “bug” which is what it has done now.

    You have some great content on this site, but I do have to disagree with your views on using H1 in the header. Just because wordpress might do this by default, doesn’t make it best practice, IMO.

    I realize that Matt Cutts has said that using more than one H1 on a page isn’t necessarily bad, as long as you have a logical reason for doing so. But in this case, what logical reason is there? Do you want this particular page to rank well for “css newbie”, as thats what your first H1 tag contains.

  14. AJ (reply)

    I was incorrect in saying the first tag is the one used for the main meta tag keyword, sorry. With your plugin, it goes alphabetically, so no choice but to have bug as the first keyword.

    Which is a shame really, the word bug is not what you would want this page optimized for is it?

    regarding the use of transparent images. Maybe you will do a post sometime on the png fix for IE6? Im sure that is something people will find useful, and it would work in well with the info that you have here. Thanks, and keep up the good work.

  15. Gareth (reply)

    I’d recommend using a real (transparent) background image, rather than a made up filename. Otherwise your apache error logs are going to be filled with requests for “fake_image.gif”

    Just a thought.

  16. Justin (reply)

    A good (and popular) post, Rob. I’d strongly recommend not using the transparent image just to avoid an unnecessary HTTP request. However, on the image topic, setting the background-image does seem like the best solution. You can still get this to work without splicing up your image (and without the additional HTTP request). Just use the same technique as you’d use for CSS sprites. Throw in the image that you’re already using for your background, and either position it so the images align, or just position it so it goes beyond the element (with no repeat flipped on).

  17. Paul (reply)

    After spending a large amount of time with this and trying everyones different hacks with inconsistent results I added this to the bottom of my html page:

    // fix IE bug where hash anchors don’t update scrolltop on some occasions
    if (window.location.hash)
    window.location = window.location.hash;

    I had a unique requirement where I had an email with anchor links jumping to an anchor on my site.

  18. elias (reply)

    very good, this was exactly what i needed. thanks vor the work! to be clean i placed that transparent image on harddisk to avoid 404.

  19. Marcelo M (reply)

    Yep, the approach that solved this bug for me was a transparent pixel image as a background, display:inline-block didn’t worked on this case. I used a transparent gif, as I know png transparent images are tricky with IE. It’s an extra request, but using conditional ie comments it would be easy to trigger this fix just for our non-friendly-to-uidevs browser.
    Thanks to all, this problem could have been a day taking issue, solved in 10 minutes. I love this game :D

  20. Dead Rising 3 PC Download (reply)

    Instead of not wasting the Mooladhar energy in sexual passion it ought to be raised to
    the head region to ensure via proper meditation the eye of divine wisdom can be opened up.
    So the topics ought to be a fantastic balance between somewhat mature topics too as topics close to the heart of the youngsters.
    Also, these are interested in looking good, looking after their physical aspect, getting decked
    out well, so ultimately these are beautiful ladies, plus they want to make
    a better man, if she can.

  21. LoL hack (reply)

    In this screen you have revealed whats happening when you
    use this League of Legends Hack. The Gobi Desert is the largest desert in Asia,
    and the fifth largest in the world. Those who
    are interested in buying MMA fight shorts can find it on this
    site without any problem at all, and this will enable you to
    benefit many ways that you never thought possible because having great equipment means that you will be a better fighter.

  22. Hugo (reply)

    Hi folks, just want to warn you – don’t pay $500 for platinum roulette system, you can find it for free, just search in google – platinum roulette system – you will
    find interesting post about this system

  23. Nam (reply)

    It is on this very day that a sister ties Rakhis to her
    brother and prays to the Almighty for his victory in face of all odds.

    Care – Short for “be careful” as there are players possibly
    MIA or you may be too far extended up your lane with no
    backup. Carry – A character that can eventually “carry” the team to victory.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>