Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
What forces layout/reflow. The comprehensive list.

What forces layout / reflow

All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.

Element

Box metrics
  • elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
  • elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
  • elem.getClientRects(), elem.getBoundingClientRect()
Scroll stuff
  • elem.scrollBy(), elem.scrollTo()
  • elem.scrollIntoView(), elem.scrollIntoViewIfNeeded()
  • elem.scrollWidth, elem.scrollHeight
  • elem.scrollLeft, elem.scrollTop also, setting them
Focus
  • elem.focus() can trigger a double forced layout (source&l=2923)
Also…
  • elem.computedRole, elem.computedName
  • elem.innerText (source&l=3440))

getComputedStyle

window.getComputedStyle() will typically force style recalc

window.getComputedStyle() will force layout, as well, if any of the following is true:

  1. The element is in a shadow tree
  2. There are media queries (viewport-related ones). Specifically, one of the following: (source)
  • min-width, min-height, max-width, max-height, width, height
  • aspect-ratio, min-aspect-ratio, max-aspect-ratio
  • device-pixel-ratio, resolution, orientation , min-device-pixel-ratio, max-device-pixel-ratio
  1. The property requested is one of the following: (source)
  • height, width
  • top, right, bottom, left
  • margin [-top, -right, -bottom, -left, or shorthand] only if the margin is fixed.
  • padding [-top, -right, -bottom, -left, or shorthand] only if the padding is fixed.
  • transform, transform-origin, perspective-origin
  • translate, rotate, scale
  • grid, grid-template, grid-template-columns, grid-template-rows
  • perspective-origin
  • These items were previously in the list but appear to not be any longer (as of Feb 2018): motion-path, motion-offset, motion-rotation, x, y, rx, ry

window

  • window.scrollX, window.scrollY
  • window.innerHeight, window.innerWidth
  • window.getMatchedCSSRules() only forces style

Forms

  • inputElem.focus()
  • inputElem.select(), textareaElem.select()

Mouse events

  • mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY (source)

document

  • doc.scrollingElement only forces style

Range

  • range.getClientRects(), range.getBoundingClientRect()

SVG

contenteditable

  • Lots & lots of stuff, …including copying an image to clipboard (source)

*Appendix

  • Reflow only has a cost if the document has changed and invalidated the style or layout. Typically, this is because the DOM was changed (classes modified, nodes added/removed, even adding a psuedo-class like :focus).
  • If layout is forced, style must be recalculated first. So forced layout triggers both operations. Their costs are very dependent on the content/situation, but typically both operations are similar in cost.
  • What should you do about all this? Well, the More on forced layout section below covers everything in more detail, but the short version is:
    1. for loops that force layout & change the DOM are the worst, avoid them.
    2. Use DevTools Timeline to see where this happens. You may be surprised to see how often your app code and library code hits this.
    3. Batch your writes & reads to the DOM (via FastDOM or a virtual DOM implementation). Read your metrics at the begininng of the frame (very very start of rAF, scroll handler, etc), when the numbers are still identical to the last time layout was done.

Timeline trace of The Guardian. Outbrain is forcing layout repeatedly, probably in a loop.
Cross-browser
Browsing the Chromium source:

CSS Triggers

CSS Triggers is a related resource and all about what operations are required to happen in the browser lifecycle as a result of setting/changing a given CSS value. It's a great resource. The above list, however, are all about what forces the purple/green/darkgreen circles synchronously from JavaScript.

More on forced layout


Updated slightly Feb 2018. Codesearch links and a few changes to relevant element properties.

@Theodeus

This comment has been minimized.

Show comment Hide comment
@Theodeus

Theodeus Sep 19, 2015

Mouse event offsets. Ouch.

Mouse event offsets. Ouch.

@pikharov

This comment has been minimized.

Show comment Hide comment
@pikharov

pikharov Sep 19, 2015

Looks like it can be easier to write down a list of stuff that wouldn't trigger a reflow. Like, you know, safe colors.

Looks like it can be easier to write down a list of stuff that wouldn't trigger a reflow. Like, you know, safe colors.

@tobireif

This comment has been minimized.

Show comment Hide comment
@tobireif

tobireif Sep 19, 2015

I hope Chrome can be improved so that the list becomes shorter.

I hope Chrome can be improved so that the list becomes shorter.

@d0mme

This comment has been minimized.

Show comment Hide comment
@d0mme

d0mme Sep 19, 2015

👍

d0mme commented Sep 19, 2015

👍

@kutec

This comment has been minimized.

Show comment Hide comment
@kutec

kutec Sep 19, 2015

Oh longer but awesome! 👍

Thanks for creating.

kutec commented Sep 19, 2015

Oh longer but awesome! 👍

Thanks for creating.

@webdesignberlin

This comment has been minimized.

Show comment Hide comment
@webdesignberlin

webdesignberlin Sep 19, 2015

Pretty long. Thanks for creating.

Pretty long. Thanks for creating.

@jakearchibald

This comment has been minimized.

Show comment Hide comment
@jakearchibald

jakearchibald Sep 19, 2015

@tobireif which of these do you consider to be bugs?

@tobireif which of these do you consider to be bugs?

@mohsen1

This comment has been minimized.

Show comment Hide comment
@mohsen1

mohsen1 Sep 19, 2015

What about CSS transition and animations?

mohsen1 commented Sep 19, 2015

What about CSS transition and animations?

@kuka

This comment has been minimized.

Show comment Hide comment
@kuka

kuka Sep 19, 2015

Thanks for the list Paul!

kuka commented Sep 19, 2015

Thanks for the list Paul!

@jlukic

This comment has been minimized.

Show comment Hide comment
@jlukic

jlukic Sep 19, 2015

Will keep in mind, thank you.

jlukic commented Sep 19, 2015

Will keep in mind, thank you.

@unbug

This comment has been minimized.

Show comment Hide comment
@unbug

unbug Sep 20, 2015

@paulirish I added some links to my fork,can you review them?

unbug commented Sep 20, 2015

@paulirish I added some links to my fork,can you review them?

@t0lkman

This comment has been minimized.

Show comment Hide comment
@t0lkman

t0lkman Sep 20, 2015

great work @paulirish

t0lkman commented Sep 20, 2015

great work @paulirish

@rafaeleyng

This comment has been minimized.

Show comment Hide comment
@rafaeleyng

rafaeleyng Sep 20, 2015

Very nice list, thanks.

Very nice list, thanks.

@glenn-allen

This comment has been minimized.

Show comment Hide comment
@glenn-allen

glenn-allen Sep 21, 2015

@paulirish, This is great, thanks!
Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?
On dynamic pages with transitions it seems incredibly difficult & problematic, however there doesn't seem to be much written about it in the community.

@paulirish, This is great, thanks!
Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?
On dynamic pages with transitions it seems incredibly difficult & problematic, however there doesn't seem to be much written about it in the community.

@jt3k

This comment has been minimized.

Show comment Hide comment
@jt3k

jt3k Sep 21, 2015

ok

jt3k commented Sep 21, 2015

ok

@jenshedqvist

This comment has been minimized.

Show comment Hide comment
@jenshedqvist

jenshedqvist Sep 21, 2015

Ok, so basically what the browser and DOM tells us is "don't touch me!". And it's our job to respect that and optimize where we hurt it and the user attached to it. Prioritize, cache/store, debounce etc.

Ok, so basically what the browser and DOM tells us is "don't touch me!". And it's our job to respect that and optimize where we hurt it and the user attached to it. Prioritize, cache/store, debounce etc.

@danburzo

This comment has been minimized.

Show comment Hide comment
@danburzo

danburzo Sep 21, 2015

You know what would be cool? A Sublime Text plugin to highlight all these in JavaScript files.
I'm looking into how this might be done.

You know what would be cool? A Sublime Text plugin to highlight all these in JavaScript files.
I'm looking into how this might be done.

@njoyard

This comment has been minimized.

Show comment Hide comment
@njoyard

njoyard Sep 21, 2015

@paulirish unfortunately, this is only a list of what may cause a reflow. In my case (preparing a complex print layout using CSS columns), I actually need reflows sometimes (mainly after splitting table/ul elements) and the list you present above is not accurate in that perspective. Some research should be done as to whether those always cause a reflow, or if they need specific conditions.

njoyard commented Sep 21, 2015

@paulirish unfortunately, this is only a list of what may cause a reflow. In my case (preparing a complex print layout using CSS columns), I actually need reflows sometimes (mainly after splitting table/ul elements) and the list you present above is not accurate in that perspective. Some research should be done as to whether those always cause a reflow, or if they need specific conditions.

@akost

This comment has been minimized.

Show comment Hide comment
@akost

akost Sep 22, 2015

Thanks!

akost commented Sep 22, 2015

Thanks!

@simevidas

This comment has been minimized.

Show comment Hide comment
@simevidas

simevidas Sep 22, 2015

@paulirish If I change the DOM (e.g. set a class on an element), but don’t force a reflow in my code, when will the reflow happen? Before or after the requestAnimationFrame callback? This demo suggests before. I thought the whole purpose of rAF is to update the DOM, so why did the browser reflow before, when it is expected that the rAF callback will make another reflow necessary. What am I missing?

Update: Nevermind. getComputedStyle forced the reflow. My bad. But if I didn’t force it within the rAF callback, would it have happened by then? (Not sure if onto something, or asking a stupid question.)

@paulirish If I change the DOM (e.g. set a class on an element), but don’t force a reflow in my code, when will the reflow happen? Before or after the requestAnimationFrame callback? This demo suggests before. I thought the whole purpose of rAF is to update the DOM, so why did the browser reflow before, when it is expected that the rAF callback will make another reflow necessary. What am I missing?

Update: Nevermind. getComputedStyle forced the reflow. My bad. But if I didn’t force it within the rAF callback, would it have happened by then? (Not sure if onto something, or asking a stupid question.)

@jakearchibald

This comment has been minimized.

Show comment Hide comment
@jakearchibald

jakearchibald Sep 22, 2015

@simevidas it depends on when you changed the dom.

See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ for how the event loop works - rendering is part of this, and raf is called just before a natural style calc, layout, and paint.

So, if you make dom changes as part of a task, then read layout/style values in another task, you may trigger a sync calc/layout, because the browser doesn't always render in between tasks, as the loop can run faster than 60hz.

Similarly, if you make a dom change in a task, then read in a raf, you'll get a sync layout.

Ideally, treat your tasks as layout/style read only, and do your writes within raf.

@simevidas it depends on when you changed the dom.

See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ for how the event loop works - rendering is part of this, and raf is called just before a natural style calc, layout, and paint.

So, if you make dom changes as part of a task, then read layout/style values in another task, you may trigger a sync calc/layout, because the browser doesn't always render in between tasks, as the loop can run faster than 60hz.

Similarly, if you make a dom change in a task, then read in a raf, you'll get a sync layout.

Ideally, treat your tasks as layout/style read only, and do your writes within raf.

@jpmedley

This comment has been minimized.

Show comment Hide comment
@jpmedley

jpmedley Sep 22, 2015

Nice work, Paul.

Nice work, Paul.

@mayankchd

This comment has been minimized.

Show comment Hide comment
@mayankchd

mayankchd Sep 23, 2015

In the case of reflow does the whole dom is recalculated or only the element that is changed ?

In the case of reflow does the whole dom is recalculated or only the element that is changed ?

@adardesign

This comment has been minimized.

Show comment Hide comment
@adardesign

adardesign Sep 24, 2015

Very helpful and a step closer to a smoother and jank freeer experience
Thanks!

Very helpful and a step closer to a smoother and jank freeer experience
Thanks!

@ephraimtabackman

This comment has been minimized.

Show comment Hide comment
@ephraimtabackman

ephraimtabackman Sep 24, 2015

computeRelativePosition() is only called if it is dirty. If the value has already been computed it will not be called again. Instead, it will be read from the cached m_layerLocation.

computeRelativePosition() is only called if it is dirty. If the value has already been computed it will not be called again. Instead, it will be read from the cached m_layerLocation.

@mayrop

This comment has been minimized.

Show comment Hide comment
@mayrop

mayrop Sep 25, 2015

Very helpful, thank you!

mayrop commented Sep 25, 2015

Very helpful, thank you!

@SpoBo

This comment has been minimized.

Show comment Hide comment
@SpoBo

SpoBo Sep 28, 2015

Can someone make a linter for this?

SpoBo commented Sep 28, 2015

Can someone make a linter for this?

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Sep 28, 2015

@paulirish I added some links to my fork,can you review them?

@unbug merged those links back in. thank you!

Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?

@glenn-allen, TBH this focus discovery above was unexpected and new to me. It requires some more investigation. The most concrete thing I can offer right now is… If you need to set focus(), do it at the start of the event handler, before any changes to the DOM.

unfortunately, this is only a list of what may cause a reflow.

@njoyard, as long as the DOM is dirty, what I listed above will def cause a reflow. Whether the browser paints immediately after isn't guaranteed, however.

In the case of reflow does the whole dom is recalculated or only the element that is changed ?

@mayankchd browsers try to be smart about it, but typically (probably ~75% of the time) it's the whole DOM. A "layout boundary" or "relayout root" can help to contain the layout: http://wilsonpage.co.uk/introducing-layout-boundaries/ It's effective, but requires a fixed width and height.

Very helpful, thank you!

@mayrop my pleasure. :)

Owner

paulirish commented Sep 28, 2015

@paulirish I added some links to my fork,can you review them?

@unbug merged those links back in. thank you!

Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?

@glenn-allen, TBH this focus discovery above was unexpected and new to me. It requires some more investigation. The most concrete thing I can offer right now is… If you need to set focus(), do it at the start of the event handler, before any changes to the DOM.

unfortunately, this is only a list of what may cause a reflow.

@njoyard, as long as the DOM is dirty, what I listed above will def cause a reflow. Whether the browser paints immediately after isn't guaranteed, however.

In the case of reflow does the whole dom is recalculated or only the element that is changed ?

@mayankchd browsers try to be smart about it, but typically (probably ~75% of the time) it's the whole DOM. A "layout boundary" or "relayout root" can help to contain the layout: http://wilsonpage.co.uk/introducing-layout-boundaries/ It's effective, but requires a fixed width and height.

Very helpful, thank you!

@mayrop my pleasure. :)

@Lewiscowles1986

This comment has been minimized.

Show comment Hide comment
@Lewiscowles1986

Lewiscowles1986 Sep 28, 2015

@paulirish this is just JS triggered changes or would CSS be the same / worse?

@paulirish this is just JS triggered changes or would CSS be the same / worse?

@tigt

This comment has been minimized.

Show comment Hide comment
@tigt

tigt Sep 28, 2015

@paulirish So if we need to scroll to a particular element, is setting the hash the most performant option?

tigt commented Sep 28, 2015

@paulirish So if we need to scroll to a particular element, is setting the hash the most performant option?

@JoeMilsom

This comment has been minimized.

Show comment Hide comment
@JoeMilsom

JoeMilsom Sep 29, 2015

Think window.pageXOffset/window.pageYOffset causes a relayout as well. At least in Chrome.

Think window.pageXOffset/window.pageYOffset causes a relayout as well. At least in Chrome.

@glenn-allen

This comment has been minimized.

Show comment Hide comment
@glenn-allen

glenn-allen Sep 29, 2015

@paulirish - Thanks for the response, greatly appreciated!

@paulirish - Thanks for the response, greatly appreciated!

@bfred-it

This comment has been minimized.

Show comment Hide comment
@bfred-it

bfred-it Sep 29, 2015

Can somebody explain to me why window.innerHeight and window.innerWidth would force a layout? They don't event depend on the DOM.

Can somebody explain to me why window.innerHeight and window.innerWidth would force a layout? They don't event depend on the DOM.

@aFarkas

This comment has been minimized.

Show comment Hide comment
@aFarkas

aFarkas Sep 29, 2015

Please developers, don't be scared of those methods and properties. In fact those work extremely fast and can be called/accessed a "million time" without any harm. The problem is not whether you use them, but when/how.

Ideally, treat your tasks as layout/style read only, and do your writes within raf.

The following little function might help to organize your code, while doing this read/write separation. It's similar to Function.prototype.bind:

/*
* returns a function, that is wrapped in a requestAnimationFrame. Useful to separate read from write.
* While all reads can happen where needed (but never inside a rAF) any DOM writes should happen inside a rAF.
* @param {function} fn - function that should be wrapped in a rAF
* @param {object} [options] - options
*   @param {object} [options.that] - the this context in which the function should be invoked (binds that to the function)
*   @param {object} [options.batch] - whether multiple calls to the function during one frame should be let through or should be throttled to the last call
*
*   example usage:
 class MyWidget {
     constructor(element){
         this.element = element;
         this.changeWidget = writeFn(this.changeWidget);

         this.checkWidget();
         //add resize events and do more useful things....
     }

     changeWidget(add){
        this.element.classList[add ? 'add' : 'remove']('is-large-widget');
     }

     checkWidget(){
        this.changeWidget(this.element.offsetWidth > 600);
     }
 }
*/

var writeFn = function(fn, options){
    var running, args, that;
    var batchStack = [];
    var run = function(){
        running = false;
        if(options.batch){
            while(batchStack.length){
                args = batchStack.shift();
                fn.apply(args[0], args[1]);
            }
        } else {
            fn.apply(that, args);
        }
    };

    if(!options){
        options = {};
    }

    return function(){
        args = arguments;
        that = options.that || this;
        if(options.batch){
            batchStack.push([that, args]);
        }

        if(!running){
            running = true;
            requestAnimationFrame(run);
        }
    };
};

aFarkas commented Sep 29, 2015

Please developers, don't be scared of those methods and properties. In fact those work extremely fast and can be called/accessed a "million time" without any harm. The problem is not whether you use them, but when/how.

Ideally, treat your tasks as layout/style read only, and do your writes within raf.

The following little function might help to organize your code, while doing this read/write separation. It's similar to Function.prototype.bind:

/*
* returns a function, that is wrapped in a requestAnimationFrame. Useful to separate read from write.
* While all reads can happen where needed (but never inside a rAF) any DOM writes should happen inside a rAF.
* @param {function} fn - function that should be wrapped in a rAF
* @param {object} [options] - options
*   @param {object} [options.that] - the this context in which the function should be invoked (binds that to the function)
*   @param {object} [options.batch] - whether multiple calls to the function during one frame should be let through or should be throttled to the last call
*
*   example usage:
 class MyWidget {
     constructor(element){
         this.element = element;
         this.changeWidget = writeFn(this.changeWidget);

         this.checkWidget();
         //add resize events and do more useful things....
     }

     changeWidget(add){
        this.element.classList[add ? 'add' : 'remove']('is-large-widget');
     }

     checkWidget(){
        this.changeWidget(this.element.offsetWidth > 600);
     }
 }
*/

var writeFn = function(fn, options){
    var running, args, that;
    var batchStack = [];
    var run = function(){
        running = false;
        if(options.batch){
            while(batchStack.length){
                args = batchStack.shift();
                fn.apply(args[0], args[1]);
            }
        } else {
            fn.apply(that, args);
        }
    };

    if(!options){
        options = {};
    }

    return function(){
        args = arguments;
        that = options.that || this;
        if(options.batch){
            batchStack.push([that, args]);
        }

        if(!running){
            running = true;
            requestAnimationFrame(run);
        }
    };
};
@napengam

This comment has been minimized.

Show comment Hide comment
@napengam

napengam Sep 30, 2015

Good to know, thanks !

However I don't care because systems are getting faster and faster all the time.
As long as the responds time is acceptable for and by the user , it is all fine.

BTW. what about

obj.style.display
obj.style.visibility
obj.style.position

Good to know, thanks !

However I don't care because systems are getting faster and faster all the time.
As long as the responds time is acceptable for and by the user , it is all fine.

BTW. what about

obj.style.display
obj.style.visibility
obj.style.position

@pvolyntsev

This comment has been minimized.

Show comment Hide comment
@pvolyntsev

pvolyntsev Oct 7, 2015

The changes that achieve silky smooth animations

As quote from the article http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/

Today transforms are the best properties to animate because the GPU can assist with the heavy lifting,
so where you can limit your animations to these, do so.

opacity opacity: 0...1 ;
position transform: translate(_n_px, _n_px) ;
rotate transform: rotate(_n_deg) ;
scale transform: scale(n) ;

P.S. I see, it's yours :)

The changes that achieve silky smooth animations

As quote from the article http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/

Today transforms are the best properties to animate because the GPU can assist with the heavy lifting,
so where you can limit your animations to these, do so.

opacity opacity: 0...1 ;
position transform: translate(_n_px, _n_px) ;
rotate transform: rotate(_n_deg) ;
scale transform: scale(n) ;

P.S. I see, it's yours :)

@aFarkas

This comment has been minimized.

Show comment Hide comment
@aFarkas

aFarkas Nov 30, 2015

@paulirish

The cause of the forced layout of focus is, that focus first invalidates layout (by applying :focus styles) and then invoking the scrollIntoView algorithm.

The later is also a pain if you want to create accessible and animated UI components (see: http://allyjs.io/api/when/focusable.html). Maybe a new API that sets focus without invoking the scrollIntoView algorithm would be great.

aFarkas commented Nov 30, 2015

@paulirish

The cause of the forced layout of focus is, that focus first invalidates layout (by applying :focus styles) and then invoking the scrollIntoView algorithm.

The later is also a pain if you want to create accessible and animated UI components (see: http://allyjs.io/api/when/focusable.html). Maybe a new API that sets focus without invoking the scrollIntoView algorithm would be great.

@Cristy94

This comment has been minimized.

Show comment Hide comment
@Cristy94

Cristy94 Dec 2, 2015

What about CSS transition and animations?

+1

Why do CSS transitions on the transform property trigger Layout? Makes no sense.
http://jsfiddle.net/cygvaubo/1/

Without the transition everything seems fine.

LE: Adding will-change seems to fix this issue: http://jsfiddle.net/cygvaubo/3/ but text quality drops.

Cristy94 commented Dec 2, 2015

What about CSS transition and animations?

+1

Why do CSS transitions on the transform property trigger Layout? Makes no sense.
http://jsfiddle.net/cygvaubo/1/

Without the transition everything seems fine.

LE: Adding will-change seems to fix this issue: http://jsfiddle.net/cygvaubo/3/ but text quality drops.

@dmnd

This comment has been minimized.

Show comment Hide comment
@dmnd

dmnd Dec 8, 2015

Can somebody explain to me why window.innerHeight and window.innerWidth would force a layout? They don't event depend on the DOM.

@bfred-it window.innerHeight and window.innerWidth depend on whether or not a scrollbar is visible, so they do depend on the DOM. (That's an assumption — someone more knowledgable please confirm or contradict)

dmnd commented Dec 8, 2015

Can somebody explain to me why window.innerHeight and window.innerWidth would force a layout? They don't event depend on the DOM.

@bfred-it window.innerHeight and window.innerWidth depend on whether or not a scrollbar is visible, so they do depend on the DOM. (That's an assumption — someone more knowledgable please confirm or contradict)

@pygy

This comment has been minimized.

Show comment Hide comment
@pygy

pygy Feb 9, 2016

@paulirish What do you mean by "The element is in a shadow tree"?

Edit: As in shadow DOM?

pygy commented Feb 9, 2016

@paulirish What do you mean by "The element is in a shadow tree"?

Edit: As in shadow DOM?

@riskers

This comment has been minimized.

Show comment Hide comment
@riskers

riskers Apr 6, 2016

how to use timeline check dom is repint or reflow?

riskers commented Apr 6, 2016

how to use timeline check dom is repint or reflow?

@yardfarmer

This comment has been minimized.

Show comment Hide comment
@yardfarmer

yardfarmer Apr 19, 2016

@bvaughn

This comment has been minimized.

Show comment Hide comment
@bvaughn

bvaughn Jun 20, 2016

Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?

@glenn-allen, TBH this focus discovery above was unexpected and new to me. It requires some more investigation. The most concrete thing I can offer right now is… If you need to set focus(), do it at the start of the event handler, before any changes to the DOM.

@paulirish: It's been a few months since you left this comment. Don't suppose you have more insight or suggestions for dealing with it? Recently ran into this snag when trying to optimize scrolling frame rate for react-virtualized. A focused grid repaints entirely on-scroll whereas an unfocused one only paints newly-added rows. Unfortunately focus is a necessary part of a11y for the library.

Just thought I'd ask in case you had any pointers! Thanks for putting together this gist! :)

bvaughn commented Jun 20, 2016

Regarding focus: Given it's an important part of accessibility but it appears to be performance bottleneck (double forced layout) do you have any recommendations on how to avoid or reduce its impact while maintaining accessibility (beyond simply avoiding layout thrashing)?

@glenn-allen, TBH this focus discovery above was unexpected and new to me. It requires some more investigation. The most concrete thing I can offer right now is… If you need to set focus(), do it at the start of the event handler, before any changes to the DOM.

@paulirish: It's been a few months since you left this comment. Don't suppose you have more insight or suggestions for dealing with it? Recently ran into this snag when trying to optimize scrolling frame rate for react-virtualized. A focused grid repaints entirely on-scroll whereas an unfocused one only paints newly-added rows. Unfortunately focus is a necessary part of a11y for the library.

Just thought I'd ask in case you had any pointers! Thanks for putting together this gist! :)

@trusktr

This comment has been minimized.

Show comment Hide comment
@trusktr

trusktr Jul 5, 2016

Mouse event offsets. Ouch.

@Theodus This is why I've taken the stance at starting new projects with all events disabled, then enabling them only as needed, and also using only transforms as much as possible with constant sizing.

trusktr commented Jul 5, 2016

Mouse event offsets. Ouch.

@Theodus This is why I've taken the stance at starting new projects with all events disabled, then enabling them only as needed, and also using only transforms as much as possible with constant sizing.

@trusktr

This comment has been minimized.

Show comment Hide comment
@trusktr

trusktr Jul 5, 2016

@paulirish, you have unanswered questions that need your respected and appreciated attention.

trusktr commented Jul 5, 2016

@paulirish, you have unanswered questions that need your respected and appreciated attention.

@grese

This comment has been minimized.

Show comment Hide comment
@grese

grese Aug 24, 2016

Nice :) Thanks for taking the time to put this together!

grese commented Aug 24, 2016

Nice :) Thanks for taking the time to put this together!

@przeor

This comment has been minimized.

Show comment Hide comment
@przeor

przeor Sep 1, 2016

Hi I see that you use React, so I am sure that you will find interesting the https://reactjs.co - this is the free online convention and tutorial book for React.JS Developers. React is not only the View (in MVC) anymore. ReactJS For Dummies: Why & How to Learn React Redux, the Right Way.

przeor commented Sep 1, 2016

Hi I see that you use React, so I am sure that you will find interesting the https://reactjs.co - this is the free online convention and tutorial book for React.JS Developers. React is not only the View (in MVC) anymore. ReactJS For Dummies: Why & How to Learn React Redux, the Right Way.

@ckomop0x

This comment has been minimized.

Show comment Hide comment
@ckomop0x

ckomop0x Jan 20, 2017

Nice =) Thanx!

Nice =) Thanx!

@hereisfun

This comment has been minimized.

Show comment Hide comment
@hereisfun

hereisfun Mar 1, 2017

I'm suprised that according to CSS Triggers, visibility and opacity will also trigger reflow in WebKit. It makes me confused. Aren't they only visual properties?

I'm suprised that according to CSS Triggers, visibility and opacity will also trigger reflow in WebKit. It makes me confused. Aren't they only visual properties?

@stevemao

This comment has been minimized.

Show comment Hide comment
@stevemao

stevemao Mar 28, 2017

@hereisfun Probably because WebKit is not optimised for them

@hereisfun Probably because WebKit is not optimised for them

@kaseopea

This comment has been minimized.

Show comment Hide comment
@kaseopea

kaseopea May 11, 2017

@njoyard I have faced with the same - complex layout using CSS columns. And I have a problem on Ipad. When I change orientation from landscape to portrait css columns doesn't repaint for the first time. Did you experience this issue on Ipad? If so, how did you solve this?

kaseopea commented May 11, 2017

@njoyard I have faced with the same - complex layout using CSS columns. And I have a problem on Ipad. When I change orientation from landscape to portrait css columns doesn't repaint for the first time. Did you experience this issue on Ipad? If so, how did you solve this?

@tarekahf

This comment has been minimized.

Show comment Hide comment
@tarekahf

tarekahf Jun 20, 2017

I am using ngProgress in my project which has large number of directives with $compile service. It seems that the progress bar won't show unless all elements are compiled. I tried to use several methods as mentioned in this post, but none of them worked. I am using ngProgress.start() as in the beginning of the ng-controller, and yet, the progress bar won't show until almost everything is done.

Appreciate your help to solve this problem.

More details here.

Tarek

tarekahf commented Jun 20, 2017

I am using ngProgress in my project which has large number of directives with $compile service. It seems that the progress bar won't show unless all elements are compiled. I tried to use several methods as mentioned in this post, but none of them worked. I am using ngProgress.start() as in the beginning of the ng-controller, and yet, the progress bar won't show until almost everything is done.

Appreciate your help to solve this problem.

More details here.

Tarek

@jeremychone

This comment has been minimized.

Show comment Hide comment
@jeremychone

jeremychone Jun 21, 2017

Thanks for spending the time to share this.

Thanks for spending the time to share this.

@Gibolt

This comment has been minimized.

Show comment Hide comment
@Gibolt

Gibolt Jul 2, 2017

@trusktr

This comment has been minimized.

Show comment Hide comment
@trusktr

trusktr Jul 7, 2017

Does adding an element with display:none cause any layout (without reading those above listed properties)? f.e., if I add a bunch of SVG elements to the DOM, and the <svg> is display:none, can I avoid any overhead?

trusktr commented Jul 7, 2017

Does adding an element with display:none cause any layout (without reading those above listed properties)? f.e., if I add a bunch of SVG elements to the DOM, and the <svg> is display:none, can I avoid any overhead?

@prchando

This comment has been minimized.

Show comment Hide comment
@prchando

prchando Jul 22, 2017

Is there a way to test what causes reflow/layout/repaint and what does not

Is there a way to test what causes reflow/layout/repaint and what does not

@PraveenVignesh

This comment has been minimized.

Show comment Hide comment
@PraveenVignesh

PraveenVignesh Oct 13, 2017

@paulirish @SpoBo did you find any linter for Layout thrashing? If so please share the code.
Thanks.

@paulirish @SpoBo did you find any linter for Layout thrashing? If so please share the code.
Thanks.

@metavurt

This comment has been minimized.

Show comment Hide comment
@metavurt

metavurt Oct 21, 2017

@holmberd

This comment has been minimized.

Show comment Hide comment
@holmberd

holmberd Dec 10, 2017

Using document.getSelection().removeAllRanges(); does in some cases cause this when toggling elements visibility with display: none.

Using document.getSelection().removeAllRanges(); does in some cases cause this when toggling elements visibility with display: none.

@sambgordon

This comment has been minimized.

Show comment Hide comment
@sambgordon

sambgordon Jan 16, 2018

Awesome, thank you!

Awesome, thank you!

@fmortens

This comment has been minimized.

Show comment Hide comment
@fmortens

fmortens Jan 30, 2018

Just curious. Could the elem.blur() also trigger a repaint?

Just curious. Could the elem.blur() also trigger a repaint?

@Cerbrus

This comment has been minimized.

Show comment Hide comment
@Cerbrus

Cerbrus Feb 1, 2018

In your Appendix, the <center> tags around the image break GitHub's markdown rendering for that image.

See my fork, compared to yours ;-)

Or, for your convenience, a rich diff

Cerbrus commented Feb 1, 2018

In your Appendix, the <center> tags around the image break GitHub's markdown rendering for that image.

See my fork, compared to yours ;-)

Or, for your convenience, a rich diff

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Feb 6, 2018

@Cerbrus thanks!! fixed.

Owner

paulirish commented Feb 6, 2018

@Cerbrus thanks!! fixed.

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Feb 6, 2018

@fmortens yes i've seen blur() DEFINITELY force layout before. good question as to why its not on my list. i'll take another look.

update: nevermind, i was thinking of focus()

Owner

paulirish commented Feb 6, 2018

@fmortens yes i've seen blur() DEFINITELY force layout before. good question as to why its not on my list. i'll take another look.

update: nevermind, i was thinking of focus()

@ExtAnimal

This comment has been minimized.

Show comment Hide comment
@ExtAnimal

ExtAnimal Feb 14, 2018

@paulirish pretty important addition:

elem.classList.remove('this-class-is-NOT-in-the-classlist') invalidates the layout. This is poor behaviour from the browser vendors!

@paulirish pretty important addition:

elem.classList.remove('this-class-is-NOT-in-the-classlist') invalidates the layout. This is poor behaviour from the browser vendors!

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Feb 22, 2018

@fmortens blur() doesn't force a layout. You can verify if you profile this:

document.body.style.background = '';

document.body.onclick = e => {
 document.body.style.background = `hsl(${Math.floor(Math.random()*360)}, 50%, 50%)`; 
  now = Date.now(); 
  document.querySelector('#i').blur();
  while (Date.now() < now + 10) { }
}

@ExtAnimal yes technically invalidation is an entirely different thing. It's a shame classList.remove(fakeclassname) does an invalidation; you can file it on crbug.com and there's a good change an engineer will take it on.

Owner

paulirish commented Feb 22, 2018

@fmortens blur() doesn't force a layout. You can verify if you profile this:

document.body.style.background = '';

document.body.onclick = e => {
 document.body.style.background = `hsl(${Math.floor(Math.random()*360)}, 50%, 50%)`; 
  now = Date.now(); 
  document.querySelector('#i').blur();
  while (Date.now() < now + 10) { }
}

@ExtAnimal yes technically invalidation is an entirely different thing. It's a shame classList.remove(fakeclassname) does an invalidation; you can file it on crbug.com and there's a good change an engineer will take it on.

@MorrisJohns

This comment has been minimized.

Show comment Hide comment
@MorrisJohns

MorrisJohns Mar 15, 2018

@paulirish: In theory window.innerHeight and window.innerWidth should never cause a layout / reflow because the values do not include the scrollbar thickness (I tested this and also MDN agrees in documentation for window.innerHeight albeit not said well: "Height (in pixels) of the browser window viewport including, if rendered, the horizontal scrollbar"). I checked all your links and I could find nothing relevant, although I am not sure how you test for reflow (@bfred-it also asked about this. @dmnd commented but I am contradicting his assumption as he asked!).

MorrisJohns commented Mar 15, 2018

@paulirish: In theory window.innerHeight and window.innerWidth should never cause a layout / reflow because the values do not include the scrollbar thickness (I tested this and also MDN agrees in documentation for window.innerHeight albeit not said well: "Height (in pixels) of the browser window viewport including, if rendered, the horizontal scrollbar"). I checked all your links and I could find nothing relevant, although I am not sure how you test for reflow (@bfred-it also asked about this. @dmnd commented but I am contradicting his assumption as he asked!).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment