PSA: New JS helpers to query layout state without forcing reflow

Mike Conley mconley at mozilla.com
Wed Aug 2 19:22:22 UTC 2017


Yes, I'll update that document today.

This is tremendous, kmag. Thank you for your work here!

On 2017-08-02 3:16 PM, J. Ryan Stinnett wrote:
> Might be useful to list somewhere on the frontend practices page,
> especially so these caveats are captured.
> 
> https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
> 
> - Ryan
> 
> On Wed, Aug 2, 2017 at 2:11 PM, Kris Maglione <kmaglione at mozilla.com
> <mailto:kmaglione at mozilla.com>> wrote:
> 
>     In bug 1383367, I landed a set of new helpers to make it possible to
>     query the layout state (e.g., element size and position, or computed
>     style such as color) without forcing an uninterruptible reflow.
> 
>     Note: Please read on for caveats before jumping into using this.
> 
>     The one that you probably really care about is
>     promiseLayoutFlushed[1], which is in a lot of ways the converse of
>     (and complement to) requestAnimationFrame. Its use looks something
>     like this:
> 
>        let width = await BrowserUtils.promiseLayoutFlushed(document,
>     "layout", () => {
>          return elem.clientWidth;
>        });
> 
>        requestAnimationFrame(() => {
>          otherElem.style.width = `${width - 2*borderWidth}px`;
>        });
> 
>     This will cause the layout width of an element to be queried as soon
>     as that's possible without a reflow (which may be immediately, or
>     just after some other code queries the layout state, or just after
>     the next paint), and then uses that width to update the DOM in the
>     next animation frame.
> 
>     Essentially, as long as your `promiseLayoutFlushed` callback queries
>     the layout *but never alters the DOM*, and your
>     requestAnimationFrame callbacks alter the DOM *but never query the
>     layout*, all queries and updates should happen in groups, and we
>     shouldn't have any uninterruptible reflows. In theory, either of
>     these things on their own should be enough to guarantee that, but in
>     practice, we have a lot of legacy code that doesn't follow those
>     rules, so this is another tool in our toolbox to get us close to
>     that ideal.
> 
> 
>     Important caveats: *Please* be careful how you use this. And
>     especially keep in mind that there may need to be a paint before
>     your promise resolves and any dependent DOM updates happen. If
>     you're not absolutely sure that that won't result in glitchy UI
>     behavior, *please test carefully* to make sure that it doesn't.
> 
>     At the moment, the implementation is fairly crude, and any callbacks
>     which need to be deferred happen after the next full reflow, even if
>     a full reflow isn't required. And there's no way to force deferred
>     callbacks to be handled before the next paint aside from forcing a
>     layout flush. It should be possible in the future, though, to
>     schedule an interruptible reflow just before the next animation
>     frame in cases where we know that's required, and trigger our
>     deferred callbacks before paint. If you have a particular need for
>     that, please let me know and I may be able to make it a higher priority.
> 
> 
> 
>     [1]:
>     https://dxr.mozilla.org/mozilla-central/rev/ef9a0f01e4f68214f0ff8f4631783b8a0e075a82/toolkit/modules/BrowserUtils.jsm#702-729
>     <https://dxr.mozilla.org/mozilla-central/rev/ef9a0f01e4f68214f0ff8f4631783b8a0e075a82/toolkit/modules/BrowserUtils.jsm#702-729>
>     _______________________________________________
>     firefox-dev mailing list
>     firefox-dev at mozilla.org <mailto:firefox-dev at mozilla.org>
>     https://mail.mozilla.org/listinfo/firefox-dev
>     <https://mail.mozilla.org/listinfo/firefox-dev>
> 
> 
> 
> 
> _______________________________________________
> firefox-dev mailing list
> firefox-dev at mozilla.org
> https://mail.mozilla.org/listinfo/firefox-dev
> 


More information about the firefox-dev mailing list