 Good morning, everyone, and welcome back from the break. It's true my name is Gray. And I don't think my parents could have known when they named me all those years ago that my hair would prematurely match my name, or that I would be a valid CSS color. So I give them a lot of credit. So I'm the engineering manager for the Polymer project at Chrome. And my team focuses mainly on web components and libraries and tools to help you use them. But we're involved in some other stuff too. And today I'm here to talk about something a little different. Or maybe we'll just stand here and look at my picture. So shockingly, we're going to be talking about performance. As you may have noticed, we're a wee bit obsessed with that topic. And by now, you've already heard about speed tooling and best practices for doing everything faster, from loading to rendering to responding to user input. But for the next half hour, we're going to drill in on something a little more specific. And that's a proven pattern for improving performance that we'd like to see more of on the web. Ben and Dion mentioned in yesterday's keynote that today's web platform is really a high performance machine. It's way faster in almost every way than it was even a few years ago. But there are still some surefire ways to slow it down. And one of those ways is just trying to render too much. Especially on low-end mobile devices, you can bring performance to a crawl by piling on too much DOM. And sadly, there are key parts of the rendering process, like styling and layout, that just take longer the more nodes you have in your page. So for a certain class of performance problems, the best thing you can do to speed things up is to lighten your load, minimize the number of DOM nodes you have on the page at any given time. And there are various ways to do this, of course. But one of the simplest and most effective is to adopt a pattern called virtual scrolling. So for the last several months, a couple of members of my team have teamed up with some of our Chrome colleagues and some other folks inside and outside of Google to explore what it might look like to add first-class virtual scrolling support to the web platform. Today, I'd like to share what we've come up with so far. It's early, but we're pretty excited about where the project is headed. We'll start with a quick introduction to what virtual scrolling is and how it's currently being used on and off the web. And then we'll take a closer look at the performance problems we're trying to address, seeing firsthand how too much DOM can impact the responsiveness of your pages. Next, we'll talk briefly about the approach we're taking, and we'll show you what we've come up with so far. And then finally, we'll look ahead to what's next and how you can get involved if you're interested. So without further ado, let's see what virtual scrolling is all about. For the sake of comparison, first, we'll look at ordinary scrolling. So the blue box here is our viewport. And as you can see, as we scroll, the document moves behind the viewport, revealing content further up or down. But notice that all the content was present from the start. The only thing that changes is what we see. Now here's the same page in a virtual scroller. As you'll see, only part of the content exists in the document. As we scroll, nodes are dynamically added and removed, keeping just enough to fill the viewport. And this is an obvious one at load time since we only need to render one screen full. But as we'll see, virtual scrolling actually also improves performance in other ways that might not be as obvious. So when does it make sense to use virtual scrolling? It's clearly a natural fit for any time you need to display a lot of data in a list or table form, for example, like this address book. And also it's an obvious call for content feeds, obviously in cases like social media or messaging. But feeds have started showing up in less traditional places too. So some publishers have started stitching together articles in a way that takes advantage of the low friction of scrolling. And this may not look like your garden variety infinite list, but nonetheless it's absolutely a case where virtual scrolling can help. And for that matter, we actually think there's a strong argument to be made for looking at virtual scrolling in cases beyond lists and feeds. A single piece of long form content like this Wikipedia article might easily contain tens of thousands of nodes. And the same techniques that we use for lists can also help us keep the weight of documents like this under control. So virtual scrolling isn't a new idea, of course. It's widely used on native mobile platforms. And in fact, both iOS and Android put virtualized views front and center in their SDKs, making this one of the first concepts you learn as a new developer on one of those platforms. And this is a big part of why native mobile apps tend to feel fast. A basic native view is actually heavier than the equivalent chunk of DOM, but the mainstream use of virtual scrolling on platforms like these helps keep performance in line. Now, you might be thinking virtual scrolling isn't new to the web either, and you'd be right. There are popular and effective virtual scrolling solutions for all of the top frameworks, including, among others, React Virtualized and its younger sibling React Window, the virtual scroll viewport in the Angular Material CDK, and the View Virtual Scroller Library. But these solutions are currently getting by without much help from the web platform. So in the age-old tradition of paving cow paths, we asked ourselves, what might it look like for the web to offer first-class virtual scrolling support? How could we make things better? And we came up with a few ideas. First, virtualization generally means you can't link to locations within the same document since the browser can't scroll to a node that's not currently on the DOM. Now, this may not be an issue for many use cases. You don't see a lot of links between address book entries, for example. But in other cases, it is a big deal, and it breaks a fundamental feature of the web. And there's a similar problem with the browser's find-in-page feature, which only sees text if it's present in the DOM. And then there's search friendliness. Since virtualized content is added on the fly, it's not generally visible to search engine crawlers. And again, this isn't relevant for every use case, but we'd love to get the performance benefits of virtual scrolling without sacrificing indexability. Finally, and maybe most importantly, we'd like to see if we can greatly increase the amount of virtualization that happens on the web by adding platform level support. While you can do it today, virtual scrolling on the web is basically a fringe feature. You have to discover you need it, and then you have to jump through some hoops to get it. We'd like to put it front and center the way it is in mobile SDKs, making it easier to discover and easier to use. Okay, so we've talked about what virtual scrolling is and why we're interested in adding it to the web platform. But to really understand the nature of the performance problems we're trying to solve, it'll help to look at some examples. Since problems are the worst on low-end devices, we'll use a typical Android Go phone for this exercise. So I actually recorded a bunch of real-world interactions for this talk, but I wasn't super happy with the quality of the recording, so I ended up creating dramatic re-enactments in DevTools with CPU throttling turned on. But what you'll see here is representative of the performance on the real device, and I'd be happy to show you on the device itself if you come find me after the talk. Okay, so first we'll look at how the size of the document impacts rendering and what that means for responding to user interactions and content updates. So I created a simple example to demonstrate. It's a bit contrived, but it exercises the browser engine in the same ways that real pages do. So this mocked-up content feed has just five items in it, and it performs pretty well. You'll see it has advanced features like a dark mode and a compact layout mode, and these are all made just using standard CSS techniques changing classes. And then lastly we have this slider here, which lets us increase or decrease the size of the items by changing the base font size in the document, which is a technique that many of you have probably used and the layouts of the items themselves are based on Ms, so that the whole thing scales. As you can see, this performed pretty well, but again, it's only five items. So let's see what happens if we bump up to 50 items in our feed. So I'm scrolling here to show there's more content, but don't focus on the scrolling performance. We'll talk about that in a minute. For now we wanna focus on the other interactions. You'll notice I added a jank indicator, so the screen flashes red when rendering gets slow. And we're not too bad here at 50 items still, although there are noticeable delays for the mode switches, and then you'll see there's some sluggishness as we start moving the slider. But where we really start feeling the pain is when we get up to 500 items or more. So the lagginess in this example is gonna be impossible to miss. So you'll notice that when we go to dark mode there's a compact mode, there's a very noticeable lag, and the slider is gonna be virtually unusable. It's so slow to update. And if anything, it actually feels worse on the real phone than this. So again, this example is a bit contrived. You may not do exactly this on your page, but the effects it illustrates are very real. Rerendering the content on your page, any content on your page, whether it's in response to user interactions or changing data, it gets much slower as your document gets bigger. And on devices like this, it can kill your page. So let's jump ahead of it and see how much virtual scrolling might help. So this is exactly the same page with our work in progress virtual scroller swapped in for the scrolling region. And we've bumped all the way up to 5,000 items, but of course only a small fraction are actually in the document at any given time. And as you can see, we're pretty much back to the same performance we had in our original five item list, and this is essentially how it feels on the phone as well. And remember, this is a very low-powered Android Go device. Next, let's see how virtualizing might help us at load time. So a quick caveat about this. Load time performance, how quickly we get something on screen, how quickly we make an interactive depends on a lot of factors, and virtual scrolling doesn't directly impact many of them. But to the extent that styling and layout are slowing things down at load time, virtual scrolling can definitely help. So being the big web nerds that we are, we'll use the single-page HTML spec doc as an example. So this thing is massive, somewhere on the order of a million words, I'm told, and it's notoriously slow to load. So on my Android Go device, with a good but not great network connection because I'd gone over my data allowance for the month, it took about seven seconds to get something on screen. So for comparison, we've built a virtual scrolling version of this page out of duct tape and bailing wire. Basically, it loads the original doc into a hidden iframe and then it populates the virtual scroller as the nodes stream into the iframe. And you wouldn't build a real thing this way, but it's an interesting test case and it illustrates the impact. So as this visualization shows, we got something on screen much faster, just over three seconds instead of seven, and it actually gets even better from there. The original version on this Android Go phone was suffering from scroll jank for well over a minute after I started loading it, whereas the virtual scrolling version is usable right away. As you scroll, there's occasionally a delay as it updates, but unlike on the original version, you're never sitting and waiting for seconds while the screen is locked up. Okay, so before we move on from performance, one quick word about scrolling performance because it seems a little weird not to talk about that and I talk about scrolling. So because scrolling is driven by the GPU, even on our low-end Android Go device, you actually get pretty decent scrolling. It scrolls at a reliably high frame rate and it actually looks really good at normal scrolling speeds. But when you scroll quickly, something funny happens. The screen blanks out, goes completely white for long periods of time while the rendering pipeline catches up, and this actually gets worse as the size of the document increases, just like the other performance problems we've been looking at. So I did salvage one of my original on-device recordings and we'll look at it here. Our virtual scroller, it turns out, significantly reduced the blanking problem. It happens much less frequently and when it does happen, the renderer catches up much more quickly. The trade-off is that scrolling is mildly but noticeably less smooth overall. As you would expect, you know, doing JavaScript layout on a CPU challenge device like this does impact the frame rate. But as you can see from the video, it's a very good experience nonetheless, even on this low-power device. Okay, so we know what virtual scrolling is. We know we want it to add it to the platform and we've seen firsthand why we need it. We see the performance issues we're trying to overcome. So I want to talk for a moment about the process that we're going through because it's actually not that common in recent years for the web to add new high-level features and so we had a bunch of things that we really want to do and treat this sort of as a guinea pig for how we might add higher-level features. We'll start with some basic principles. Anytime you're building something in the web platform itself as opposed to in user space, it's important to get the very basic use cases right because web APIs live forever and it's much more important that we do the simple stuff right. So with that in mind, we wanted to make sure that we learned from prior art. There's obviously virtual scrollers on other platforms and plenty of good work in the framework space. As I said, we want to make it simple. We want the feature to be easy to use. As much as possible, we want you to be able to create web content that you just happened to put in a virtual scroller as opposed to picking up a brand new API and thinking fundamentally differently about the way you build stuff. Make it work. It sounds trite and it is, but what I mean by this is everything needs to work. We talked about links. We talked about find and page. It's critical that accessibility works. We want tabbing from item to item to work. And of course, it needs to be fast. After all, this is a performance problem we're trying to solve. Okay, the next thing we want to do is we want to embrace layering. And we'll talk a little bit more about what we mean by that. Nicole actually mentioned this in the keynote. One of the important things we want to do out of this process is identify and implement any lower-level primitives that the browser may be missing in order to support this high-level use case. We also want to enable this thing to be used right out of the box, much like you use vanilla HTML and JavaScript. We don't want you to have to pick up a framework to do virtual scrolling. We'd like you to be able to use it on the web platform simply. But with that said, we also want to give frameworks and libraries a solid base to build on. And certainly the low-level primitives are things they can use, but ideally we'd like the virtual scroller itself to be something that they can take in whole or in part and layer features on top of for their own virtual scrolling solutions. And as I mentioned, this is all really with the idea of blazing a trail. We think that there's a lot of room to improve the developer experience and the user experience of the web platform by adding some high-level features in coming years. And with that in mind, we want to use virtual scroller as sort of a lens or a testing ground for us to examine what it means to add new high-level features. And so we'll talk about some of these things as we look at the virtual scroller. So with those principles in mind, we sat down to do our homework. And the first thing we did was we set up what we called at that time the infinite list study group. We basically had a bunch of people from across Chrome who would get together once every couple of weeks and each time someone would take the homework of looking at a particular virtual scrolling solution and reporting back and we would discuss it and we'd learn about what was working and what wasn't. And we documented all this here on GitHub. Once we'd done that for a while, we came up with a set of requirements and it was time to start building. Now I don't know what this is. I think it's molding or something, but it looks like something I'd really like to build. So I put it on the slide. And we have the same sort of love for virtual scroller. So once we started implementation, we did that on GitHub as well. And one of the things you'll notice here is that virtual scroller is being implemented in JavaScript. And this obviously is sort of unusual for something that's under consideration for a web platform API. It's not typically how we build platform APIs. But this gets to the layering concept. We wanted to make sure that we didn't reserve any special powers in adding these features and one of the best ways to do that is to develop things in the same environment that framework and app developers develop in. So the next important thing about the process is we wanted to be in constant dialogue. We talked about the fact that we're doing these things out in the open in GitHub, but we also have been talking to people all along. So we've been talking to other browser vendors about the ideas behind virtual scroller and the principles that we're trying to look at for adding new high level features. We've been talking to framework and library authors. So along the way, we've talked to members of the Angular team who are working on the Angular material scroller. We talked to the AMP team. We've talked to members of the Ionic team who are working on their own virtual scroller. And we've talked with Brian Vaughn, who's the author of React Virtualized and React Window as well. And we also have very active discussions going on in GitHub. So it's important to us that this process be carried out in the open and with the input of the community, including frameworks. Okay, without processes backdrop, let's go ahead and look at what we've built. So this is that example we were looking at before. And I show it here in DevTools, just so you can see as we scroll, there are just a few items in the DOM at any given time. And when we scroll, you'll see them cycle in and out. And so even though we have a list of 5,000 items here, at any given time, we're only laying out styling, rendering a very small number of them. And as you can see, the virtual scroller itself is a custom element. And let's see how you would actually use that in vanilla style. So starting from a blank slate here, the first thing that we're gonna do is we're going to use the browser's native module loader to import this. This is also a new concept that we're trying out as part of the way we're thinking about higher level APIs. Typically, browser APIs are sort of baked into every page. You may use them, you may not, but there's a memory impact and the size of the browser is impacted. We'd like to explore a pay-as-you-go model. And so we already have in the form of the module loader a way to dynamically load libraries and code at runtime. And so we're using that here. And you can see we have a proposed syntax for requesting something that would be part of a standard library provided by the browser. And I won't go into the details here, but you can read about it. So once we've imported it, we just put the virtual scroller tag in our HTML document. And this is what you get without doing anything more. You can see the virtual scroller has a default size, much like an image or an iframe. Not an image, but rather an iframe. And so it's not doing anything yet. Let's make it do something. So first, ordinary query selector to find the virtual scroller. We're just gonna fetch some data. And then here's the first bit of virtual scroller API. It's an item source. You can assign this an ordinary array as we've done here. And then we'll call our async function and we get that, which probably isn't exactly what we want either. So we wanted the virtual scroller to do something by default. And so what it does is it just takes the item and it tries to render it into the item. And in this case, it's string and it doesn't look very good. So let's fix that. So the next bit of API is this update element hook. So here we're basically just gonna take the contact name and put that in the text content. And there we have something that looks much more useful. So just a few lines of code, vanilla HTML and JavaScript, and we have a virtual scroller. So let's take a look at one more example. You notice the virtual scroller initially was empty. And by default, it will just create a div for each item. You can actually override that in addition to the update element, there's a create element hook and you can give it any kind of DOM you want. But you can also put a template inside the virtual scroller and whatever is there will be what's instantiated for each item. So I'm gonna go ahead and in my update element function, gonna assign the image. And then lastly, I'm gonna specify that I want a vertical grid layout. So the out of the box that supports vertical and horizontal, normal and grid layouts. Layouts are actually pluggable under the hood. It's TBD whether that gets exposed in the API as it eventually ships. Okay, so as I mentioned, we're taking a layered approach. We're not building fancy features like custom headers and things in, but it is important to us that these things work because again, we want layering. So here's a case where we have headers interspersed with list items. These are all examples that you'll find in our GitHub repo. So the other thing is it's important we wanna support various loading patterns. So this is a common one where it's sort of an infinite scroll and as you go, each item gets loaded and you just keep scrolling. We also support the other common pattern where you scroll to the bottom, you explicitly ask for more. So again, we're validating that our basic constructs are working for these use cases. Fancy your features. If you've ever built stuff like this, worked with the UX team inevitably, they're gonna want fancy stuff. So here's a proof of concept that shows that things like swipe to dismiss can work with this virtual scroller as well. Okay, so we mentioned that we thought there would be some missing primitives that we might discover and we think we found one. Specifically, it's called invisible DOM. So you remember our earlier examples. In this one, you'll see it's a lot like the virtual scroller except instead of actually getting rid of and adding nodes, it's basically just making nodes invisible. Invisible DOM is in the document much like a display none element, but it's different from display none in that it can be linked to and it can be found by the browser's find in page. And so here's an example where we have non-traditional virtual scroll type of content. This is a document much like you might find in Wikipedia or a long form news article. And you can see, here it is, we get a certain way down the list and all of a sudden there's nothing highlighting over in the window because some of these DOM nodes are invisible, they're just not there. And as we scroll, we'll see that they're basically being flipped to visible. And so when the virtual scroller is working with invisible DOM, this is how it works. So you'll see here, we'll do some resizing, changing orientation and you'll see that the layout is preserved. Again, this is just ordinary styling and layout on these items and virtual scroller works with them out of the box. This is what we were talking about when we said we wanted to make it simple. We don't want you to have to think hard about using a virtual scroller. So what we're looking at here, though, is the cool thing, it's links and this is what invisible DOM is making possible for us. So when I click on one of those links, the DOM nodes that it's linking to are not even in the document yet. But, well, they're in the document, but they're not rendered. And so you get an event on them and by default, the browser will actually flip it visible and scroll to it. But in the case of virtual scroller, we're capturing that event, we're scrolling to it, but in the process of doing that, we're rendering all the context around it. So it's perfectly seamless. So the end user who's using invisible DOM with a virtual scroller, it's exactly as if the entire document had been rendered the whole time. And I am just about out of time, but I wanted to show you one of the exciting things about using invisible DOM with virtual scroller is that it means you can actually put invisible content directly in a document. And we're talking with our friends over in search and the idea is that you'd be able to effectively have your content be entirely indexable, but to benefit from the performance wins of virtual scrolling by not having to render at all on first load. So very quickly talk about the path forward. Again, very early days, but very encouraging results. What's next? More invisible DOM integration. We've really just started exploring how the two play together because thanks to some great work from Rekina on our DOM team, we've just had working a version of it become available very recently. In fact, it's available behind a flag in Chrome Canary. We think there may be additional privatives as well. We've talked about some, I won't go into detail here, but invisible DOM is just the first. Framework collaborations. So from the start, we've actually, in the repo had proof of concept integrations with lithtml and with preact. And for this talk, but it ended up getting cut. I did a basic react integration as well, but it's very early there and we haven't worked closely with the frameworks on that specifically yet. More advanced use cases. So we saw some of those examples, but there are others that we have not gotten to yet. Performance optimization. It's pretty darned fast right now, but there actually hasn't been intensive optimization done on it yet. And then importantly, down the stack explorations. So one of the first questions we get when we talk about this is why doesn't the browser just do this stuff better in the first place? Why do you need a virtual scroller? Can't the browser just do this? And these are discussions that we're having not only externally, but also internally. And it's a long complicated story. Browser layout is complicated in much the way that AMP simplifies building pages. Virtual scroller can simplify layout by locking you into a much simpler model and there are some wins there. But that being said, it's very possible that we can also pursue other types of optimizations further down the stack that get you some of the same types of benefits without even having to go to a virtual scroller. And those are certainly things that we're discussing. The standards process. So again, I've been talking to other browser vendors all along, but it's very early for this on other similar high-level features. And the list could go on. So if you're interested, I invite you to engage with us on GitHub. We have a very active set of discussions going on in the issues here. And here is the GitHub repo where you'll find us. And with that, I've been excited to show you virtual scroller. I hope you're as excited as I am to see it come into the web platform.