 Are we good? Yeah? Is it whenever? Yeah. You're right. Oh, cool. Sorry, we've been talking over. Yeah, it's fine. Oh, OK. So this title is CSS about, not is CSS a bad idea. Oh, is .css a bad idea. But this will look good on YouTube, right? You are going to start some flame wars. You're going to, like, the framework people are going to feel so validated. Yeah, but this is not a talk against CSS. It is a talk questioning external CSS resources. All right. So immediately, we've just lost 50% of the people who tuned in for a real something bashing CSS. But no, I actually want to talk about CSS resources. All right. Well, so I'm going to put my flag down here as call me a heavy skeptic for this premise. All right. All right. Well, we can see where you are at the end. Yeah. HTML is a streaming format. This is something we've mentioned on the show before, but the browser can render the header. It can now render the main bit. All without having the end tags for the rest of the stuff. And then now it can render the whole page. How much do browsers do this nowadays? Because when I was using the internet first, when the internet would scream at you before you could use it. Yes. I remember those noises. Like a page would stream in. And as the HTML was loading, you'd see it load chunk by chunk. It would build up and load progressively. But nowadays, I often go to a website. And then it's just like blank page, blank page, blank page. Yes. Do you know who's fault that is? Who's? Engineers. Because we do this. We've got this external style sheet resource there. And we've got a blocking script tag. These prevent the page being rendered until these resources load. In fact, the script tag, in many ways, prevents parsing as well. But the CSS just blocks rendering. Yeah. Well, we're going to, I'd like to assume the developer here has been paying attention to your series for at least a bit of time and probably put an async defer on. Like this? Yeah, there you go. Exactly like that. And this is like people who care about web performance have been trying to make this point for a decade or two. That, yes, we should be writing scripts which don't block. Yeah. And yeah, defer is one way of doing async, as you say, is another. But that leaves the CSS. And there's nothing really we can do about it. Because CSS cannot stream. We need the whole thing. If you've got this at the start of your CSS, then at the end, you've got like, no, actually, it's a different background color. No developer wants or expects to see the dark background or the light background. And then it's switched to the dark background as it chews its way through the CSS file. This is just a color change. But if you were pausing incrementally through CSS, the page would be like jumping around all over the place. I can't help but feel that if that was a known scenario, developer would design their CSS file to put things in hierarchical order of importance. I agree. But things do seem to be changing a little bit in this space. This is a cascade layer. This is part of a cascade layer. It's got a new CSS feature that's landing in browsers right now. Extremely cool. It's extremely cool. But I thought an interesting element of it is that upfront, you're specifying something about the order of how to interpret the file. And I feel that that is, it'd be interesting if CSS was built now from scratch, I think it would have a lot more of this sort of stuff. Like things upfront that said, look, here's what's going to happen. And then maybe what things could stream in after that in some sort of way. Thinking about how people actually authored the CSS, this is a common way, one style sheet for your site. Yes. That's what I do on my blog. But there are bigger sites that do this as well. Doesn't scale. Oh, no. No. Carry on, carry on. Well, OK. What about this? I took this screenshot. I didn't even have to look far to find this. So this is the coverage panel in Chrome DevTools. Two megabytes of CSS. And almost entirely unused. So this is a, this is a, oh, no. And eight, sorry. And seven, almost seven megabytes of JavaScript. Yes. But the JavaScript on this page is bad, right? That's too much JavaScript, especially because so much of it is unused. It does jank the page with its parsing, with its execution. But it is loading asynchronously. The main performance problem on this page is the CSS. What the hell are they doing? I didn't have to go looking far for this. My favorite thing to do to go for examples of how people build websites that aren't, like the people who are most performance focused. I look at Formula One websites. I like it because they tend to go through a yearly refresh. So people will be building it usually, you know, fresh every year because of new branding. So this is a Formula One website. I won't name the team. But yeah, this is- I like the irony there. Oh yeah, like- Some of the worst performing sites I've ever seen. Yeah. But this is the problem you get when you have like one CSS file for your whole site. People just keep adding to it, other teams and stuff. And you end up with eventually two megabytes and people don't know what to safely remove and that sort of thing. Yep. This is the other model I've seen. And again, I saw this on a Formula One website. I actually do something very similar to this myself. Like just because the way I author CSS files, because I'm a developer advocate, all the demos I do, they're usually pretty performant and also coded very leanly. And so, and I'm, I don't want to run any pre-processors or have any build steps because it makes it difficult for people to like fork it or use it for other own projects. Except instead of being separate link tags, I have one CSS file with lots of import statements, which is basically exactly the exact same thing except with an additional network hop. Yes. So it's going to be slightly slower than doing it this way because it has to request the first thing to find out about the others. I'm going to say there's also a benefit here compared to the single model is that HTTP2 allows sites to download resources in parallel. So here's the difference I saw. Again, this is a real website. This is a Formin1 website. You had 32 CSS resources. Out. But 48K. Oh, that's not so bad. That's great. Like compared to the two megabyte one we saw before. That's fantastic. Even if they're downloaded in multiplex. We can say parallel. That's parallel. Yeah, that's what we mean. Yeah, then I think that, okay. So to second to first render three seconds, not terrible, This is over 3G, I will say. Yeah. What's the JavaScript like here? Like also pretty good or? So I removed JavaScript from the equation for this. Okay, cool. So this is just pretty much just the HTML and CSS. Yes. I think that's pretty acceptable. Over 3G. Yeah. That's really good. Cool. And what you get with these multiple CSS files is you do get to target them more for the page because you just include the ones you need. And that's why you end up with 48K rather. Anything else. Yeah. But here is, and this is the same resources, just concatenated into one. All right. Now, one interesting thing there is the file size has gone down. Yeah, I can do that. And that's, broadly, or the GZIP will be the same. Yeah. Because it can't zip across file boundaries. So when they're all joined into one, back references work more. Yeah. And you get a smaller file like that. One thing I left off this graph. All right. Is that. So I ran each of these nine times. Wait. What? And there was this massive variance for a few of the results. And I repeated this test many times. And I saw this variance crop up time and time again. So here's the web page test graph of it. And this is where you can start to see what we were referring to before, is the multiplexing, the single connection being used. Yeah, they're coming down altogether. Exactly. So the blue bit at the start there is the HTML. The green is the CSS. And the purple is images. Now, what happened in these outlier cases, this is one of the outlier cases. The images came in first. They stole the bandwidth and pushed the CSS back. They ended up, I guess, either equal priority for the browser or the server was just like, I'm sending this data. And before the browser could come in and say, look, these priorities need to be the other way. Were these images in the first style sheet, it's like got and parsing? Or is it images in the HTML? They were image tags in the HTML, which is why they were discovered so early. Yeah, images in your CSS won't download until a calculation in layout has been applied. I'm not sure if you're on experiment, but if you were able to, stick like a preload onto the CSS, do you think that would have solved the, I mean, we're talking about like 200 milliseconds here. So not like nothing killer. Exactly. Yeah, I should say is that ignoring the outliers, the difference we're talking here is half a second. Oh, it's one second. Half a second, I'd say. Oh, yeah. So it's not huge, but if you play performance, it's going to be the fastest it can possibly be. Or that's certainly what I'm trying to chase here. Now, when I talk about this, what a lot of people say is like, doesn't matter, cache it, and then you're fine. Yeah. The fastest HTTP connection is one that isn't made. Yeah. I remember someone saying, and yeah, so these resources can be far future cached. The way this works, user visits a page, the rendering is blocked on fetching, a style sheet, whatever. I noticed you include the hash in there because I'm assuming that on the next reload, sorry, I'm jumping ahead. I'm not going to... I think you know what's coming. But yeah, time passes, user visits another page, and then it's fetched from the local cache and everything's great and fast. But how often is that hash going to be the same because either developers push changes or it's a different page with ever so which needs a different set of CSS and is a different file? Yeah. Two things can go wrong here. One is that the resource is evicted from the user's cache and if they've been clicking around the internet or even they've, you know, a lot of users religiously go and clear out their cache for whatever reason, this system isn't going to work. But yes, as soon as you deploy, as soon as you make a one change to the CSS, you're no longer, your caching is not doing its job. This is the system that I'm proposing is that we just dump all the styles in the page. I guess the benefit of doing this, the downside is you lose the caching, but I'm not sure if that's an actual benefit. But here you get to hyper-target your styles for this page because you don't have to figure out which thing goes in which CSS file, which da da da da da, because it's just going in the page. Okay, I was hoping you would bring this up because I'm assuming you have some magic tool that then looks at your rendered HTML for all possible situations that you could land in, like all media types, page widths, and user preferences, and then looks at your giant two megabyte style sheet and picks out just the rules that are being applied and dumps them into... So this is what you're talking about. And now I have to remember what this stands for. That's quite the acronym. What you serve doesn't necessarily have to be what you author, remember that. And I think this is one of the great things we have on the web now is that there was a while when frameworks first became big where I felt like the developer experience took a leap forward, but it was at the expense of the user experience. I feel build tools have got so much better that we're starting to... If you were a happy being in a build tools world, and I agree with what you said before, if you're making this for educational purposes, maybe not the best thing to do, but you get to write in a way that is great for you as a developer, but you get to serve it in a way that is great for the user. And so, yeah, how you offer it, whether it's a big style sheet or not, the way I tend to do it is I have lots of little style sheets. I'm just going to make a whole bunch of the commenters super salty here. Okay. I have not seen the correlation between good developer experience leads to a good user experience. Like a lot of the developers I've seen, we've given them, you can write code really quickly, and they're like, yes, fantastic. I'm now going to ship, well, as we saw before, 6.8 megabytes of JavaScript and two megabytes CSS files to the user. No, that happens. I would say that I have been able to create a better developer experience and a better user experience using build tools. But I can't help but feel that, like, we have a bit of an audience mismatch here because this example here, like 48 kilobytes of CSS resources, you're managing to pull it down to 37 kilobytes and it's in line just to the file. So the saving here is negligible, whereas if you're on the page where you have the two megabytes of CSS and the 6.8 megabytes of JavaScript, like, I don't think they're even thinking about performance. This is definitely the sharp end of performance, absolutely. So with an inline situation, this is where we're at. Yeah, that's really nice. So it's the same CSS resource just inlined and so it's brought it down again by half a second, a bit more, maybe. But I was actually able to take that chunk of CSS and look at what was actually used on the page and bring it down to 6K. And I think that's actually the real value here. This is just showing you the cost of those HTTP requests. But the real value of inlining is that you don't have to architect what goes in what CSS file to try and figure out how that will spread across your pages in an optimal way. You can just sort of what is needed by that page and it's like 6K. What about a middle ground? So let's say we're going to forget about frameworks for now. So let's say a website was authored using web components. Yes. Each JavaScript file has HTML and CSS and are embedded in the JavaScript files as is common with the pattern for... Like this? Oh yeah, exactly like this. So I would say if you've got a JavaScript dependency, then the CSS should just be with the JavaScript. I've seen plugins... With the JavaScript, not in the JavaScript. I think in the JavaScript. I would say like why would you create... You've got this thing where the CSS is useless without the JavaScript. The JavaScript is useless without the CSS. Why would you serve those as two resources? They're interdependent. Okay, as a string in the JavaScript or as a JavaScript object where you like... Again, so the way I author this stuff is I have my CSS in the CSS file and I bundle it at compile time. If you want to write it in CSS and JS stuff, it's not... I'm not a fan. But if it has zero impact for the user, I guess I don't care. But I do prefer offering in CSS files. This is actually what we did with Squoosh. Squoosh, all of the CSS is inlined. Actually, all the JavaScript is inlined as well. So I ran a test of... This is on 4G connection. So this is the difference with just the bit of styles that Squoosh has inline versus not inlined. So it's 300 milliseconds on 4G. So it's not a lot, but it's not nothing. And it felt like it didn't seem to... I'll take 300 milliseconds for free for what felt like free. We had a build system anyway. But yeah, I would say the stuff that was inlined is just the CSS needed for the first render. So that is the stuff that doesn't need JavaScript. Yep, that makes sense. Whenever I have components that need JavaScript, I usually have them default as being invisible so that when in the situations where my JavaScript fails to load, no one notices the missing elements. Yeah, there may be some blank patchy spots on the page, but... So that's what we're seeing there on Squoosh, that first screenshot there on the top left. It's missing that button because that button needs JavaScript. And I think it's even just in the markup already. It's just hidden. Exactly, and it's a really good pattern for ensuring that your page still makes sense even when there's not as much interactivity. Your links still work, your HTML still works, but your fancy JavaScript functionality is just silently swept under the rug as it's failed to load. It's actually one of my big gripes with stuff like Vite or Vite and Next.js. It does seem to encourage you to have your HTML render be the same as your JavaScript render, which would therefore include buttons that don't work. And I feel that is something that we need to get better at as a community. I will say that this stuff I'm talking about is not like me coming up with anything new. A lot of sites are using this pattern today. So I took a look at... I just took a handful of sites, a couple of tech sites, CSS Tricks, Smashing Mag. Both of them, they have no CSS resource, external resource, it's all inlined. The Guardian, the BBC are the same as well. So this is like... I know those teams, they care about performance. And so they are absolutely using this pattern. One thing when I've talked about this with people in the past is they ask about... I've seen lots of your tweets about HTTP2 push and I know you've hit lots of blockers with it. It was supposed to be the chosen one. It was supposed to solve this problem. You're not wrong there. The idea that you go to a page and the connection would just be like, here's some stuff you need. You don't need to inline. This is the equivalent of inlining, but better. And it was full of browser bugs particularly. And I think Chrome did okay. The browser said a lot of bugs with it. But also it was really difficult for developers to understand what... Because the caching was at a connection level. And that's really difficult to think about versus the preload, linker all preload, which is cached at a page level, which is much easier to understand. It makes so much more sense. So yeah, HTTP2 push hasn't solved this problem. But I wonder if web bundles could solve this problem. The reasons I like web bundles are weird and esoteric, but I'm sure they'll tell me about this. Yeah, so people don't know web bundles is a spec. And the idea is it's just a collection of requests and responses. The way I would like to use it is as a navigation entry point. So you navigate to a page and the server sends you a bundle. And that bundle will contain one particular resource, which is the entry, the response for this navigation. So you'll be your HTML. But as the author of the bundle, you can decide what comes before and after that. So you could say... There'll be the front of the bundle that says, oh, this contains these five CSS files and these two JavaScript files and the HTML file. But as the bundle author, you could go, well, those CSS files are all going to go at the start because they are render blocking. And then we'll have the HTML. And then we'll have the JavaScript. And so the browser doesn't need to send out another request. It's just all going to be pushed down in this bundle. And it's kind of just H2 push. But it would be at a page level and you wouldn't need to be interacting with H2 directly. You would just be able to use it in a system like this. And that's what I want us to have. We don't have that in the browser yet. But I think that could kind of be like the nice middle ground. If you wanted to do the caching thing, then you could be like, hey, I've never seen this user before. Send them a bundle. But you're like, hey, I've seen this user before. They probably have some stuff. Don't know what they have. So we're just going to give them the HTML and if they need anything extra, they can request it. Yeah. And you could use cookies for that. Maybe one day we'll get a feature that's like... I know with H2 push, they talked about like bloom filters or something to send down what was already cached. Whether we can get something like that in future, I don't know. But yeah, you could do it with just a cookie or something like that. I do wonder with... I love the idea of being able to get an idea of what's cached and just send what's needed. But to me, that seems like the biggest fingerprinting. I don't think so. Because caching is a fingerprint anyway. And if you use... The tools you would use to clear your cache would also clear this bit of data. If you know what's cached... Okay, but caching is... Okay, I'm not sure this is in Chrome, but I know in some browsers nowadays, caching is limited to a per origin. So this bundle would be per origin, right? You would not be able to put files from another origin in your bundle. Absolutely. So I think in web bundles, you literally can. But they're called signed exchanges. But I think for this system, especially if it was going to reveal what was cached, you're right. That has to be same origin for all the privacy reasons. Okay, that makes sense. So that's really all I had. And at the start, you said you were a skeptic of this. So I guess my last question is... Can we still be friends? We can always be friends. Oh, thank you. But yeah, I think it seems like an interesting pattern. I'm not probably going to be jumping to put this in the things I build. And people will look at my blog and point out that it's not using this pattern right now. Yeah, I think, like, my biggest suggestion is author, if you can, author sensible code, check the stuff you're building, don't ship this. And I mean, this being the 6.8 megabytes of JavaScript, 2.8 megabytes of CSS. Like, work together the point where many of your viewers already are of shipping good stuff. Like, for us, for me, these are the white whales of the web, the ones where we need to hunt them down and destroy them. And because this is monstrous. I think an end point that we can agree on is that if this site did things like the other F1 website where they split their CSS up into lots and lots of files and served them as lots and lots of files, but just the ones they knew were definitely needed for this page, it would be an order of magnitude better than this. And the step for inlining and stuff would be a much smaller leap forward than this. So I guess that's the moral of the story is yeah, don't do this. Don't do the one CSS for your whole site thing. Split it up. And I guess if you want to go a step further, look at the inlining thing. Yeah, that sounds like a fantastic takeaway. I feel like I stopped going to the cinema at some point and then I didn't fly so much. Or I started watching TV series on flights, so I've missed loads of movies. I've not seen any Matrix one yet either. I'd say it's better than the Seat Hall's not as good as the first one. That puts it in a fairly big area. Thank you.