views:

129

answers:

2

Bug: when hiding an element with JavaScript in IE8, the margin of still-visible other elements on the page is ignored.

This bug has been introduced with IE8, since it works as expected in IE6+7 (and other browsers).

<html>
<head>
    <style>
        #a, #b, #c, #d {background: #ccf; padding: 4px; margin-bottom: 8px;}
    </style>
</head>
<body>
    <div id="a">a</div>
    <div id="b">b</div>
    <div id="c">c</div>
    <div id="d">d</div>
    <script>
        setTimeout(function () {
            document.getElementById("b").style.display = "none";
        }, 1000);
    </script>
</body>
</html>

When running this code, notice how a and c have a margin of 8 between them in normal browsers, but a margin of 0 in IE8.

  • Remove the padding, and IE8 behaves like normal.
  • Remove the timeout and IE8 behaves like normal.
  • A border behaves the same way.

I've been working with IE-bugs the last 10 years, but this has me stumped. The solution for now is to wrap the divs, and apply the margin to the outer element and other styles to the inner. But that's reminicent of horrible IE6-workarounds.

Any better solutions?

Edit: I submitted a ticket to the IE9-team, and now the bug has been fixed in IE9. Hopefully they will backport it to IE8 aswell.

+1  A: 

This one has me stumped for a true fix. For a hacky workaround, you could just reset that marginBottom to 8px. Apparently, setting display:none is removing a's margin. To verify, try:

    setTimeout(function () {
        document.getElementById("b").style.display = "none";
        document.getElementById("a").style.marginBottom="8px";
    }, 1000);
edl
A: 

An enhancement of edl's solution could be to automatically select and apply margin-bottom from the previous element. This way you won't have to choose (and remember) the elements ID and assigned margin.

setTimeout(function () { 
    var e = document.getElementById("b");
    e.style.display = "none";

    var prevSibling = e.previousSibling;
    prevSibling.style.marginBottom = prevSibling.currentStyle.marginBottom;
}, 1000); 

You may need to check if the previous element exist/is part of the bug.

Mads Jensen