Reputation: 57
I was reading through some code today and came across this for loop:
for (i=0; i<100; i++){
document.getElementById(elem + i).style.display="none";
}
I've only just begun to learn about browser reflow; However, my current understanding is that this loop is causing a reflow for each of the 100 elements it is setting to display none.
What are the effects of this loop on the DOM? Is this really as horrible as I think it is?
This code is used while rending a new page.
Upvotes: 1
Views: 1649
Reputation: 2550
The Chrome Developer Tools timeline is a great way to test these kinds of questions, especially since "as horrible as I think it is" is fairly subjective.
I ran a test of the code you posted in this fiddle. Call this Test 1.
For control, I hid the elements efficiently by setting a wrapper element to display:'none'
in an animation frame, using the code in this fiddle. Call this Test 2.
So the empirical answer is yes, the tested code requires more than 10x the computation time to reflow the page layout, versus an alternative (ideal) method. Without knowing more about the code from which it is extracted, it is hard to say whether the method used is appropriate or necessary.
For example, if the elements to be hidden aren't neatly wrapped in their own wrapper <div>
, optimization is difficult. A strategy that avoids the for
loop would be to assign the elements a "hideable
" class, and set up a CSS rule like wrapper.hideChildren > .hideable { display:none; }
. Then, when we assign class "hideChildren
" to the wrapper, the marked elements are hidden. Using this strategy, I was only able to get rendering time down to 15ms, or 10ms when the wrapper was detached from the DOM before the manipulation, and re-attached afterwards. In other words, the for
loop may not incur that much of a performance penalty. Bear in mind that 17ms is roughly 1 frame of animation at 60 frames-per-second.
If you examine the screenshots at the end of this post, you will notice that even in Test 1, all "scripting" (the execution of the for
-loop) happens in advance of all "rending" (re-flow). So if your question is, "will the browser alternate scripting and rendering at each iteration of the loop", then the answer is no, at least in Chrome 50.
As for fridge_light's link in the comments, the linked documentation never states that setting display:none
won't trigger a reflow; it just includes a chart from a video that it links to, without a legend. Setting display:none
will change the layout: the height of the document may change, elements flowed beneath the hidden element will be shifted closer to the top of the document, elements inline with the hidden element will shift in-line, floated elements will change position around it, etc. So there is necessarily some computation done by the browser.
Your question is a little confused: the DOM is not necessarily related to page re-flow. Re-sizing the browser window, for example, may trigger a re-flow without affecting the DOM at all! Setting display
to none
removes an element from the page layout/flow, but leaves it in the DOM.
Upvotes: 5