字幕列表 影片播放 列印英文字幕 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 by Gérard 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 somehow costly if we think about performance, so it takes a while and On the left we have Chromium on the right we have Firefox that's because I was crafting this example for this talk and I realize it we were not getting very good results in Chromium So I was checking Firefox and Firefox was much better and it makes actually sense the results We are getting in Firefox For example with these 10,000 items in Chromium is like 12 times faster with "contain: strict" which is quite a lot but in Firefox is like 2,700 times faster, but that makes sense because if you need to visit 10,000 grid containers and do layout on will on each of them and all that, or whatever you need to do Instead of just doing it in one. It's suspected that it's very very fast when you just have this strict containment in that element, that you just do it there So We have been working on this at Igalia as part of our ongoing collaboration with Bloomberg in which we implemented CSS Grid Layout in the past years or we have been implementing things in JavaScript like async/await or BigInt lately and Bloomberg has some quite complex UIs and then we're getting benefit of using CSS Containment in some of them So this is one of the stress cases we had this is like a huge table like layout or grid like layout. It doesn't have to be a table or grid It doesn't matter but it has like 10,000 cells or whatever and the text is changing constantly but we actually know that we are just changing one number by another number that the number is going to fit in the size we are providing, we know that for sure So we don't need We can say to the browser. Okay, this element has "contain: layout size" and you can avoid doing the layout of the text you are changing there ,because if you are adding a long sentence or whatever the browser needs to do line breaking, all that and Calculate some things, so we are saying okay You can save all that time if we have "contain: layout size" because we know that we are just changing one number way another and it's going to fit inside and Then this stress test with 10,000 elements. We were like four times faster using containment. So it's a nice optimization This is the still to ported to LayoutNG, which is new thing that Chromium is shipping really soon. So It will be like similar things This was another one pretty similar again very big table or whatever. Here are some of the Progress bars are moving are changing size. We're not changing the contents like that. But something is changing size inside each of them But the thing is that in the use case each of these cells were absolute positioned. So we have like Each of them has its own layer So the browser when something was changing inside one. It was traversing the whole layer three and depending on the size of the DOM, that was taking a while in some phases and then we "contain: strict" and a very big stress we get like 10% faster. It's not a lot but it is, I mean, everything helps Probably we were respecting more, but maybe there are room for more things yet So let's talk about the future of all these We can expect better browser support Firefox is shipping really soon. We don't know Safari but We hope that, I mean, we never heard complaints from Apple about this spec. So it seems Maybe at some point they will have it Other thing that we can expect is more optimizations based on css-contain Basically when people are start to use it, they will say okay like this example, I just did in Chromium Ok, this will be much faster than what we are seeing. I mean I'm changing just one element It should be almost as fast as having just one element in the DOM despite I have a ton of 10,000 elements or whatever So you can report a bug and probably the browser will try to improve that use case with some optimization because maybe, I mean this is somehow it's not new because it has been there for a while but There has not being a lot of work So there are still a lot of room for improvement here in a lot of optimizations to be done in the browser And also there are some new features or proposals that some browsers are working on, that are based on this spec So, I don't know if you have heard about Display Locking proposal from Google. Google is experimenting with this and have some experimental implementation already in Chromium Main idea of display locking is that in a DOM tree you can lock an element of the DOM Then you do manipulation in JavaScript you modify Whatever you need there without blocking the main thread and then when everything is ready you unlock it and show it in the screen But for that you need that the element is independent of the rest and that's where containment comes to the rescue. And I mean you mark that element with "contain" and then you can do that so things like this in the future will appear maybe display locking is not the the feature that is finally standardized But it's one of these ideas And that's all from my side. I hope you understand a little bit better Now what this spec is about you can start experimenting with it and report bugs about it in my blog you can read I just only have one article about this but maybe in the future I will have more, I've been writing articles about grid and things we are working on for a while And I will be around the whole day. Feel free to talk to me about CSS Containment, CSS Grid, what it takes to implement a CSS spec in a browser or things like that or even ask me about Igalia and the things we do So, that's all. Thank you
B1 中級 提高網站性能與CSS Containment由Manuel Rego | CSSconf EU 2019年 (Improving Website Performance with CSS Containment by Manuel Rego | CSSconf EU 2019) 3 0 林宜悉 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字