How to Fix Randomly Disappearing Absolutely-Positioned Elements in IE

IE6 and IE7 disappearing elementsAfter 8 years, you’d have thought all IE6’s bugs would be well-documented and understood. Actually, after that time, you’d have hoped most of the issues would have been fixed in IE7 or IE8!

I was recently contacted by a frustrated developer who’d experienced disappearing absolutely-positioned elements in IE. The bug is quite bizarre, it’s not often you experience it, and there’s little information about it on the web. Hopefully, this article will go some way to rectifying that situation.

The Problem

Consider this layout:

layout

The HTML elements are coded in the order specified, i.e. content blocks 1 and 2, header 3, right-hand block 4, and footer 5. The outer container is set to position: relative and all items have widths assigned so IE hasLayout. It may not be the most efficient layout but it’s valid and works in all browsers. Except IE6, IE7, and possibly IE8 … sometimes.

The first time you visit the page, IE can refuse to show the header. However, the header may re-appear when visiting a similarly-coded page on the same site. It can also re-appear when you return to the first page?

The problem is caused by an IE bug that hides an absolutely-positioned element when it’s coded immediately before or after a floated element (it’s next to a floated sibling). Unfortunately, this condition does not necessarily trigger the bug — it’s time dependent! The timing of the file downloads and the rendering speed affect whether it occurs or not. In my experience, the bug seemed less likely to occur if some files were cached.

So, here’s an example page.

Unfortunately, the bug is so inconsistent that it’s impossible to create one that’s guaranteed to work (or fail?)

On my local PC’s server, the header disappears in IE6, 7 and 8. On the SitePoint server, it only disappears in IE6 and 7. You may have a different experience.

In addition, fake IEs such as IETester do not necessarily exhibit the same problem. I’d recommend using a real version of IE such as one within a VM (see Run IE6, IE7, and IE8 on the Same Machine Using Windows 7 XP Mode or How to Run IE6, IE7 and IE8 on Windows 7 HOME).

The Solution

Fortunately, there is a quick and dirty solution: simply place an empty un-positioned static <div></div> immediately before and/or after the absolutely-positioned element. In the fixed example, an empty <div></div> after the header prevents the problem occurring.

Semantic HTML devotees will be horrified but I’m afraid there doesn’t appear to be a CSS-only fix … unless anyone knows otherwise?

A better solution would be a more efficient layout without the absolutely-positioned header. Unfortunately, that can require a significant amount of code re-factoring if you haven’t tested IE early and often.

Have you experienced this strange bug before? Or have you given up on IE altogether?

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Simon

    Does it work if you insert the div via javascript for IE only?

    Failing that you could at least wrap it in a IE Conditional

  • http://www.tyssendesign.com.au Tyssen

    Semantic HTML devotees will be horrified but I’m afraid there doesn’t appear to be a CSS-only fix … unless anyone knows otherwise?

    Have you asked Paul O’Brien?

  • Lee

    I remember encountering this bug a few times.
    However I was unable to find information on the issue or how to fix it back then, so I had to rewrite the page in a different way.
    Thanks for putting this up, will keep it in mind.

  • Anonymous

    Differences between local PC and SitePoint Server may come from DTD declaration ?
    IE 8 seems to have this bug only with “compatibility mode” activated.

  • http://www.optimalworks.net/ Craig Buckler

    No, it’s nothing to do with the DTD or DOCTYPE. The same page on a different server acts in a different way. The main difference is the speed of download.

  • http://www.deanclatworthy.com Dean C

    Interesting. I have a few questions. Why are you using float: right on the right column when you could use float: left. The display: inline’s are probably un-necessary. And it also begs the question why the elements are within this order. I’m almost certain there will be a CSS fix for this, and it’s not a bug. I wish I had the time to debug it :)

  • c0wfunk

    I have run into this bug before. I ended up switching to relative positioning when it made me insane. I came across explanations that basically said IE “loses” items that are nested too deeply.

  • http://www.dotcomwebdev.com chris ward

    Want semantics?

    Then consider wrapping the three columns in the middle with a container div and hack your css, not your markup!

    The container div can be called ‘content’, the three columns inside can be called contentPrimary, contentSecondary, contentTertiary.

    div#container
    {
    _height: 1%;
    overflow: auto;
    }

    Don’t bother positioning the top element absolutely – it’s block-level default properties should push the content container/wrapper element down below it.

  • stacye

    @Dean C, I use float: right when dealing with 3 column elements, because it’s easier for me to make column 1 and column 3 (or in this case, 4) look the same in positioning from the wrapper (or in this case, page).

  • http://www.optimalworks.net/ Craig Buckler

    @Dean
    As mentioned, it’s not a great way of laying out a page, but it’s valid HTML and CSS. I have seen it occur in other pages were a AP box is next to a float (it doesn’t matter whether it’s left or right).

    Best of luck finding a CSS-only fix. I spent several hours on it and tried every trick I could think of!

  • jonathansnook

    I had run into this problem on a recent project and solved it by wrapping the positioned element in an unpositioned DIV instead of putting an empty element before or after. Still not very semantic but I could live with it.

  • http://www.fldtrace.com Recruit

    I have the same problem on a dropdown navigation. The level 1 displays good, only after I removed the z-index attribute from it, but the level 2 dropdown won’t display in IE6 and 7. It is very weird, as all of my code is correct.
    Also, it might be a fake IEtester problem not displaying that. I really need to install the XP virtual server.

  • http://www.optimalworks.net/ Craig Buckler

    @chris ward
    Thanks for a solution, but you are hacking your mark-up! You changed the HTML to make the CSS work. (Incidentally, you don’t need the height:1% because all the widths can be set explicitly.)

    In a perfect world, the page’s HTML shouldn’t need to be changed and CSS could position the elements as shown in all browsers. That’s the challenge!

  • mwistrand

    Oddly enough, I ran into this problem for the first time yesterday. I had the same code on two different pages on the same site, and the absolutely positioned element disappeared on one page but was visible on another. Fortunately, both elements were part of the same containing div, so I got around this by also setting the floated element to position: absolute. It’s annoying, and it certainly won’t work in every situation, so thanks for this post!

  • http://www.pixelbehavior.com CupidsToejam

    I’ve given up on IE altogether. If you come to my site with any version of IE, you are directed to download a compliant browser.

  • Brendan

    I experienced this bug in a recent site build. Relatively-positioned elements were disappearing. They were being displayed within a jQuery pulgin already, so finding no alternative I used jQuery to hide and show the disappearing elements. Forcing the “show” this way worked every time and was undetectable to the user (unless they have javascript disabled…).

  • http://fvsch.com Florent V.

    I may have an explanation for the flimsy behavior in IE8.

    If your access your local test with a filesystem address rather than a http one, or if you access it with a http address whose domain IE8 thinks is “local network” (IP 127.*, any domain without a TLD…), then IE8 will use compatibility rendering mode. So basically your IE8 is using IE7’s rendering engine.

    On a distant server, since you have a valid DTD for your test page, you get IE8 rendering mode (yay).

    Could you check that? I think the existing ways to check this are a) to keep an eye on the compatibility mode or information on current rendering mode in IE8’s developer tools, and b) to disable the automatic switching to compatibility mode in IE8’s settings (disable the list-based and local domain-based switching).

    Regarding a fix, did you try a HTML comment? If any DOM node between the two elements stops the bug from happening, maybe a simple could work? Still not a CSS solution, but better than an empty DIV if it does work (can’t check right now, sorry).

    Last time i encountered this bug, i think i worked around it by modifying the positioning scheme so it wouldn’t trigger the bug. :/

  • http://www.dotcomwebdev.com chris ward

    @craig buckler – hacking my mark-up? Not sure I entirely agree with that – the containing element may seem extraneous, but it still highlights the grouping of content and for that purpose should be fine? Semantically fit for purpose in my opinion :)

    The css? yes, definitely _height: 1%; is an IE-only fix for forcing those parent containers to scale the full height of their floated child elements.

    I believe there’s an alternative to hacking the css this way, by forcing IE’s hasLayout – but I’ve never had the time to investigate.

    I’m happy to hack my css, but never my mark-up – always feeling like a piece of me has died when I have to resort to wrapping containers for rounded corners and the like – would rather use a <table> (same thing if you ask me)

    The addition to the HTML is clean and logical and will allow you to achieve the layout you’re after…

  • Louis Lazaris

    Craig,

    You seem to be correct that there is no way to fix this with CSS alone. Nothing seems to work. The two non-CSS ways I found to fix the issue are:

    1) Place the #header div as the last child element. In the past I’ve often fixed absolutely positioned problems in IE6/7 by moving the absolutely positioned element to be the last child element. This makes sense since the element is no longer beside a floated element.

    OR

    2) Place the following JavaScript on the page:


    document.body.onload = function() {
    document.getElementById("header").style.display = "block";
    }

    The JS code could be anything that applies a harmless style on the fly to the #header element (“overflow = visible” or “border = none” would also work here).

    I don’t believe there is a CSS-only fix to this problem.

  • http://www.optimalworks.net/ Craig Buckler

    @Florent V
    You’re right! IE8 was in compatibility mode for intranet servers. The bug *may* therefore be fixed in IE8.

    HTML comments don’t have any effect I’m afraid.

    @chris ward
    I meant that you changed your HTML markup to fix the problem rather than finding a pure CSS-only solution. Semantically, there’s nothing wrong with the HTML as it is.

    IE’s hasLayout is triggered by setting height or width. Setting a valid “width:100px” will have the same effect as “height:1%” (but it’s a little less hacky!)

    @Louis Lazaris
    Thanks for investigating it, Louis. Moving the element would be the best solution but it’d be easier to move it to the top of the page and scrap the absolute positioning!

    The JS solution is especially bizarre. I suspect it could be because IE’s re-rendering after the page has loaded so any timing quirks won’t be evident.

  • http://www.ryanreese.net RyanReese
  • http://www.ryanreese.net RyanReese

    This is definately documented somewhere..can’t quite remember where though :).

  • http://www.pmob.co.uk Paul O’B

    Hi,

    I documented this a couple of years ago and the solution is that absolute elements must come last in source within the current stacking context and if they follow floats they should also have clear:both added to the absolute element.

    It’s nonsense I know but works :)

  • http://www.optimalworks.net/ Craig Buckler

    Thanks to everyone who has provided a solution. So far, all of them require changes to the HTML – either by re-ordering or adding additional elements. In a perfect world, that should not be necessary. But a CSS-only fix remains elusive.

  • http://www.pmob.co.uk Paul O’B

    There isn’t a css fix to the absolute element disappearing (apart from moving the element to the end of context as already mentioned which is an html fix) but there are of course other ways to achieve the effect that you are asking with css only.

    The simplest would be to not absolutely place the element and then drag it into place with negative margins. The downside of that method would be that you need to know the height of the middle columns.

    Instead you can use an almost pseudo absolute element and use a float with negative margins that practically removes it from the flow and allows it so slide upwards regardless of how high the middle columns may be.

    e.g.

    #header
    {
    float:left;
    width: 752px;
    margin:4px -100% 0 -548px;
    height: 150px;
    background:#c00 ;
    }

    That achieves the layout you wanted without changing the html but of course is not a fix for the original problem as the solution to that is adjusting the html as already mentioned above (and in the tip I gave in 2004 in the Sitepoint newsletter – Don’t you remember :))

  • http://www.pmob.co.uk Paul O’B

    I forgot to mention that this bug is also well documented on Bruno Fassino’s site.

  • Zimbirti

    I am used in my customer’s web page and wonderful working. Look at Atasözleri ve Anlamları. I am understand this knowledges. Your are wonderful.

  • http://aarontgrogg.com/ aarontgrogg

    Thanks, Craig, this is good to know, the only solution I had come up with was JS-based: Turns out if you “grab” the absolutely-positioned element post-page-load it pop into place. It’s as if IE needs to be “nudged” or reminded that the element is there…

    In other news, for anyone that does not have Win7 and would like multiple real versions of IE, I recently stumbled on Hilbrand Edskes’ Internet Explorer Collection which offers every IE from 1.0 to 8.0, and includes the IE Dev Toolbar! I’ve been using it a couple weeks and am thoroughly impressed!

    Thanks again,
    Atg

  • cssmoo

    Woot! Thanks, Paul O’B for the clear: both tip. That’s the one that did it for me. Placing the empty static divs didn’t work for me at all.

    For those who argue for rearranging the markup, my response is: I’ve already placed everything in the logical order it should be in (should CSS be turned off, everything flows properly and makes sense). Unfortunately, in the design, certain things don’t belong next to each other (the visual hierarchy is different). So in my case I’m firmly committed to my markup the way it is, and the design the way it is.

    CSS provides the answer. But it’s only IE6 that botches it. Why do I have to rearrange the markup and design that I’ve spent so much time thinking about and putting into logical order, just to make it work better for IE6? It’s ridiculous.

    So thanks, again Paul O’B: my markup is semantic; the stylesheets are valid. I’m happy.

  • John

    Thank you sooooo much!!! What a pain in the ass that was. Empty divs did the trick.

  • Jim

    Awesome, fixed it for me – thanks.

  • varun

    Thanks man.. it is really easy and awesome too… thank you so much.

  • http://www.andib.co.uk Andi

    PERFECT! We’ve had a problem with this at work for about a month now! Thanks so much!

  • http://www.devolved.co.uk Steve Firth

    If you have any problems with jQuery sliding effects in IE7, mostly copy collapsing on to each other …
    the empty trick works for that too.