Check out a free preview of the full Web Performance Fundamentals course:
The "Responsive Images Practice" Lesson is part of the full, Web Performance Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Todd explains how the srcset and sizes attributes are used to load images based on the browser window's width and adds this responsive image code to the project. The images in the project are also optimized using an optimization script to reduce their file size.

Get Unlimited Access Now

Transcript from the "Responsive Images Practice" Lesson

[00:00:00]
>> So let's look at how do we improve images even further, because even though we're not pulling all of our images down right away, they're still kind of big. They're bigger than I would expect them to be for what we're doing. For example, if we take a look at our images, these call out images that we need to download, even though we're downloading them lazily a 1.2 megabytes for this one, and 250 kilobytes for that one, which is pretty big.

[00:00:34] They're pretty big for what we get out of them, which is this little image right here. Even though it's a great image, it's probably not a 1.2 great, 1.2 megabyte worth of great image. So how do we reduce this? Let's say I have a picture and the source I have of the picture is 1200 pixels wide.

[00:00:56] I name it picture-1200.jpg, just to kind of indicate picture quality. Well, how I display that picture is gonna be different based on which browser and which device my end user views it on. For example, on a large screen on the desktop, they might see that image in the full 1200 pixels wide.

[00:01:21] And I'm showing them the right thing. But if they're on a tablet, the responsive nature of the website is gonna squish that down, and I might only have 900 pixels. On a mobile I have even less and I can only show 600 pixels. So how do I improve and send fewer bytes down the wire by showing a smaller version of the image for this particular screen size?

[00:01:51] Well, there's some annotations that we can use for that called srcset. Now, in the old days, an image had a source, it's like here's the file, load this image. But now we can say multiple sources and some rules about when to use them. So for example in addition to the 1200 pixel version, I have this picture.

[00:02:10] I have a 900 and a 600, which I can describe using this annotation. I can say here's a 600. Here's a picture, it's 600 wide. Here's a 900, it's 900 wide. Here's another one, it's 1200 wide. And then we can tell the browser when to use these by using a sizes annotation.

[00:02:29] That says just like a CSS conditional rule, up to the max width of 600 pixels, use the 600 pixel image. If it's up to 900, use the 900, if it's anything else, use the 1200. And so doing that, we can optimize which images get delivered down to which users.

[00:02:52] When the browser goes to interpret it, it's gonna look at the sizes attribute first, it's gonna say, hey, what are my rules, which one do I need to get? And then it's gonna look at srcset and it's only going to get the image that it needs. So if the screen is only 500 pixels wide, it's only gonna pull down that picture 600.

[00:03:10] It's not going to bother downloading the other ones. If there's not a srcset or the srcsets don't match, eventually it'll go back and look at the source, but only as a last resort. The other way that we can improve images is simply by crunching the images. There's a bunch of algorithms that we can use to actually just rip out unnecessary quality attributes and metadata inside of most images.

[00:03:37] Here is an example from a service that I've used a bunch called tiny png. It's a cool picture of a panda. On the left it's 57K, on the right it's 15K and they're exactly the same. You can get a lot of mileage out of just crunching your images.

[00:03:52] So let's do that, let's do that together. So I've built a little utility for us to use. If we take a look inside of the tools folder, I have a little js file called image optimizer. Now, we don't need to go through this line by line. But this is a build tool that you can use called imagemin, and imagemin just apply some of these really common image optimization things that's got plugins for JPEGs, and PNGs, and SVGs, and GIF images, and whatever.

[00:04:24] I've built this image optimizer to basically go through all of the images that we have in this website and create a .min version with these common optimizations. We can run that right from the terminal. So let's stop our website. Now we can enter the command npm run imagemin.

[00:04:46] Because I've defined this as a command in my package,json. If we run that, it blows up. It blows up because I'm using the wrong version of node, sorry. Okay, hopefully it ran successfully for everybody. It takes, a few seconds to run because there's actually some real work behind it.

[00:05:19] What it did is if we look in the public assets images folder, there's now a .min version of all of the files. It's created a crunched version of them. Now we can see what exactly that means. So for example, request_metrics_logo_rss.png, is 4.6K. And the minified version is 3.14K.

[00:05:42] So we got a little benefit off of that. If we go and look like one of our really big images, like these call outs, the unmodified call out break down 24 is 248K. Whereas the minified version is only 223. So we're carving out 25 to 40% off of these images.

[00:06:09] We've generated all of these images right in line. So we're gonna use some IDE incantations to go ahead and replace it. I am going to do a find for anytime there is a .png in this file. And I'm going to replace that with a .min.png in line. I'm gonna run those.

[00:06:31] I'm gonna do the same thing for svg. And that's all I have to do. I don't have any JPEGs or any GIFs in this website. But if you did, you could do the same thing. Essentially on all of these lines, I have just replaced the path to reference the minified version.

[00:06:56] Now, the other thing we needed to do was use some responsiveness to load the correct size image for these call outs. Like this right here. Here's one of our call outs, referencing a 2400 wide call out distribution. We want to change this and reference a src set. So we're going to call this data.srcset, because we still want it to be lazily loaded.

[00:07:28] And we're gonna define a couple of alternate image sizes. So rather than 2400, so we'll have a 2400 wide, but we're also gonna have some other ones. We're gonna have a 1200 wide. And we'll have a 900 wide. And we'll have a 600 wide. Which covers a wide range of possible values that our customers could load our website in.

[00:08:22] Now, how do we pick the right one? How do we tell the browser to pick the right one? Well, that's the sizes attribute as we talked about before, you might actually go to the slides and just copy paste that. I can't copy paste it. Max with 600 and 600.

[00:08:56] Do a 9 and a 12 and all else fills a 2400 pixel. And a 9 and a 12 and 2400 pixel. So we define a couple of rules, so up to the max width of 600 pixels, use a 600 pixel wide image. 900, 900, 1200, 1200, if you don't know, go ahead and use the big one.

[00:09:22] So with this annotation, this image is now responsive and should load the correct size document. Now three call outs. Let's go ahead and replicate this for the other two, which we're just gonna do with some copy paste magic. So I'm gonna copy all of these images down to this next image, and I'm just gonna paste it.

[00:09:45] The only part that's different about my images is they're called callout- something-the size. So I'm just gonna change distribution to break down. And we'll change this one here, To Web Vital. Okay, so with that saved, we're now running smaller images and responsive images. So let's pop back over to our Chrome window and reload this.

[00:10:30] I'm not running. As part of that, I had to stop the server. So we have to go back to our terminal and do NPM start to get our server running again. All right, so now we have this running. And if we go and take a look at our dev tools, If we scroll down our page until some of our things load right now it's loading the 2400 wide image because we're running on a big screen.

[00:11:03] Now if I shrink the size of this to a smaller screen and reload it, I'm now pulling down the 900 wide version of this image. It's going to respond to what screen is running and how big it is to download the right version that you need. So I'm gonna put this back to where it was, which is about 12 or 1150.

[00:11:33] And let's run another lighthouse report and see if we got any improvement. This improvement might be more noticeable for mobile users. So I don't know if necessarily we're even gonna see an improvement right here. Now when we see about the same. But if we were to run this thing using the mobile lighthouse report, I would imagine we would see quite a big improvement from changing those images.