Placeholder Image

字幕列表 影片播放

  • Hello everyone and

  • Thanks the organization for giving me the chance to give this talk here, in the last CSSconf edition in this type or whatever

  • So it's really a pleasure and an honor to be here in this great conference

  • So the title of my talk is "Improving Website Performance with CSS Containment"

  • So quite a long title even doesn't fit on the slide, so I will go over it slowly

  • So first, let's explain a little bit about me. I'm Manuel Rego

  • I'm part of Igalia Web Pplatform team. Igalia is an open source consultancy that

  • has a

  • Cooperative like structure, so we have people all around the globe

  • despite the headquarter are in Spain and

  • we have a large team working on browsers and we having implementing in several CSS

  • specifications and other things on browsers

  • I have been working on Grid Layout mostly for several years

  • And also other specs in Blink and WebKit and now I'm working also in the CSS Containment

  • And as part of all these work I having interacting more and more with the CSS Working Group people

  • Putting issues participating in discussions and finally joined the group like two years ago

  • So

  • Yeah the spec I mean the talk is about CSS Containment. This is a CSS spec

  • this spec has a property that is called "contain" and it has four values "layout", "paint", "size" and "style" and that's all

  • We are almost done

  • I mean, it's very simple in theory

  • But I think is going to be tricky to explain

  • Maybe you watched some of my talks about Grid Layout or read some of my blog post about it.

  • I mean

  • Grid has tons of properties, many different values for each of them and all that

  • But I believe it's easier to understand that maybe CSS Containment

  • So let's see if I manage to do it properly and you don't get very bored

  • So the other part of the title was improving website performance

  • So basically you can improve the performance of a website in many different parts

  • You can improve how images are loaded or the resources or whatever. In this case is more about the rendering pipeline

  • These are somehow the main phases from a very nice article by Lin Clark

  • So you have like where you compute the style you do the layout where you are

  • Positioning the things then you paint and then you composite the layers

  • And basically with CSS Containment you're going to be able to get performance benefits in this pipeline

  • So, let's go to the spec, the spec is now candidate recommendation

  • So it's quite a stable at this stage

  • And we will explain how it works and try to explain the different options and all that. So basically the main goal of

  • CSS Containment is to improve the performance of a website by

  • identifying the

  • independent parts of a website which are

  • parts of the DOM tree that doesn't have to interact with the rest, so somehow it's like isolating

  • that subtree from the rest of the page

  • In a way that if you do modifications inside that subtree

  • they don't get propagated outside so you don't need to do work in the

  • ancestors and all that

  • One confusing thing about containment when you first read about it or you hear about it is that

  • is not that things outside cannot affect the elements inside, is not top to bottom. But is the other way around

  • Things inside that element are not going to affect anything outside

  • So this is a sentence

  • By Tab Atkins, one of the spec editors, that he usually needs to repeat over a over in the CSS Working Group meetings

  • "contain" property doesn't block things going into the subtree, it blocks things leaking out

  • So it's quite relevant for all the containment stuff

  • So yeah, I already say that. This spec only introduces a new property, which name is "contain"

  • So it's very easy to remember and this property has four values, main values, or types of containments

  • layout, paint, size, style. You can just put one or put two combine or combine the four, you can do whatever you want there

  • style is red in the slides because it's market as at risk now in the spec, so we will talk more later about that

  • So imagine this is a website. You have some content, some text, the header, whatever and

  • you know that you have a component, maybe in the top left corner

  • For example that you are showing some live information that you are getting or showing

  • an animation or whatever, but you know that's totally independent from the rest of the page

  • So you identify that part, mark it like a contained element

  • And when the browser does work there, it doesn't need to care about the rest of the pages

  • The page is very big or very complex DOM tree or whatever

  • The browser doesn't need to spend any single time in doing other stuff

  • So basically what web authors will need to do is to identify

  • which are that independent parts of a website and mark them with the "contain" property and then

  • The browser engine needs to do

  • something because it's not just parse the property and

  • implement the restrictions but also it needs to implement some optimizations and avoid doing extra work. Browser engines usually

  • Try to do as less work as possible

  • When you do a change in a website, they have some kind of heuristics in order to achieve that

  • But still there are many corner cases and many combinations of things

  • So when you do a change on a single element that you believe is

  • Not going to affect anything else

  • The browser still needs to maybe

  • Check all the siblings just in case your overflowing content and you need to paint something in other parts of whatever

  • And when you use containment, you have some kind of restrictions or implications of using it

  • so you cannot just put "contain" to all the elements and you are done you need to

  • To put it when it makes sense

  • so there are

  • Like this four type of containers we are going to review

  • First one for example layout containment. Basically here that means that the internal layout of the isolated subtree

  • Is totally isolated from the rest of the tree. So the element where you put "contain: layout"

  • The layout of that element is totally independent of the ancestor

  • so these are the effects it takes to element. Any overflow on that element is treated as ink overflow flow

  • like shadows for example, I'll show an example later

  • That element becomes a containing block for absolute and fixed position and descendants

  • it also creates a new stacking context and independent formating context like display flow-root and

  • Also that the element has no baseline. So why these

  • Restrictions when you use it. So let's see an example of this ink overflow thing. We have here two

  • divs that one has

  • "contain: none" the other "contain: layout", is the magenta dotted border the element that has the "contain: none" or "contain: layout"

  • So if the size of the text is changing here you see that an

  • scrollbar is appearing on the parent element. So the browser

  • Something changes inside and needs to do work outside like painting this scrollbar

  • But with "contain: layout" it doesn't need to do anything outside

  • this is

  • treated as ink overflow, like shadows

  • You cannot access it actually

  • But I mean the browser can avoid doing any work in the parents checking if there are overflow and it needs to paint

  • to show a scrollbar like here

  • Similar is for baseline. I say that when you use layout containment the element is considered to have no baseline

  • So basically is the same, here in the "contain: none"

  • you see that the "foo" is aligned with the "bar" in the other one if use the

  • synthesized baseline that is the underline in this case, if the size changes inside the browser needs to move foo a

  • little bit below

  • however with "contain: layout" something changes inside but the browser

  • Doesn't care. I mean it can save time and avoid that kind of operations

  • So another type of containment is paint containment, which is pretty similar to "overflow: hidden," but also has some

  • Effects so basically the descendants cannot be displayed outside of the boundaries of that element

  • But again it has some effects, contents are clipped like with "overflow: hidden", but also it becomes the containing block for

  • positioned descendants/children, it also creates a stacking content and independent formatting context. So let's see another example

  • So we have "contain: none" again in the dotted magenta

  • element and "contain: paint" and we have an absolute positioned at the element that has

  • -100 pixels top and left. It has 200 pixels by 200 pixels size

  • So it's positioned against the parent, it means the viewport or whatever

  • And in the other case is positioned against the container element is moved a little bit left

  • and top and also

  • the

  • overflowing things are clipped

  • So when you change the color

  • Here the browser needs to paint also things outside that element but here the browser needs to paint

  • things inside

  • so again

  • If you have an element with content paint that is not in the viewport the browser can avoid

  • doing work on it doing, doing any painting because

  • the browser is sure that there are not

  • something overflowing that that is painted in the viewport or whatever, they know that they can save that the time

  • Size containment is about how the browser computes the size of an element

  • Basically, if you put "contain: size" is going to ignore the children

  • so the element is treated as having no contents, only things like padding add space or

  • column-gap if you have multi column or the tracks in grid something like that

  • you already defined, but not the contents itself. And also it's monolithic

  • That means that you cannot split it when you print it or it's in multi column or things like that.

  • So again, this is the same example again. So the first element

  • The size depends on the contents is "Hello World!"

  • and

  • when the contents change the size changes

  • but in this case, only is the padding the one that is defining the size of that element, if the

  • contents change it doesn't care. You see that it's overflowing

  • The thing is that when you combine this with the other ones, the browser can say, okay

  • I know for sure that nothing is going to change outside, even the size isn't going to affect anything outside and all that

  • And then last one is style containment

  • This is somehow special because it only affects counters and quotes.

  • I don't know if you use them a lot. I guess no because it's not very common, but

  • at least is on the spec and

  • It's currently market as at risk, because the scope is maybe too narrow only counter and quotes

  • So there are some discussions about if it's worth. Firefox for example is not implementing this so far

  • So that's another reason why is at risk in the spec? Because they don't see the benefit

  • And also chroming implementation of style containment is pretty broken so only works for the very simple cases

  • so if any of you find a use case that

  • Can get performances benefit with style containment share with the CSS Working Group at the GitHub repository

  • Because that will be valuable information to know if we need to keep or not this value

  • so basically the effects are that the counters and quotes are scoped to the subtree and

  • That when you try to increment a counter you actually are creating a new one instead of incrementing it

  • So basically, just an example with counters

  • This is a class that is incrementing this counter "n" and this is just an element that paints the counter

  • So we are here creating this counter "n" and increment it to 1, then we print it is just 1

  • then we have a

  • "contain: style" element, so this counter inside cannot increment the one outside so it creates a new one

  • so we have here 1.1 and

  • When we print it after outside of the contained element, this doesn't know anything of what happened inside with the counter

  • So that's what's isolated, so still 1 again. So that will be the expected output

  • Then with quotes, quotes are I think even a

  • less common use case

  • So you can define

  • Which symbols are you using when you have

  • nested quotes. So this is double first and then single or whatever and then we are opening a quote here

  • We have "foo" then we have the style containment element and we open another quote

  • we have the text "bar" and then we close

  • the quote. When we close this, it doesn't know that a new one was opening inside the style containment element

  • So it just closes the initial opening

  • We are not closing both in this case, but they mean basically that the changes here doesn't affect anything outside

  • So, okay

  • We have aliases in the spec so you can say "contain: content" and that implies layout and paint

  • Or you can say "contain: strict" and that implies layout, paint and size

  • This used to include style too, but like style is market at risk and Firefox was planning to ship

  • CSS Containment, it was removed from the spec at this stage. If in the future style is implemented by all the browsers probably

  • There will be a new alias like "all" or whatever that will include style too

  • So let's just check the status of things

  • This is not a new spec. Maybe it's the first time you've heard about it

  • But if has been shipping for three years already in Chromium, so it's not an new spec at all

  • and Google has been using it in their products like YouTube or Gmail, even in the Chrome Dev Tools, things like that

  • But during past year there has been quite a lot of work in the in the spec

  • Florian Rivoal one of the spec editors has been working quite a lot

  • in pushing the spec to candidate recommendation

  • Also the test suite in Web Platform Tests repository has been completed byrard Talbot and with contributors from Mozilla and Chromium

  • while we were working in the implementations

  • We at Igalia having fixing the implementation in Chromium. So it's aligned with the spec and we can start to implement optimizations based on that

  • And that was causing us to be breaking most of the sites

  • I mean, we broke YouTube for a while

  • we broke Gmail, we broke Dev Tools several times because maybe they were using "contain: layout" for example in many places and now

  • the overflow is treated as ink overflow so you can access it, things like that, or now that is a containing block for

  • the positioned descendants, so everything is positioned wrongly, so you need to or stop using contain layout or

  • Change how things work inside that element

  • and

  • Then Firefox is also working on the implementation

  • They are targeting Firefox

  • 69 to ship it, but you can already test it behind the runtime flag

  • And meanwhile Chromium has been implementing some optimizations based on css-contain

  • So like I say you can just parse the property in the browser implement the restrictions and you are

  • passing all the tests of CSS Containment so you are totally spec on client

  • But maybe you don't have any optimization in the browser so is not useful at all at the end

  • So then when the browser has that information it needs to still implement some

  • optimizations

  • and

  • If we look at "Can I use" like Microsoft is moving to Chromium/Blink

  • it's getting support for this, all the Chromium browsers has support for this, and Firefox is about to ship in a few releases and

  • and then regarding Safari/WebKit there are no public signals yet

  • So let's show some examples to try to understand this a little bit better

  • This is one example from a blog post I published about

  • Containment is very simple and not cool at all. But I believe it's the best want to understand how how it works

  • so imagine that we have a very big DOM tree, like ten thousand elements like this item that has all of them have

  • one child and

  • We are modifying the content of that child over and over or whatever. So we have a DOM tree like this

  • We have many many elements here, but we are only doing changes in this green

  • div

  • But still the browser needs to do work in the rest, not a lot of work maybe just

  • Traversing the whole DOM tree to do some checks or whatever but it's doing work in all of them, so we can say okay

  • This has "contain: strict". We cannot affect anything outside. We are just changing things inside here, the browser can avoid

  • Navigating the rest of the things

  • So this example is, I mean not cool at all, is changing the the text in the first

  • element

  • it actually goes from changing is taking six milliseconds without containment to take

  • 0.2 milliseconds with "contain: strict". So it's like a

  • quite a bit difference

  • This is another example is the same one, but I'm using grid layout in the items because I know that

  • grid layout has all these track sizing algorithms. So it's