30

I was wondering if there's anyone having an idea how to tackle with the following problem in IE7:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>IE7 absolute positioning bug</title>
    <style type="text/css">
      #panel { position: relative; border: solid 1px black; } 
      #spacer { height: 100px; } 
      #footer { position: absolute; bottom: 0px; }
    </style>
    <script type="text/javascript"> 
      function toggle() { 
        var spacer = document.getElementById("spacer"); 
        var style = "block"; 
        if (spacer.style.display == "block" || spacer.style.display == "") { 
          style = "none"; 
        }
        spacer.style.display = style;
      }
    </script>
  </head>
  <body>
    <div id="panel">
      <button onclick="toggle();">Click me</button>
      <br /><br /><br />
      <div id="spacer"></div>
      <div id="footer">This is some footer</div>
    </div>
  </body>
</html>

When you run this in IE7 you'll see that the "footer" element stays after modifying the CSS for "panel". The same example tested in IE8, FF and Chrome behaves exactly as expected.

I've already tried updating the element's class but this does not work if the browser's window has been opened maximized and no further size changes were made to the window (which is about 90% of the use cases we have for our product.... :( ) I'm stuck with a CSS-based solution however I think that I can make an exception in this case if it can easily be made IE7-specific (which means that other browsers will behave in a standard way with this).

Please help!

Machavity
  • 30,841
  • 27
  • 92
  • 100
Matthias Hryniszak
  • 3,099
  • 3
  • 36
  • 51
  • Have you tried switching doctypes to html-strict or xhtml-strict? What happens then? – NotMe Mar 18 '10 at 20:43
  • Indeed I have not. The problem is that I'm not in control over what doctype is sent to the client (for reasons I can't discuss here) so it'd not be the solution even if it had worked... – Matthias Hryniszak Apr 28 '10 at 08:32
  • 4
    2 years later and this question (and answer) are still incredibly useful! Been smashing my head against this for a while. Couldn't even figure out how to word the question properly... Thanks! – chrisfrancis27 Apr 03 '12 at 13:32

3 Answers3

68

This is related to the "hasLayout bug" of IE. The relatively positioned #panel parent doesn't have layout and hence IE forgets to redraw its children when it get resized/repositioned.

The problem will go if you add overflow: hidden; to the relatively positioned #panel parent.

#panel { position: relative; overflow: hidden; border: solid 1px black; } 

In depth background information about this IE bug can be found in the excellent reference "On having layout" and then for your particular problem specifically the chapter "Relatively positioned elements":

Note that position: relative does not trigger hasLayout, which leads to some rendering errors, mostly disappearing or misplaced content. Inconsistencies might be encountered by page reload, window sizing and scrolling, selecting. With this property, IE offsets the element, but seems to forget to send a “redraw” to its layout child elements (as a layout element would have sent correctly in the signal chain of redraw events).

The overflow property triggers the element to have layout, see also the chapter "Where Layout Comes From":

As of IE7, overflow became a layout-trigger.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Can't confirm that in IE7 in IETester: The whole thing disappears. Are you sure this is it? – Pekka Mar 18 '10 at 20:47
  • 1
    That is A M A Z I N G !!! Thanks!!! I've been struggling with this for 2 days and have not found an answer. Thank you so much! – Matthias Hryniszak Mar 18 '10 at 20:47
  • Oh all right, seems to have done the trick - maybe I got the desired result wrong. – Pekka Mar 18 '10 at 20:48
  • @Pekka: I tested it in real IE7 by the way. But you're right, I can confirm it for IETester. Another bug? – BalusC Mar 18 '10 at 20:48
  • 2
    @Pekka, that's why I still don't trust IETester. – Joel Mar 18 '10 at 20:48
  • @Joel @BalusC Wow interesting, good to know. I was trusting IETester blindly in layout things. – Pekka Mar 18 '10 at 20:51
  • Is there any logical explanation as to why this is working? Or is it just one of the things one normally does when IE7 is going haywire? – Matthias Hryniszak Mar 18 '10 at 21:08
  • This already smelled like one of the `hasLayout` bugs. The `overflow` forces the element to have layout and is one of the most used fixes. More about `hasLayout` related bugs: http://www.satzansatz.de/cssd/onhavinglayout.html and http://haslayout.net/css/ – BalusC Mar 18 '10 at 21:11
  • @BalusC: Actually IE8 Dev tools' "Render As IE7" get's this one right. However, for absolute confidence I'd use a virtual machine. You can set it up to run almost seamlessly in Win7 (http://www.methodicmadness.com/2009/09/running-ie6-in-windows-7-with-virtual.html). – Joel Mar 18 '10 at 23:23
  • Hmm... this doesn't seem to work for me, it just is hiding my absolutely positioned DIV in IE8/IE7 Mode as opposed to showing it at the right – walnutmon Sep 21 '11 at 16:22
  • @walnutmon: ask a new question with an sscce or jsfiddle. – BalusC Sep 21 '11 at 16:25
  • +1 Thanks! Adding _overflow_ didn't solved the problem for me; adding _position:relative;_ to the parent element worked though. Last sentence in the paragraph you linked had my salvation http://www.satzansatz.de/cssd/onhavinglayout.html#rp – daniloquio Apr 13 '12 at 22:14
  • Thanks! Simply adding `overflow: hidden;` on my CSS for my form seems to work. I also thought this was interesting, but I didn't need it: http://stackoverflow.com/a/1228452/470749 – Ryan Feb 19 '13 at 19:25
  • 3
    I find that adding `zoom: 1;` instead is better since it won't affect your layout in other ways like `overflow: hidden;` can. Both trigger `hasLayout`. – Rowno May 21 '13 at 04:22
  • @Rowno: That depends completely on the context. On OP's specific use case, `overflow: hidden;` is safe. – BalusC May 21 '13 at 10:38
2

This solution doesn't necessarily have anything to do with dynamic content, but it worked for me (at least made the page borked to a manageable degree): specify dimensions. I only noticed IE7 thought a div didn't have a width when using the crappy 'Select element by click' tool (ctrl+B) in IE tools.

Sebastian Thomas
  • 1,245
  • 13
  • 20
0

I have created my function to trigger redraw. Maybe it is not a right solution, but it works.

// Script to fix js positon bug on IE7

// Use that function, recomended delay: 700
function ie7fixElementDelayed(elements, delay) {
    window.setTimeout(
        function () {
            if(navigator.appVersion.indexOf("MSIE 7.") != -1) {
                ie7fixElement(elements);
            }
        },
        delay
    );
}

function ie7fixElement(elements) {
    elements.each(function(i) {
        var element = $(this);
        var orginalDisplayValue = element.css("display");

        element.css("display", "none");
        element.css("display", orginalDisplayValue);
    });
}

Sample usage:

ie7fixElementDelayed($('#HandPickedWidget .widget'), 700);
MaciejLisCK
  • 3,706
  • 5
  • 32
  • 39