Platform/Layout/CSS Containment Best Practices

From MozillaWiki
Jump to: navigation, search

We are experimenting with enabling CSS Containment in Firefox frontend code. We've got some bugs to fix before we expose it more broadly, but it's already useful enough for internal use. This wiki page exists to document the anticipated best-practices for using CSS Containment in Firefox frontend code.


For now, the primary benefit of CSS Containment is to tag a frame as a "reflow root", which allows Gecko to initiate reflow directly on that frame (rather than initiating reflow at the root of the frame tree and traversing the tree from there to find dirty frames). This should allow layout flushes to be cheaper, and may cut down on jank.

Anticipated Best Practices

  • Use the CSS contain: layout size to indicate that you'd like a particular element to be a reflow root.
  • A good candidate for CSS containment should match the following conditions:
    • It should be HTML (not XUL). We don't intend to implement CSS Containment for XUL.
    • It should be fixed-size (it shouldn't depend on its contents for sizing). The size containment keyword makes the element size itself as if it had no children, which in most cases means it'll collapse to nothing unless you give it a specified width and/or height.
    • It should have descendants which are expected to change & trigger frequent reflows. (For example: the web console's text-input area, which requires a reflow for every keypress as new user-typed characters are added & trigger context-highlighting.)
    • It should be in a document where there may be lots of content outside of the contained element's subtree (so that there will be nontrivial amounts of reflow work that we can avoid by applying containment).
  • Do not use CSS containment on:
    • ...lots and lots of elements. Reflow roots are stored in a flat list, and it's possible there may be a negative performance impact if there are too many of them. (See e.g. https://bugzilla.mozilla.org/show_bug.cgi?id=1510100 -- needs further study...)
    • ...inline-level elements or internal table elements (for which containment simply has no effect)
    • ...XUL elements.
    • ...elements whose descendants do not change frequently.
  • Also, be aware that contain:layout size has some spec-mandated side effects:
    • It will make the element a containing block for any fixed- or absolutely-positioned descendants.
    • If the element doesn't have a specified size, it may collapse to zero (sizing as if it has no children).