(00:03) Tim: Hey, Scott.
(00:04) Scott: Hey Tim, how are you?
(00:06) Tim: Not too bad. How you doing buddy?
(00:08) Scott: Doing well. Good. Thanks for having me on again.
(00:11) Tim: What's That?
(00:12) Scott: I'm excited to be invited back.
(00:15) Tim: Yeah, no, it's actually, it's like the hotel California, like once you're on, you can't leave, man. You're stuck now.
(00:22) Scott: All right. No complaints.
(00:24) Tim: Yeah, like I said, we didn't, read the small print before, the fine print before the last time. So you’re here for good I'm here. No, it's good. It's fun. It's always, I think it's nicer for me. Like, have someone to talk to, it's definitely nicer for the folks watching to not have to just listen to me talk all the time. Like that's also,
(00:43) Scott: Yeah I can relate to that. Just having seen the, the early episodes.
(00:48) Tim: Thank you. Thank you, buddy. Hold on. Where's the, there's a boot button here oh the remove button. That's what it is. Yeah, good. No, so, I mean like, yeah, so I think we were chatting a little bit about like what we wanted to do and stuff I like that. And, core web vitals are timely and, one of the ones that we were kind of talking about was LCP and stuff like that. So I thought maybe it makes sense to kind of go into that a little bit, but, before we did that, I just, there was one, there was one thing I wanted to do. Hold on one second here. Sound effects are still free.
(01:34) Scott: You have a soundboard over There?
(01:35) Tim: No, no, that's just, yeah, we don't even need one and that's all, it's all here. Did you, people happen to see, Look at this, look at this. This is yeah webpage test on a, on a small screen and it's actually, it works. And in fact, we can go to like a test result, Scott,
(02:11) Scott: This is, yeah. It's, it's incremental. Right. So we're aiming for usability. But yeah, in general, you'll find that, overall the site doesn't, break out horizontally when you have a smaller window size, in some parts like the view you're looking at now have a little more, refinement added. This is the, the film strip, view with, it's a comparison view too, if you want to look at more than one film strip, but see, we added a little sinking, between the film strips and the waterfall below them. So you can kind of, this was always there in fairness, it was just, some tightening that we did. So, before there were some UI elements and form controls that came between the film strip and the waterfall that kind of made it harder to, to line them up quite as tightly. So
(03:09) Tim: Yeah, you broke those out, which I thought was super nice having the nice alignment there.
(03:14) Scott: Yeah. And it kind of shows a little more on the wider screen actually. So it's not just, mobile improvements, but, yeah, especially here, when you're, when you're looking at the film strips, you get, a nicer view at what's happening at each, little, key frame in the film strip.
(03:30) Tim: Yeah. It's nice, it's some really nice, like the film strip is right. Like that is the one that's the view. They probably got the most love. And like you said, it's incremental, but it's kind of its. I mean, I'm super excited. I've been threatening, to help Pat put together like a responsive version of this for probably a decade now, like when was responsive design, like when did that first become a thing? We started paying it. It's like a, over a decade now, right?
(03:58) Scott: It is it's of
(04:02) Tim: I even looked there was, Stewart language, actually submitted a PR that was supposed to make some incremental steps, like back in again, like a decade ago. So it's like the idea of having webpage tests, much more usable on those small screens is awesome.
(04:21) Scott: Yeah. Because people use the internet.
(04:23) Tim: For my, ability to put the phone down, but
(04:25) Scott: Right. Yeah. Because people use the internet on their phones now, so we're catching,
(04:31) Tim: It's a thing, apparently it's going to stick. And that's what I keep hearing. Yep. Yeah, no. So I wanted to call, so that was, Scott, did most like, yeah, Scott really just pounded that out just for those kind of watching and stuff like that. So thanks for that, man.
(04:45) Scott: Yeah. Glad to see that go up. again, kind of a first step of many, but, we wanted to get, get a good, baseline of usability in there first, before we can, start to really refine things further. So yeah. I like it really
(04:59) Tim: Good stuff, man. Yeah. Thanks also. I heard kittens.
(05:04) Scott: Yeah. They're so
(05:07) Tim: Are they around, I mean, because look, I've actually saw, Eric is in the chat actually bringing up the kittens. So I think we're going to get in trouble if we don't have kittens on this one, Scott,
(05:15) Scott: There are kittens.
(05:16) Tim: Okay. Hold on.
(05:18) Scott: In fact, we, we could, this could just be a kitten podcast now.
(05:23) Tim: Could be, there you go. Oh man. Yeah.
(05:27) Scott: We're really open to names on these two. I've heard copy and paste kind of into that. Um,
(05:34) Tim: You haven't named them yet?
(05:35) Scott: No, it's only been a couple days that they've been in the house. Totally tearing the place apart.
(05:41) Tim: That's awesome. Yeah. I mean, maybe not the tearing the place apart part, but yeah, the rest of its awesome.
(05:47) Scott: Yeah. Yeah. Well,
(05:50) Tim: Yeah, no, I, I've enjoyed having them sort of crash a few video calls here and there too, which is kind of nice.
(05:56) Scott: Yeah. They're, they're super sweet. And it's a New York City apartment with, four people in it already. So yeah, not the best idea to add even more creatures, but we're, getting by,
(06:11) Tim: Oh yeah. The plants come down yet.
(06:14) Scott: They haven't figured out how to, climb up on, on the shelves. Okay. Yeah. Okay. But
(06:20) Tim: It's coming
(06:20) Scott: Maybe. Yeah. Maybe by the end of this episode, they grow fast.
(06:25) Tim: Cool. Yeah. We're watching the background here the entire time. Oh, that's a good suggestion. Async and defer.
(06:31) Scott: Oh yeah. I need to pull up the stream here
(06:34) Tim: For the, for the cats. There that'd be good names. I like it. I think that, that we can do that too. Like maybe like by the end of the show, we'll have some good names for 'em too. I think async and defer is a pretty tough one to top.
(06:46) Scott: That's pretty good. Yeah. A lot of these pairings are just, they're kind of, they're kind of weird in, just like the singular form, like to say like copy come here something like that, but we can work with it.
(06:57) Tim: Huh. Figure it out. So yeah, so performance, I guess. Huh? Um,
(07:03) Scott: I don't know.
(07:05) Tim: Yeah. Its debatable kittens are better anyway. So yeah, the LCP stuff. So I think where this came from for me was Henri Helvetica did, at online meetup for the, all around images. had some great speakers, the talks are online, can probably find the link and drop it in. and as part of that, I did like just a really short talk, about, it needed to be image related and LCP was, top of mind so did that. And one of the things that jumped when I was digging through HTP archive for stats was that it was like 80. So webpage test records, the, for LCP event, the largest contentful paint event, right. That can be text. It can be an image. It can be a background image.
(07:51) Scott: Good to highlight that it can be text it often isn’t. Good to highlight that, that it can be text. Sometimes
(07:58) Tim: It, can
(07:58) Scott: Not very often you see that.
(07:59) Tim: Yeah. It's not often as it turns out. So like webpage tests when we collect the LCP image or image. Yeah. When we collect the LCP information, one of the things we record and expose in the JSON itself is the type of the LCP event. So like, was it an image? Was it a background image or was it text? And HTP archive, which if folks aren't familiar, catalogs millions of URLs across the internet, to see how they perform, how they're being built up, that kind of thing, like what goes into 'em. HTP archive uses webpage test under the hood, which means that the stuff were exposing a webpage test. We can, query and stuff like that. So I was digging around there and it turns out its like 82% on desktop and like 73 or 74% on, mobile of the LCP events are triggered by either an image or a background image. So it's very tightly connected is image performance and the LCP events as it turns out.
(09:08) Scott: Yeah. Yeah. And images are tricky. Like, you know,
(09:11) Tim: They can be,
(09:13) Scott: They can be a big part of the page to, deliver really quickly and for sure a subsequent load. Right. So, yeah. Yeah.
(09:20) Tim: So they can be heavy and it's also like the way you load. And so I thought, like we were kind of bouncing a few things around before, just kind of showing off some of the common things that we run into on those. Yeah. Yeah. Well, you had a good story about the text though. Did the text, did you ever try-
(09:39) Scott: Not really. So I was thinking back that, when we redesigned the filament group website, when I worked there, we, we, there it is. Yeah, Tim pulled it up. So you can see that the, region in the center of the page there as a, a build animation, and it runs pretty quickly here. That’s no mistake. We actually found when we put the site online, originally our, LCP went really long, like it was in the red zone and, that was a surprise to me. So I looked into it, first of all I wasn't even aware at the time that LCP could be for text, not just images. So that was like a learning moment. But that also that animations can affect it. So, at least at the time, and I think, I think the algorithm or the metrics been, adjusted a little bit since be, because I wasn't able to reproduce it quite as well.
But it is something to keep in mind that, we originally had this animation on a, a bit of a delay. So the page came in, with nothing in that region and then kind of slowly built each line of text in over the course of like say five seconds. And in the first pass, our LCP was reporting five seconds, which is really long. Unless you're doing something intentional like this, in which case yeah. It was sort of like we didn't want to get rid of that thing that was causing our scores of, and frankly scores are, that's something we all care about now. So we wanted to fix that. But anyway, delaying, the animation was causing that at the time anyway. So we got rid of the delay and made sure there was some text showing initially and that made LCP happy, which of course is, it's not necessarily what the user cares about directly. But we wanted that, that good score for the launch.
(11:44) Scott: Yeah. I think that is a, so first off to your point, like a lot of things have changed. I know there's like a, there is a change log for core web vitals somewhere. See if Google-fu comes up like right away and that's going to be a big negative yes. So there is a, a where they keep track of change logs, like things related. And I know there have been a lot of work around, opacity zero stuff and trying to account for, different bugs and stuff. And then I know early on there was a thing around like if a image was in the Dom and then got pulled out and then got put back in like, through hydration. So it is for anybody who's like looking into web vitals, which is pretty much everybody nowadays. keeping tabs on the, change log is probably well worth your time, just because, it explains a lot of, especially if you're seeing like your monitoring and you see a big change in your metrics or in the situation filament, like it is entirely possible that one of those things ended up, changing the way LCP was recorded. And that's why it's picking up as the image now instead.
(13:07) Scott: Right. Right. Yeah. So, I mean, again it's most important to, keep these, metrics in mind with how it impacts actual users. Maybe you do want a long build, not too long, but a little drama. and you decide to leave it in, even if it was, getting flagged in a particular metric, but at least you have those measurements to know and you can be informed,
(13:32) Tim: and that balance is important too. Because it's like, yeah, the metrics matter from the Google perspective. But one thing we don't want to lose sight of is right, is that like the whole reason we're doing this is because we think it's better for the user. And as a result, better for the business and everything else, but so that's where yeah. A little bit of judgment comes into play.
(13:52) Scott: Yeah. So that was when I recalled. But since then it seems that on a mobile, run in webpagetest or in lighthouse, one of those images below is now the, the LCP and it could have been that we adjusted the margins since then
(14:08) Tim: Something. Yeah, I, I did check and it does look like the LCP now gets triggered by even on desktop, by that first in image there, that kind of loads up. So underneath
(14:19) Scott: Yeah. Yeah. Interesting. Yeah. Anyway, these metrics are evolving. So, that was a few years ago at least. But yeah, it was interesting.
(14:32) Tim: Yeah, definitely. I dig it. You don't hear as much about the text because it is like the 15 to 18%. So it's nice when there's, so yeah. So on the images side, going back to some of those common issues we found again, like kind of just digging through HTP archive as one does, a few different examples of some of the common problems that I see impacting that I think would be worth us digging into.
(14:58) Scott: Okay. This example looks like a good one. It's got a big hero image.
(15:04) Tim: Yeah. Yeah. So this is the Utah department of human services page, big hero image as you pointed out. The LCP, our test run is showing it a little bit slower than it does at the 75th percentile from Chrome's perspective, but it's not like Chrome is still flagging it as a needs improvement. So even though you could argue then in this case that we probably could have relaxed the test a little bit in terms of maybe the network or something, it's still not like its still highlighting something that exists as a problem for this page right now. Yeah,
(15:38) Scott: Yeah,
(15:40) Tim: Yeah. And so this hero image, so if you click through on the largest Contentful paint, and get some information, we see it's a background image.
(15:49) Scott: Yeah. That's interesting.
(15:54) Tim: Yeah. So they've got a div here. This is a little bit of the outer we collect like the first, I don't know how many characters I don't remember anymore. Like 60, 90 looks like more than 60 of the outer HTML. And so yeah, it's a div, it's got the inline background image on top of it. And then if we look at the waterfall as a result, it's pretty delayed like its request number 30.
(16:18) Scott: Yeah.
(16:21) Tim: And yeah, it comes after quite a bit of stuff in front of it.
(16:23) Scott: Yeah. And that's, that's not uncommon, especially if a background image is defined, say in an external CSS file. So you get that kind of cascade of requests before you can get to it. But in this case you showed it in the markup, right? Is
(16:41) Tim: Yeah, it was in the markup, although it's still going to be like, it's sitting right there inside the HTML, but it's still going to be delayed because the browsers still not going to go out in it still has to parse that CSS. Right. It still has to go through that stage before it figures out. Okay. I'm going to go ahead and make the request for the image itself.
(17:00) Scott: Yeah. And it's going to prioritize it lower. Right,
(17:03) Tim: Right. Yes. Yeah. So if you see the initial priority too, when it's first discovered as low, if it's requested as a high, eventually it's an image, it kicks it up, but yeah. Oh this is HTP one. Didn't even catch that this is on HTP 1 before.
(17:17) Scott: Yep. So
(17:18) Tim: Don't see that as often.
(17:20) Scott: So a few things could potentially be yeah.
(17:23) Tim: And the other thing here is like the size itself looked a little.
(17:27) Scott: Yeah.
(17:28) Tim: Potentially.
(17:29) Scott: Yeah. Especially on that, that mobile view.
(17:33) Tim: So this is the actual size of the image as it's presented down here. So yeah, it's definitely a bit larger. So there's a few things like one would be, resizing this to be a little bit more, accurate or I guess in line with the view port.
(17:53) Scott: Yeah. So are you thinking like, since it's a background image, I guess you've got some responsive image options, not quite as good as, as you have, if it's a foreground image. Sure. But you could use break points.
(18:08) Tim: Yes, like break points in the CSS would absolutely pull that out.
(18:12) Scott: The media queries, in other words,
(18:14) Tim: Yes. Media queries, old friend.
(18:19) Scott: But at that point you're already thinking maybe, having the, background image right on the, style attribute right there is, is limiting. Right. Because media queries can't go into a style attribute. So we, we already run into an issue there.
(18:34) Tim: Yeah. So the media queries, what we could do with media queries is serve the right image. Right. Like, so we could do, like some image sizing, serve up the appropriate image based on the view port. Yeah. There’s probably some compression that we can do here. Like if we just grabbed this and then went to Squoosh that app. Yeah. We've mentioned squish before on one of these things, but for those, like, this is a super slick little app online. And just drop the image in. I'm just curious. Yeah. So like right off the gate, it is cutting this to down what? To 222 K. So saying like a 95% reduction or so I guess on what it saw before, but like, this is yeah. With no visual reduction here either, and this is without resizing the actual image. Right,
(19:26) Scott: Right. And you'd want to do both. Yeah. Ideally anyway. Yeah.
(19:30) Tim: So we can get a nice, like do some shrinking, serve up through the media attributes, but then we're always still going to have that delay of like having you go through the CSS step before we request this image. Right. Because it's not in the markup, it's always going to take the browser a little bit longer to find it. So what you could alternatively do is look at like, maybe this is an image that actually does make sense, to be in the content itself.
(19:59) Scott: Yep. Kind of looks like content there's, there's something there you could describe.
(20:06) Tim: And if it didn't, I know you can, I hesitates this feels dirty, but you could do things. I know, I think Harry Roberts has written about this approach actually like you can take and inject like put in a hidden image in the markup right by this. So that at least the markup is it's discovering the image right away. That's another option potentially at least gets it into the markup so the browser can find it and grab it.
(20:31) Scott: Yeah. And that's a good thing to mention because, it's easy to forget. Sometimes people don't know that, an image is going to be requested if it's in the markup, even if you hide it. Right.
(20:44) Tim: True. Yes. Right. Yeah. Yeah. I remember doing like in the early, early days of responsive design, I did a whole bunch of like, I don't know, fired up like 20, 30 different devices and tested all this stuff. And like at the time that was a pretty surprising revelation to me.
(21:42) Scott: Joke in actual solution.
(21:46) Tim: Yeah. If we put this in. Yeah. So we put this in the markup or another option might be to preload. Right. Like it, we preload, that would also push it up a little bit. And that way it doesn't have to have the empty image or I'm sorry, that hidden image in the markup as well. So there's a few different options probably.
(22:01) Scott: So, so by preload you mean put a, link rail pre-load yeah. Up in the,
(22:09) Tim: yeah, it doesn't fix the, yeah. So by itself, I mean like anything we're talking about by itself doesn't do it. It's probably gotta be a combination of things like you want to do probably, either the markup write a hidden image or hidden picture element or preload. and then in addition have the different sizes going, but yeah, if we put like a link rail pre-load on here that would bump it up quite a bit.
(22:30) Scott: Yep. Yep. And if you did have different size images, say through CSS break points or something like that, you could use media queries with the preload too, right?
(22:44) Tim: Yes. Yeah. That is absolutely. That works. That was actually, I think Pat, Meenan just, tweeted about this the other day. Like he didn't realize this was a thing you could do, but yeah you are able to use the media attribute with media queries on your preload element. Technically this allows you to do it for other resource hints, but it doesn't work yet. So preload though. It does. So, yeah.
(23:09) Scott: Yeah. So, varying of, how, easy that is to maintain it's tricky when you've got a hero image that's way down in a post, a blog post, for example, and way up in the head, you want to preload something? Coordinating those, especially if they're more than one size can yeah. Can be kind of tricky.
(23:32) Tim: It can be. Yeah. Yeah. And especially if, if the markup is containing a background image, sometimes that CMS generated and like there's a detachment too, between different. Yeah. It's just a little tricky.
(23:42) Scott: So what if we had an image in the page that was a, a, a content, a foreground image, and we wanted to just make it request at like a higher priority without preload. Could we do that?
(23:57) Scott: We can now like, well, soonish, like keep saying like, priority hints, good segue. So priority hints for anybody who's not, which is probably a lot of y'all because this is a new, thing. Priority hints, I think there was an attempt at, playing around with this a few years back. I see this article from like 2019 and then it just kind of died. So, Pat has been working on, I think I'm logged out Twitter in this one here. Yeah. All right. Give me a second. Pat Meenan has been working on the, priority hint stuff inside of Chrome and recently got it out there in Chrome version 96. Yeah. So let me grab,
(24:56) Scott: And that, that impacts, not just images but other kinds of resources, right?
(25:00) Tim: Yeah. Absolutely
(25:02) Scott: Link elements.
(25:05) Tim: Yeah. So he's been doing, if I, but if I just did, he's been tweeting a bunch of these. If I spell, right, so he's been doing a bunch of these experimentations, like, really quick, just first for the priority hints. It is in origin trial, which is like this whole process that you can sign up and be able to try it in the real user world like, on your site, in production, in Chrome, which, if you're in a position to do that, is worth doing because it's very helpful for, getting actual feedback in terms of what is the real world impact like that real user data matters quite a bit. but there's also the ability then to fire it up, in these sort of synthetic data test, and this is where like, things like this, that Pat's been running these comparisons here with and without to show, like what happens to the LCP reduction.
(26:03) Scott: Yeah. This is really great. So this is the Google flights,
(26:08) Tim: Yeah. So this one is Google flights. So if we were to look at the priority hints versus none the LCP element in this case, I believe well, let's take a look at our original first. So LCP wasn't too awful slow anyway.
(26:28) Scott: Two and a half seconds.
(26:30) Tim: Yeah. This SVG. So there's a flights underscore3.SVG. So in the original test and he's got this proxy through a CloudFlare worker, which is always fun. In the original test, this is what it looks like. You can see there's your HTML response, little CSP stuff, blah, blah CSS. And then, so it's request number five. So it's not like it's very far down the line.
(27:00) Scott: And he's, proxying this to get kind of a control, right?
(27:02) Tim: Correct. Yeah. So he could have tested this and probably did first like test the site without any CloudFlare proxying however, CloudFlare workers lets us do things like dynamically, add the priority, hint, for example. And if, we're going to do that so that we can run that through webpagetest and see the result. We probably want a test case where it's proxied through CloudFlare, but we're not changing the markup that way. We're at least getting some apples to apples. Cause that's going to impact, response time and potentially the prioritization or order of requests. So, we want to have an even testing surface. So that's what this is like, this is your control. Nothing changed
(27:45) Scott: Makes sense. Okay.
(27:46) Tim: And so, yeah, so it's not that far down, but what's, I think kind of interesting and I actually want the green bar to go away. So I'm going to look at the film strip view on this one. Just because I think it's a little easier to see. So if we were to go to let's highlight our LCP and let's just give us a little bit more granularity.
(28:11) Scott: Yeah. The settings are up in the top right now. That's part of the new design. Yeah.
(28:17) Tim: Yeah. Snazzy so if we come down here, and I've got the red lines, you can see the little markers lined up, right about the time that we're making this request for flights three. So I just wanted to show like why this has potential for priority hints. So with a priority, hint, what we're doing is we're adding something like importance equals high or importance equals low. You can actually hint the opposite and say like, Hey, this is a lower priority thing. So to your point, it's actually could be potentially very useful for things like changing priorities of pre-loads or, or async deferred scripts or lazy loading CSS and changing priority of that. Like there's a lot of interesting applications. I think the one we're talking about and the one that Pat's played around with the most is the, adding importance high to an LCP image. But there's a lot of opportunity for experimentation here.
(29:07) Scott: So that's the, attribute name is important that you put right on the image on it. Yeah, yeah.
(29:18) Tim: So this is the original again, the thing is like this request, so it gets discovered around one point or queued up around 1.8. Yeah. Right around 1.8 seconds or so, right about there is when we actually get that image going. Now, before that there's other stuff happening. Like there's our CSS, just all this Google stuff. There’s the request being made. If we were to go down to, the bandwidth utilization, this little green line, we would see that there's actually quite a bit of like, it's pretty low. There's a lot of bandwidth available that we're not actually taking advantage of because we're spending most of that time on connection costs and setting things up.
(30:09) Scott: Yeah, Interesting.
(30:11) Tim: And so now this is on a separate domain, it's on G-static. So we're still going to have like the initial connection time to get this image, but there's no reason for us to wait this long. So this is where like priority hints can kind of be helpful in this case. So then if we jump to the priority, hint one, and so you can see the way you test this is right now, you gotta test it in Chrome, Canary, you need version 96 and then you pass a command line flag, which is enable blink features priority hint. But then if we go to our run 3 down oh, I am on run three. That's fine. Silly Tim. I want to look at the film strip again we'll do highlight largest contentful paints and let's go ahead and give us the 1.1 seconds just for fun.
(31:08) Scott: Yeah.
(31:10) Tim: All right. So now see here though, like this is the big difference, right? It is requested third instead of fifth, but the biggest thing is it shifted all the way over here during the same time that we were making the initial connection cost for everything else. Yeah.
(31:22) Scott: Yeah that’s pretty cool. Can you show in the compare view?
(31:27) Tim: Yeah, absolutely. We'll go back to the compare now. Which I think was our original here. I'm being lazy. Oh, there it is. Okay. So yeah. So if we come here and adjust the waterfall opacity and kind of play back and forth, so here we see on the priority hints 3 and in fact, let's line up with where that comes in all the way over here is when we're first starting to make that connection. The browser sees it's a high importance grabs it pretty early, but on the original waterfall at that point, it's not even queued up for download yet. Yeah. Like it's a full what almost 700 milliseconds, 600 milliseconds earlier.
(32:15) Scott: Yeah. Which is a big deal for yeah. Yeah. Especially significant. I mean, and that's just, in an ideal kind of setting, it could be delayed further, so
(32:26) Tim: Yeah. Right. Yeah. And this is, so he's been playing with this on a bunch of different examples. Like if you, again, if you look through Pat's recent Twitter, I think he's done Amazon product page saw improvement, MSN improvement, like pretty much everything he's been posting a bunch of like pretty substantial Improvements.
(32:47) Scott: That's really cool stuff. Yeah. Definitely, recommend following along. I'm excited to see this feature. I mean I remember, for a while, I was pretty gung-ho on this asynchronous CSS loading thing and, we had this--
(33:02) Tim: I've used that.
(33:03) Scott: Approach. Yeah. We, we still use it now. And then, if you need to load a style sheet that contains, font references and you don't want it to block the, the rendering of the page while it's requested, maybe you'd requested async, something like that. And the way to do that, is yeah listed here. So, the trick of it, and I'm getting around to the request priorities thing. But the trick here was to set the media to something that by default, just loads in the background or in parallel. So print happens to do that. And then on load, you would flip it to all or to screen and it would apply to the page. So that's like a way a trick to load, CSS asynchronously, a downside to this is that it would request that a low priority.
So print style sheet, which is a really good thing, request at a low priority because they're not needed to display the page on the screen right away. But if you're using a hack like that to get a style sheet, as soon as possible, you might want it at a higher priority, even though it's asynchronous. Right. So we ran into this dilemma and, there are a couple ways to work around it. You could, put a preload link in front of that, that style sheet link and, requested earlier. And then it still gets requested in parallel by the link itself that follows it. But something like this, importance could make all that a little more, streamlined with just one element. It sounds like,
(34:46) Tim: Sounds like an experiment we should be running anyway on the async CSS and just seeing what the impact is there. Like absolutely fun test.
(34:55) Scott: There is a way to get a high or a low priority. I went through all these options and, the alternate style sheet, something, a feature that we rarely use these days, but you used to be able to load many different themes for a page. For example, you can still do this actually. And if you put, link rail alternate, then it, some browsers will expose it in a menu that you can switch styles for the page, maybe be to high contrast, things like that. That happened to request at a low priority, like, print media. And you could combine that with preload, to request the style sheet and also have it load, at high priority asynchronously. So there were like all these options you could kind of, but it's very, it's still a hack.
(35:48) Tim: Yeah. Well, even that would require some testing. Because one thing, I mean, it's not, we haven't talked about it here, but like the other thing that changes in Chrome 95, which is not quite out it comes out next week, but in Chrome 95, preload is going to be behaving entirely differently than what we've known in the past. Like preload always had this, just jumped right to the top of the queue. There was some issues there with like some old code hanging around from app cash and stuff like that, that messed with prioritization. Like, yeah. So, and Pat also he's been busy. So pat fixed that up in Chrome 95. And so actually preload, I've done a few tests with preload that have preloaded is dramatically different in 95 than it is now. So like that, because I know, I know what you're talking about with that preloading in the CSS. And so then you had that same sort of issue sometimes. Well now it's too high of a priority, right? Like now and yeah, but like testing that in 95 would be interesting because preload is no longer quite as aggressive and it’s interesting.
(36:48) Scott: Yeah. So it'll be good to have more control over priority. When you want it.
(36:54) Tim: Yeah. Agreed. So, a question here about testing priority, how answer without service workers and webpage test, is there any documentation there is not yet documentation for how to test it? We could probably just walk through one really quick. How we would do it. So like, and with the caveat that if you have access to your site, and your source code, like just make the change there and don't even mess with like, if you have like another, even a staging environment or something else where you're able to test a version of that site. Right. Try it that way. And you don't necessarily have to go through this. This is if we need to, I don't have access in this case to source code. Or if it's easier for you to do it this way than adding, messing with the source code, this would how
(37:39) Scott: It'd be nice to run test, that don't actually impact the live site. For sure. So if you don't have staging, maybe it's good to experiment somewhere else. Yeah,
(37:50) Tim: Yeah, Okay. I'm trying to think if we should do that on the background image one or if we can do that on one of the cause we've got a couple, well, no, hold on. I think let's look at one more example, cause I think maybe we can try it out on that and, and kind of showcase that workflow a little bit there. Sure. Yeah. This is by the way, a good point. We do in the performance. Yeah. We tend to have a habit sometimes of taking the things and kind of going to town with them. It'll be interesting to see what happens there. I could see that getting out of hand, trying to own too much of the prioritization.
(38:28) Scott: Yeah. Yeah. I think, in general browsers are really smart about prioritizing things in an order that is probably a good default. Right. And this is for overriding that, in cases where you really know you need to Yeah,
(38:44) Tim: Yeah. It's not yeah. Getting a, you don't want to go wild with it and change everything out, but yeah,
(38:51) Scott: Yeah, yeah. Z index is a good, is a good metaphor. I think [Interposed talking38:58 ] even more so like tab index, and actually numbered tab indexes, which we don't really do as much anymore. Once you have that level of control and, take it into your own hands, it's easy to mess things up.
(39:16) Tim: It definitely comes a point where you start trying to like take too much like yeah. Trying to basically recreate everything the browser's already kind of figured out to some extent, okay. So before, like I think this might work for the priority. He one, this was another site, this is, a job staffing site. Again, dug through HTP archive, tested on desktop in this case, LCP was kind of in that needs improvement range. And if we look at this one, it is an image, but there was this going on right here.
(39:57) Scott: Oh yeah. Okay.
(39:59) Tim: So the loading attribute.
(40:00) Scott: Yeah. That's sometimes an anti-pattern.
(41:11) Scott: Was there an update related to this?
(41:14) Tim: Yeah. Yeah. So, there was a bunch of research done on, the, that this is actually I think where the fix for this eventually came out of, but they were mining HTP archive data and they found out they were like looking at sites that used, the loading attribute yeah. And thought, oh great. We could show some sort of a nice connection between this and improvement in LCP. And what they found was the opposite. Like if you were using native image, lazy loading your 75th largest gross contentful paint was actually slower. And it turned out, this is why it was because WordPress was using the, the loading attribute equals lazy and applying it to all images.
(41:57) Scott: Yeah.
Lazy, all the things, right? Yeah.
(42:00) Tim: Yeah. So they did,
(42:01) Scott: we don't want that.
(42:03) Tim: No, that's not good. So they did fix it. They did fix it. They put out a fix for this. But this is a nice demonstration of the issue. Like this gets applied, that loading equals lazy attribute. And then as a result, when we come down to the actual waterfall here,
(42:17) Scott: its way down.
(42:17) Tim: Yeah. It's pushed down and it's definitely deprioritized compared to other things around it
(42:23) Scott: While you're here, sorry to cut in, but worth noting that in the markup there. One good thing is the width and height attributes [interposed talking42:36] into that, last episode, couple weeks ago where, layout stability, can be affected by this hero image too. If you leave these attributes out, you get, you get no, no space where the image is going to be until it pops in. And it, it shoves the content below it down. You get some instability, this prevents that. So that's nice.
(42:57) Tim: Yeah, no, that is good. And I think actually that's, their CLS score is pretty good. Yeah. And that's a big part of that. Like if you can see in this screen, this little thumbnail here where it is preserving the space, right. Like nothing's collapsed underneath it. Like, yeah. That's a good catch. Because if that's off, if that's missing you’re getting two big problems, LCP and CLS, so that's a good catch.
(43:18) Scott: Yeah. So I have a question. What if that image had a background color on it or, behind it, would LCP be tricked into thinking it's, earlier, how is it measured?
(43:34) Tim: Yeah. So LCP wouldn't be tricked by a background color. Like background color itself. Isn't going to trigger it. It's gotta be like an actual piece of content. So background image yes. Text, Yeah. So you could trick it by, for example, having a one by one pixel remember the whole spacer gif things. Yeah. You could drop something like that in there. Yeah. And in fact, I think we've seen a few examples of folks that are kind of doing that, where that load immediately. Yeah. That loads immediately, your LCP looks amazing because you've basically tricked the browser into thinking something sits there. Which, gets back to you your point earlier about, are we doing this to improve a metric or are we doing this to like, help the users?
(44:22) Scott: Yeah. And may be a little bit of both in that case, if you have the blurry image that gets replaced, or sharpened, I guess. Yeah.
(44:31) Tim: I think this is actually, there was somebody Tim Greek who, operates scale mates and I'm going to blank on finding the exact page, but I know he had this, like he had color swatches on his page. That technically were content. I think he had a back if I remember right, it was either, oh boy, and I’m going to mess this up. Now it was either a background color or something like that, that wasn't getting flagged for this color swatch when it was loading, it wasn't content. So it wasn't registering as the contentful paint. And so his content for paint was getting delayed and then it was like a something else on the page. Yeah. and so he ended up swapping that basically doing that kind of approach, making a small image that scaled up, instead of a background color to get the browser to recognize it was content out once in that to me in that gray area. Right. Yeah. Like right. It's not hurting the users to make that change. It is definitely working around the limits of the metric, but
So this one, maybe we can try to, I think we got, yeah, maybe we can try to like actually change this one using workers and this will show off a little bit like, if you wanted to test, priority hint or really anything else like that. What would that look like if you didn't have access to production code?
(45:52) Tim: I'm going to try. Yeah. Okay. So, let's see here. I'm going to put on some code. So this is the, the generic template. I think it has like a history. I'm pretty sure it was originally started in a presentation Pat Meenan did a while back, about webpagetest sort of power stuff. Andy Davies then made some edits to it, put it up on his blog. And then that's what I've got here, I think is the version of that. There may have been a couple more steps in between, but whatever.
(46:48) Scott: So a little service worker.
(46:50) Tim: Yeah. Basically. So this, this runs in, this is a CloudFlare worker, so this will run on Cloudflare's edge nodes. And what we're oh, thanks Barry for digging that up. For anybody who was familiar on one of the story we just talked about with the background image and stuff like that, here's the Twitter thread that kind of gets into that.
(47:10) Scott: Cool. Thanks for that.
(47:10) Tim: so yeah, so this will run, like when you put this put it up into CloudFlare, then anything that, it's basically like got, like you said, it's like a service worker that's running on the edge machine on the CDM level. It
(47:25) Scott: Really neat.
(47:27) Tim: So we're able to change things around the markup and how things are responding, remove headers and actually manipulate the HTML, like a whole bunch of stuff, on the fly, which is
(47:37) Scott: A little handy. Yeah, yeah.
(47:42) Tim: So without getting too much into a, I mean it's, we're fetching basically we're listening to any fetch event and then we're going to respond with this handle request, method and the result of that. the key bits are this, where we're seeing request headers.getexhost, webpage test adds an exhost, header when you proxy, like when you're sort of by-- yeah Using our sort of routing through the domain, we'll add the ex-host for the original host. So we can check that here. If it's missing, we'll just not do anything with it. and then there's also this piece here where if we set for an example, an X bypass transform header to equal true, then that says, that's our way of doing that test case, like proxy it through CloudFlare, but don't change anything. As long as that's not around then we're kind of coming in here again, we're looking for in this case, the HTML, and then we're using Cloudflare's HTML rewriter, which is kind of a little pretty handy, not too bad to work with once you get your head around it. Yeah. But you can do things like watch for an element. And then when that element is discovered, do something like append or prepend, something to the Dom or, change an attribute, something like that.
(49:06) Scott: Yeah. Sort of like JQuery.
(49:08) Tim: Yeah it's sort of like JQuery. Yes. It is pretty friendly to use. It is, I would say pretty familiar for anybody who's done that kind of stuff. It is kind of nice.
(49:17) Scott: Yeah. Yeah. This is really, really powerful stuff.
(49:19) Tim: Yeah. So, given that, let's see, I should really we’re going to do
(49:30) Scott: While you're setting this up, I can, I can say that, in the past for clients we've used these kind of workers for, running AB tests. So moving that logic, instead of running it on the client, move it into here, just save a little of that upfront time that it would take to swap a whole section of a page out on the client side and instead do it before it even reaches the browser. It's pretty cool stuff.
(49:59) Tim: Nice. So what I'm going to do is, this I'm going to try to, I'm just, again, sound effects are free. Just setting it up so that it's all kind of in one window. So it's a little easier to jump between to share. Okay. So this is the one that we want to proxy is gemstatestaffingjobs.net. So first thing we're I'm going to do is drop the name of the site here, because we use that later it to sort of check, do we actually want to, pull this origin in and manipulate the content. So all we're looking, we don't need the HTP like the protocol. We're just looking for the actual, domain here. Then the next thing I'm going to do is actually I'm going to test that. So I use, an extension called mod headers, which is a handy little extension that lets you add headers, like manipulate request to response, headers in Chrome. I actually think it works. I think if I remember right, there might be a version for this for like Firefox or something like that, but its super slick.
Here I'm just going to add the, the gemstatestaffingjobs.net. And then my, let's see if this works, my worker, I'm going to come back to code. Okay. I've got that set. So I'm going to publish this Using CloudFlare little CLI, which is Wrangler. They've really nailed the dev experience on this. I gotta say like its fast and it's pretty painless to work with. That’s nice. I'm pretty impressed. And so if I go to CFworkersandbox.timCadlec.dev Perfect. Okay. So now we can see, like if you go to this, it's pulling in that site behind the scenes, which is good. Nice. The next thing we want to do is I guess, grab this image.
(52:07) Scott: Find it right.
(52:10) Tim: Yeah. We gotta find it and then kill the loading attribute. Right. So I think for finding it, I'm just going to, I mean, it's not the prettiest way to do it, but I'm just going to look for the image with that source directly. I don't,
(52:23) Scott: Basically an ID,
(52:24) Tim: I think it's a job done. Yeah. So if we come back to the code then, and to our HTML writer, I'm going to go ahead and Comment out one thing here. So we're going to look for an image with, source equals the one we just grabbed. And then when we find that we're going to, let's see. So we grab it, we're calling it L at this point. So L.removeattribute.
(53:00) Scott: So you get some Dom methods in there.
(53:04 Tim: Yeah. You do a little bit, a little bit
(53:06) Scott: Remove the importance or remove the, loading.
(53:09) Tim: Oh, you're right. Yeah. I'm jumping ahead. Aren't I? Thank you. Nice.
(53:15) Scott: A few steps. All right, cool. Right. So we're going to load. Yeah. Nice Attribute.
(53:23) Tim: We'll publish that up and yeah, that should get rid of this attribute is what we're looking for. So if we come back over here, make sure it got published. Yep. And we'll do a refresh and we're just going to actually view the page source and look for that little image.
(53:44) Scott: Let's see if that magic worked.
(53:46) Tim: Let's see. Do you remember what the source was? That I was still on the, yeah, there. Yeah. So we've got an image. I'm looking now to see if we've got our
(53:58) Scott: And it have a source set.
(54:00) Tim: It does have a source set. I see. That's nice.
(54:02) Scott: Yeah. I
(54:03) Tim: Like that. Yeah.
(54:07) Scott: Responsive image.
(54:07) Tim: Okay. Good to see.
(54:10) Scott: Yeah so that worked great.
(54:10) Tim: Yeah. So the loading attribute is gone now. Very cool. So now, if we went back to page test, we could test quickly, like what does that do? So, we're going to grab the URL. We want the actual original, we want this.
(54:35) Scott: And I know you mentioned, they found that the WordPress thing was a little aggressive and we see it here. Is, is there a WordPress update that fixes this? Do you know?
(54:45) Tim: There was work done? I don't know if it actually has rolled out to like a proper release yet or not,
(54:51) Scott: For anyone listening it's probably worth looking, see if they've rolled an update out yet, but--
(54:55) Tim: They did do a, a second. They did a follow blog from the word press team. I'm just not sure if it's like that work has actually rolled out or if it's still kind of hiding out. I see Barry, you asked that. Sorry. I missed that. Yeah. Okay. So we want to test this one and we want to test it in Canary, because that'll be version 96 for us. That's where priority hints are. We're in a drop number
(55:19) Scott: Was that the worker URL? Did you have?
(55:22) Tim: Yes. That's the working URL. We’ll proxy it in a second.
(55:27) Scott: Cool.
(55:28) Tim: So I'm dropping the test runs down just a little bit to make it kind of fast. So it doesn't take forever. and then I'm going to say proxy no transform, which is kind of just what I've been defaulting to when I do these things So right now it's it would, if we submit it, it would a test as normal, through this, In Canary, it wouldn't actually pull in CloudFlare workers or anything like that. So for that, we need to go into the script tab and I've got a shortcut because I always forget this. But this is the gist of this script. We're going to override the host, which is a pass through variable. So that'll override this with CF workers, sandbox.Timcadillec.workers.dev, and then navigate URL.
(56:23) Scott: Nice.
(56:24) Tim: And I'm going to add one line in here. So that X bypass transform header that we mentioned before, this should run the test, proxy it through CloudFlare workers, but don't actually do any sort of change to the page.
(56:48) Scott: Cool.
(56:49) Tim: Should nothing like [Inaudible56:52] we’ll see how this goes. I think [Inaudible56:56] job done.
(56:57) Scott: Just a few minutes left here. I think we're going to do it.
(56:59) Tim: Yeah. We're getting there. I think we'll get through this part of it. And then we can kind of hint at what the importance would be, but might not be able to show that yet. So if we pull that out and then also run that test, and I forgot to update the label, but shame on me, but we'll get one test run test in the background as well with the transform applied. So without it applied, if we click, we can see everything's proxy through CloudFlare workers. That's what we were hoping for. Nothing's really changed with the image itself. Yeah. Now if we come back here, I think I'm zoomed in. I did all sorts of weird things to the, there you go. Yeah.
(57:43) Scott: Yeah. Again incremental.
(57:46) Tim: Yeah, exactly,
(57:47) Scott: Work on that view a little bit.
(57:49) Tim: So now if we come here, ooh, that's very interesting. Some funkiness going on over there. That's one we'll have to add to our backlog Scott.
(58:02) Scott: Yeah.
(58:04) Tim: Yeah. If we come down here, we should see like a change I guess in that initial priority. For which image was this again? Anybody remember?
(58:12) Scott: Yeah. And maybe we could
(58:14) Tim: Job search.
(58:17) Scott: Yeah. Staffing
(58:19) Tim: That one there.
(58:22) Scott: Search staffing. Yeah. I think so. Maybe if you got it in the timeline view.
(58:30) Tim: Check out the film strip. You're saying
(58:31) Scott: yeah. Sorry, filmstrip.
(58:33) Tim: That’s all right.
(58:34) Scott: We could compare that to the original. Right.
(58:37) Tim: We're going to pick a different something's a little off a skew with that first one so we can compare let's see that. And we'll do the no transform we're going to use for this Matt Hobbs handy little thing here will this auto generate really easily for us like specific runs to compare For these two different tests. So we wanted to do that and. Matt is passing a parameter to change the background color of our films strip,
(59:23) Scott: Which is something you can still do if you want those.
(59:26) Tim: You can totally do it. It's an option. Yeah.
(59:29) Scott: Yeah. We, we, kind of brought in the, the background from the rest of the site, for this page now. But if you download the image, it'll still map, to whatever you set the, the background and the foreground to.
(59:42) Tim: Yeah. So still totally doable. So there's just a tiniest, a bit of difference actually in this case, by removing that attribute, this is one of those I'm going to kill this.
(59:54) Scott: I think there's enough requests in this page already before that image. Right. That maybe it wasn't.
(1:00:01) Tim: Yeah. It's not a very dramatic impact because you can see like there's a little bit of a stagger, on the original versus yeah, it's queued up just a hair faster here. Like it lines up with the preceding request. Whereas before there was just a hair of a gap there, but it is a pretty small change. So this is one of those situations where it's probably hygienically better to have it off, but it's not going to make a big change performance wise. It turns out.
(1:00:32) Scott: Yeah. So it's good to test these things. And then from here you maybe mess with the importance attribute, although that's sort of forward looking yeah.
(1:00:41) Tim: Would be easy enough to add
(1:00:43) Scott: Or a pre-load right?
(1:00:45) Tim: Yes. You could look at either one of 'em.
(1:00:47) Scott: But the tricky thing with the pre-load is there's a source set in play here. So there's one of many,
(1:00:53) Tim: Well, this would also be a good stress test of the priority hint too. I'm not sure if actually like how well priority work with the different source sets and stuff like that. I would hope, but wouldn't be too surprised if the initial, version of it has a few quirks and stuff when it comes to that kind of thing.
(1:01:13) Scott: Let's see it.
(1:01:17) Tim: Yeah. Once you put in, so this is how you would test the importance high just for the folks who had asked earlier in this case, I'm removing the loading attribute and then I'm just setting importance one and then it's the same process like go through and kind of confirm. We should see an importance high catch to this now. Oh, my browser is freezing up on me because of the Dom size, but there we go.
(1:01:46) Scott: Oh, nice.
(1:01:47) Tim: Little importance high. And so then yeah, if you rerun the test now, but you ran it with that command line that we saw earlier, on Pat's example, the enabled preload hints. Now we'd be able to see exactly what the importance does as well. So that's the process and I agree. We’re working actually, a few ideas for different kind of snippets, including things that like, probably like a recipe collection for things like CloudFlare workers and fastly edge compute and Akamai edge workers. Because you can do it with all three of those, major CDNs now at this point. So there's some really fun stuff kind of coming up along there.
(1:02:23) Scott: Yeah. We've got lots of ideas. The team is growing.
(1:02:26) Tim: Yes it is. We don't have Jeff on that. We should make Jeff jump on a stream just to say, hi one, his cat is huge. He's got a huge cat. Like you got little kittens, but his is a giant it's like 15 pounds or something like that. Yeah.
(1:02:41) Scott: Yep.
(1:03:19) Scott: It pays to pay attention. Yeah. Yeah. And now you know how to look for it.
(1:03:24) Tim: Yeah. So, yeah. I think we're at about the hour. So folks want to kind of hop off, we appreciate you jumping in, we'll be back on and again, in two weeks going through more, feel free to drop ideas and suggestions. We can lurk around for a couple of minutes. Probably Scott, if you can, as well, just to kind of answer questions that come up, but thanks everybody for tuning in
(1:03:45) Scott: Little Q and A. Yeah. Thanks for listening. Do you see any here that--?
(1:03:54) Tim: No. I'm looking here
(1:03:56) Scott: Worth calling out
(1:03:58) Tim: Hero images that take the full viewport dimensions won't be tracked as LCP element as in like it fills the entire screen. Won't be tracked as an LCP element. I don't know if I actually have seen a situation where that's happened. I'm not familiar. I wouldn't know if I would call it a good, like again, it goes back to like the user versus, I mean, if there's a legitimate reason why you want to do that from a user experience perspective, maybe, but if it's a thing to try and specifically hijack or get around the metric, then probably not worth.
(1:04:39) Scott: It'd be good to see a lighthouse or a webpage test run that that shows that. Yeah,
(1:04:43) Tim: I'd be fascinated. Yeah. If you've got a URL or something that has something like that, it'd be cool to look at that one time. So yeah, I agree. That'd be kind of interesting.
(1:04:52) Scott: Yeah. Let's see what else we have here.
(1:04:57) Tim: Anything else popped up at all? Are we pretty good?
(1:05:03) Scott: Yeah. Well, I saw earlier, it sounds like that, that lazy attribute, or loading attribute, WordPress. Yeah, there we go. it, it sounds like it's sort of still open for debate whether or not this is WordPress's problem or maybe the browser should be doing a little more, I don't know, applying a little more [inaudible1:05:28 ] figure out if it really should be requested sooner maybe override the preference. I'm not sure.
(1:05:33) Tim: That's interesting. Like, yeah. That's always interesting. Like how much do we want to trust the browser [inaudible1:05:38] in a situation like that to override something the developer is indicating like on the one hand, yeah. It could save us some problems of like, mistakes or things like that, getting thrown out there on accident or whatever. On the other hand, it does feel a little bit like it's starting to then break the agreement that we had about how this thing is supposed to work. Right. Like now its do this unless you decide you don't want to do it.
(1:06:02) Scott: Yeah. Hmm. Interesting. And I'd imagine there's probably a little conflict there with needing, to know, layout dimensions before deciding whether, or is this element in the viewport or not? Well, in order to do that, you kind of have to render a bit of the page, to know if there's a giant header that CSS is going to push the image down and suddenly it is lazy loadable. Typically images get request stood before that, that that layout logic needs to happen.
(1:06:41) Tim: Yeah. And Chrome will try to adjust the priorities. Like if it can tell, I think Chrome's got like this sense of like different prioritization for, images high up in the view port versus down. But I don't know, like what the check is there and, how long the check takes and what are they actually looking at to determine what that is like under the hood. Bu yeah there's work involved basically there to make that happen. So an expectation that you gave better performance by hinting it directly and not relying on that.
(1:07:10) Scott: Right. Yeah. I mean, a good takeaway here is just if your image is showing up pretty late and it's getting flagged, maybe see if that attribute it's there. I don't know if WordPress lets you manually remove it on images that are high up.
(1:07:25) Tim: Good question. Yeah. Yeah. Be worth digging in too.
(1:07:28) Scott: Yeah. Yeah. Yeah.
(1:07:30) Tim: All right. Well, thanks everybody. Thanks Scott. Thanks.
(1:07:33) Scott: Thanks Tim.
(1:07:34) Tim: Thank you. Async and defer sorry the cats for making the cameo. Yeah.
(1:07:39) Scott: Oh man. They're asleep again. Next episode. Just all kittens. No people.
(1:07:44) Tim: All right. We'll just have him sitting up there and we'll just replace me. It'll be Scott and the cats I'm aware that right.
(1:07:53) Scott: Scott's cat show. Sounds good.
(1:07:54) Tim: Thanks everyone Bye.
(1:07:57) Scott: Thanks.