As most web developers are aware, a significant amount of a script's running time may be spent performing DOM operations triggered by the script rather than executing the JS byte code itself. One such potentially costly operation is layout (aka reflow) -- the process of constructing a render tree from a DOM tree. The larger and more complex the DOM, the more expensive this operation may be.
An important technique for keeping a page snappy is to batch methods that manipulate the DOM separately from those that query the state. For example:
// Suboptimal, causes layout twice.
var newWidth = aDiv.offsetWidth + 10; // Read
aDiv.style.width = newWidth + 'px'; // Write
var newHeight = aDiv.offsetHeight + 10; // Read
aDiv.style.height = newHeight + 'px'; // Write
// Better, only one layout.
var newWidth = aDiv.offsetWidth + 10; // Read
var newHeight = aDiv.offsetHeight + 10; // Read
aDiv.style.width = newWidth + 'px'; // Write
aDiv.style.height = newHeight + 'px'; // Write
Stoyan Stefanov's tome on repaint, relayout and restyle provides an excellent explanation of the topic.
This often leaves developers asking the question: What triggers layout? Last week Dimitri Glazkov answered this question with this codesearch link. Trying to understand it better myself, I went through and translated it into a list of properties and methods. Here they are:
Element
clientHeight, clientLeft, clientTop, clientWidth, focus(), getBoundingClientRect(), getClientRects(), innerText, offsetHeight, offsetLeft, offsetParent, offsetTop, offsetWidth, outerText, scrollByLines(), scrollByPages(), scrollHeight, scrollIntoView(), scrollIntoViewIfNeeded(), scrollLeft, scrollTop, scrollWidth
Frame, Image
height, width
Range
getBoundingClientRect(), getClientRects()
SVGLocatable
computeCTM(), getBBox()
SVGTextContent
getCharNumAtPosition(), getComputedTextLength(), getEndPositionOfChar(), getExtentOfChar(), getNumberOfChars(), getRotationOfChar(), getStartPositionOfChar(), getSubStringLength(), selectSubString()
SVGUse
instanceRoot
window
getComputedStyle(), scrollBy(), scrollTo(), scrollX, scrollY, webkitConvertPointFromNodeToPage(), webkitConvertPointFromPageToNode()
This list is almost certainly not complete, but it is a good start. The best way to check for over-layout is to watch for the purple layout bars in the Timeline panel of Chrome or Safari's Inspector.
11 comments:
// Suboptimal, causes layout twice.
var newWidth = aDiv.offsetWidth + 10; // Read
aDiv.style.width = newWidth + 'px'; // Write
var newHeight = aDiv.offsetHeight + 10; // Read
aDiv.style.height = newHeight + 'px'; // Write
I suppose this triggers two reflow because the 3rd statements have reflow-queue flushed.
@Morgan Cheng - Right. The methods listed require layout to be up to date. If layout is already up to date, then it is a no-op. Other methods which manipulate DOM/styles cause layout to be "dirty" meaning that it needs to be performed at some point but not necessarily immediately. So each line labeled "Read" requires an up-to-date layout and each "Write" dirties layout.
In this case the third line forces a layout and then another layout would occur after the script finishes.
Will the layout cause a visible repaint or is this done internally and not repainted until the script finishes?
I'm asking because in webkit i've never been able to cause flicker by ordering property-setting wrong.
In IE on the other hand you can get really nasty flicker when setting properties. Especially scrollLeft and scrollTop is a big problem as they can't be set simultaneously without a repaint between.
JavaScript doesn't necessarily run on a bytecode interpreter, FYI.
be happy and love. kiss
Wow this is a great resource.. I’m enjoying it.. good article
For anyone who's tried the codesearch link since, it's been moved.
I would like to note that merely calling "getComputedStyle" doesn't seem to trigger a relayout. You have to actually lookup a property on the returned object, like this:
getComputedStyle(element).left
A list of complicated codes for a programs. One thing's for sure, with the use of this many businesses or people will be benefited from the process.
What are the best resources for learning about how browsers work internally? For instance, Tony said: "Other methods which manipulate DOM/styles cause layout to be "dirty"...". How do you find out how all of this works inside the browser? Are you reading the source code? Or is there documentation? Thanks!
Great post, much appreciate the time you took to write this.
Post a Comment