How can I force reflow after DHTML change in IE7?
Asked Answered
M

2

17

I have a page where the user can dynamically add file upload boxes. Adding the boxes changes the height of the div they are in, but certain elements of the div below it stay in the same place, so they start to overlap with the new DOM elements.

This works correctly in IE8, Firefox, Chrome. How can I force IE7 to reflow the page with the new DHTML?

The best solution I worked out was this:

window.resizeBy(1, 0); 
setTimeout(UndoResize, 0);

But it doesn't work with a maximized window (it restores the window).

Mercier answered 9/11, 2009 at 17:12 Comment(0)
C
40

Try:

element.className = element.className;

on the modified div (or possibly its parent, or even a more remote ancestor, depending on various factors such as relatively-positioned containment).

As the className has been assigned a value IE will reflow and repaint that portion of the page in case the CSS affecting that element has changed. Luckily, it isn't optimised to check if the className value actually changed from its previous value, so the above will trigger the reflow without breaking anything else.

I did find one occasion when this fixed IE6 but broke IE7, but try it and see if it works for you.

Cremator answered 9/11, 2009 at 17:25 Comment(5)
Yes! This issue affects elements just below the body, so I'm using: document.body.className = document.body.className; Thanks!Mercier
Is this specific to IE? Like does this solution force reflow in other non IE browsers? I'm interested in the cost/trade offs.Lunar
@cottsak: To the best of my knowledge this will have a similar effect in all (current) browsers - in fact, I first got the idea from an article on Opera's developer site. The technique is also mentioned in the W3C's WAI-ARIA Primer, section 3.1 w3.org/TR/2010/WD-wai-aria-primer-20100916/#exampletree - "It may be necessary to toggle a class name, or otherwise force the browser to redraw the styles properly."Cremator
@Cremator Kool. So I guess I can assume then since the Chromes and Firefoxes of this world don't crash and burn like IE that their performance wont be hit by running this indiscriminately?Lunar
@Freewalker: document.body.className += ''; :)Knew
R
3

I've just wasted incredible amounts of time on this absolutely ridiculous bug (manifesting in IE7 only), in the webpage way too complex to put the code here, where element.className = element.className wasn't working.

The ultimate solution for IE7 (well, tested at least in the place I've encountered the bug) seems to be executing ALL of the lines below as a hook to any DOM changes:

try{
    element.parentNode.style.cssText += "";
    element.parentNode.style.zoom = 1;
    element.style.cssText += "";
    element.style.zoom = 1;
}catch(ex){}

We've already had the first two lines (surrounded with try-catch) in our framework for a long time, but it turned out insufficient in some particular scenario, but adding the next two fixed this.

Tested both in maximized and non-maximized window.

try/catch is in place because in some certain circumstances (e.g. inside an iframe) it may generate a JS error that will break the app (this is info from my team fellow, I haven't encountered it myself).

On the contrary, for IE8, element.className = element.className seems to be doing its job (yeah, we all love conditional code for each version...)

I love Win XP as an OS, but until IE-bound people use it, we have to find dirty fixes to such crazy problems... Damn sad.


Edit 2013.03.05

The snippet above seemed to be working in most of the scenarios, but also was not enough in one place. Now we have stuff like this in our code:

try {
    var s1 = domElt.parentNode.style, s2 = domElt.style;
    var dummyCss = "foo:foo;"; // do not add leading ';' here!
    s1.cssText += "";
    s1.zoom = 1;
    s2.cssText += dummyCss;
    s2.cssText = s2.cssText.replace(dummyCss, "");
} catch (ex) {}
Rosemarierosemary answered 16/5, 2012 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.