Reputation: 404
I have a page that contains a random number of rows, each row has 2 cols. The challenge is to make this two columns of the same height for each row. I do that with JS.
var len = document.getElementById("translateContainer").children.length;
for(var i = 0; i<len; i++)
{
var height = document.getElementById("origin_"+i).offsetHeight + 'px',
col1 = document.getElementById("column_"+i),
col2 = document.getElementById("column_sec_"+i);
console.log(i);
col1.style.height = height;
col2.style.height = height;
}
When on page are less then 30-40 rows it's all good. But, when there is more then 200 rows, chrome start to lag for a couple of secs.
I've created a demo page here http://jsfiddle.net/YSp76/.
In FF and IE it executes in about 2sec. In chrome I didn't count but is more then 10.
The problem is in my code or is a webkit bug?
Upvotes: 7
Views: 166
Reputation: 446
It's not a bug, it's just a result of webkit/blink's non-optimal layout strategy. Here's what's going on behind the scenes:
This means that Chrome will re-layout the page 300 times. If you have access to a Mac, Safari 7.0 has excellent tools for debugging this sort of thing (the 'layout timeline'). Chrome also has some debugging tools in the "timeline" view (filter it so only 'Rendering' events appear). For more information on avoiding layouts, see http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html, although the information presented there is incomplete. Unfortunately, the only up-to-date source on the details of the WebKit rendering process is the WebKit source code itself.
To fix your problem, you can simply separate the querying height step from the changing height step. This will avoid unnecessary layouts. I've forked your fiddle here: http://jsfiddle.net/4fb2A/
var len = document.getElementById("translateContainer").children.length;
var origin_height = [];
for(var i = 0; i<len; i++)
{
origin_height[i] = document.getElementById("origin_"+i).offsetHeight + 'px';
}
for(var i = 0; i<len; i++)
{
var height = origin_height[i],
col1 = document.getElementById("column_"+i),
col2 = document.getElementById("column_sec_"+i);
console.log(i);
col1.style.height = height;
col2.style.height = height;
}
However, for layout tasks like this, you should try very hard to create a CSS-only solution. Using script is an inappropriate tool for this job, and will alienate visitors who have script turned off.
Upvotes: 4
Reputation: 43087
The chrome profiler (available via right click, inspect element, Profiles) shows that it's the offsetHeight that consumes the largest part, it seems related to this open bug in chrome:
Upvotes: 3