1 00:00:00,650 --> 00:00:04,720 Now that we have these great, optimized images, what do we do with them? 2 00:00:04,720 --> 00:00:07,930 When it comes to mobile to desktop, there are tried and 3 00:00:07,930 --> 00:00:12,470 true solutions that you will wanna use in order to make sure that the end user is 4 00:00:12,470 --> 00:00:16,470 only getting the images that they need for their experience. 5 00:00:16,470 --> 00:00:18,800 By specifically targeting it this way, 6 00:00:18,800 --> 00:00:22,960 you can ensure that your mobile users get the smallest images possible, and 7 00:00:22,960 --> 00:00:26,430 your desktop users get amazing, high resolution images. 8 00:00:27,640 --> 00:00:29,410 As you can see in this example, 9 00:00:29,410 --> 00:00:32,820 I'm using an image to fill the screen of a mobile device. 10 00:00:32,820 --> 00:00:35,420 There is no value in compressing a desktop-optimized 11 00:00:35,420 --> 00:00:37,530 image into a small space. 12 00:00:37,530 --> 00:00:41,710 So when targeting mobile devices, you want to use an image that is correctly size for 13 00:00:41,710 --> 00:00:44,970 that experience, both physically and weight size. 14 00:00:44,970 --> 00:00:48,232 And the good news is the smaller the physical image size is, 15 00:00:48,232 --> 00:00:49,675 the lower the file sizes. 16 00:00:49,675 --> 00:00:54,220 So just by cropping it, you're winning, but how do we code for this? 17 00:00:54,220 --> 00:00:55,481 First, let's use CSS and 18 00:00:55,481 --> 00:00:58,929 media queries with background images using a mobile first technique. 19 00:00:58,929 --> 00:01:02,467 Pretty standard stuff that I'm sure most of you are familiar with. 20 00:01:02,467 --> 00:01:06,990 Using this method, we are ensuring that the user will never see the medium or 21 00:01:06,990 --> 00:01:10,190 large sized images on their handheld mobile device. 22 00:01:10,190 --> 00:01:12,560 We can see this happening in the Chrome inspector. 23 00:01:13,950 --> 00:01:17,360 Viewing this in the inspector, we see that Chrome does not request 24 00:01:17,360 --> 00:01:21,860 any of these images until this spec of the media query is met. 25 00:01:21,860 --> 00:01:26,530 Each time we increase the view size of the app, we meet the spec of the query and, 26 00:01:26,530 --> 00:01:30,047 in turn, make a request for an increasingly larger asset. 27 00:01:32,514 --> 00:01:38,540 Next for images that are actually in the HTML, we code this slightly different. 28 00:01:38,540 --> 00:01:41,370 Responsive images in CSS is pretty standard, 29 00:01:41,370 --> 00:01:44,980 while using responsive images in HTML was not. 30 00:01:44,980 --> 00:01:49,504 Today, though, we have new responsive support in the picture element. 31 00:01:49,504 --> 00:01:52,465 The picture element was inspired by the video element, 32 00:01:52,465 --> 00:01:57,242 whereas there are multiple image sources that are loaded into a source set. 33 00:01:57,242 --> 00:02:00,670 There is a fallback for browsers that do not support this new element. 34 00:02:00,670 --> 00:02:03,800 This solution works amazingly well for managing breakpoints 35 00:02:03,800 --> 00:02:07,590 in the UI where you may want to have specifically cropped images appear. 36 00:02:09,490 --> 00:02:10,760 Viewing this in the browser, 37 00:02:10,760 --> 00:02:15,540 we see that we get similar results as we did using the media queries in CSS. 38 00:02:15,540 --> 00:02:20,986 By increasing the view size again, we see that only when the browser meets the spec. 39 00:02:20,986 --> 00:02:23,900 Then it makes the request for the different assets. 40 00:02:25,510 --> 00:02:30,690 Using CSS media inquiries and new picture element techniques work great and get 41 00:02:30,690 --> 00:02:35,920 us pretty far with loading only the assets we need for the device we are using. 42 00:02:35,920 --> 00:02:40,730 But what about images that are not part of the above-the-fold experience? 43 00:02:40,730 --> 00:02:45,240 Another technique for getting that initial perceived performance as fast as possible 44 00:02:45,240 --> 00:02:50,080 is to not load all the images in the first header response. 45 00:02:50,080 --> 00:02:51,600 This is called lazy loading. 46 00:02:53,030 --> 00:02:56,120 Lazy loading keeps images from being loaded into the view 47 00:02:56,120 --> 00:02:59,590 until the user requests them by scrolling down the page. 48 00:02:59,590 --> 00:03:04,160 This can easily save you hundreds of kilobytes off that initial load and 49 00:03:04,160 --> 00:03:06,830 get you to that first meaningful paint as soon as possible. 50 00:03:08,070 --> 00:03:09,540 For lazy loading images, 51 00:03:09,540 --> 00:03:13,940 we need to make use of the small JavaScript library called Lazy Load. 52 00:03:13,940 --> 00:03:18,876 Lazy Load holds back image resources until a user needs to see them and 53 00:03:18,876 --> 00:03:22,292 allowing your essential assets to load first. 54 00:03:22,292 --> 00:03:24,400 There is a very small trade-off here. 55 00:03:24,400 --> 00:03:27,809 The JavaScript library itself, that is quite comprehensive, 56 00:03:27,809 --> 00:03:29,141 weighs in at around 5k. 57 00:03:29,141 --> 00:03:30,928 This is something to take into consideration 58 00:03:30,928 --> 00:03:32,540 with your performance budgets. 59 00:03:32,540 --> 00:03:35,914 But the results are well worth the tradeoff, in my opinion. 60 00:03:35,914 --> 00:03:40,364 For example, if you have larger images that are further down the page or 61 00:03:40,364 --> 00:03:44,520 possibly a large number of smaller images or product thumbnails, 62 00:03:44,520 --> 00:03:48,027 this could easily amount to a few 100k of image data. 63 00:03:48,027 --> 00:03:52,773 If you can delay the downloading of 600k of data in place of a 5k library, 64 00:03:52,773 --> 00:03:55,990 I think you're in a far better place. 65 00:03:55,990 --> 00:04:00,510 Looking at the library itself, we see that there are a good handful of options to 66 00:04:00,510 --> 00:04:05,470 choose from for how you may want to include your images within the HTML. 67 00:04:05,470 --> 00:04:08,420 Let's look at an example here to see how this works and 68 00:04:08,420 --> 00:04:10,950 how this can really impact your load time. 69 00:04:10,950 --> 00:04:15,420 In this first example, I'm loading all of the assets as you normally would using 70 00:04:15,420 --> 00:04:19,460 the standard image element with the source attribute. 71 00:04:19,460 --> 00:04:23,850 When we load this into the browser just with these 20 assets, 72 00:04:23,850 --> 00:04:26,200 we are downloading 1.3 MEG of data. 73 00:04:27,300 --> 00:04:29,360 This by itself is not so bad. 74 00:04:29,360 --> 00:04:33,624 But also consider that we are not doing anything else other than 75 00:04:33,624 --> 00:04:35,483 downloading 20 images. 76 00:04:35,483 --> 00:04:38,364 To make use of Lazy Load, in this example, 77 00:04:38,364 --> 00:04:43,664 we can simply add the reference to the minified JS file from the Lazy Load repo. 78 00:04:43,664 --> 00:04:48,620 Of course, you can add this library in any way you see fit within your project. 79 00:04:48,620 --> 00:04:50,215 Once the library's referenced, 80 00:04:50,215 --> 00:04:53,660 we do need to create a new object from the LazyLoad constructor. 81 00:04:53,660 --> 00:04:56,560 We need to do this within the body tag of our view file. 82 00:04:57,990 --> 00:05:02,580 Now let's replace all the source attributes with data original. 83 00:05:02,580 --> 00:05:05,220 This keeps the images from loading in the first place, and 84 00:05:05,220 --> 00:05:09,900 is the hook LazyLoad uses to take the value from data original, and 85 00:05:09,900 --> 00:05:13,120 move it to the source attribute when triggered. 86 00:05:13,120 --> 00:05:17,480 When we now run this in the browser, we see that we are only downloading the first 87 00:05:17,480 --> 00:05:22,270 two images and the JavaScript file, which amounts to about 196k. 88 00:05:22,270 --> 00:05:24,320 That's a huge savings from 1.3 mg. 89 00:05:25,620 --> 00:05:30,307 This example illustrates how a user will still eventually download all of 90 00:05:30,307 --> 00:05:33,039 the images if they scroll all the way down. 91 00:05:33,039 --> 00:05:37,960 But initially we saved over 1 mg in our initial load performance budget. 92 00:05:37,960 --> 00:05:42,330 One last thing I wanted to illustrate is a simple configuration to allow for 93 00:05:42,330 --> 00:05:46,940 some additional preload time if you are loading larger images. 94 00:05:46,940 --> 00:05:49,780 In this group tag where we created the LazyLoad object, 95 00:05:49,780 --> 00:05:52,990 we can redefine this by increasing the threshold height for 96 00:05:52,990 --> 00:05:56,270 when the images are requested by the scrolling event. 97 00:05:56,270 --> 00:06:00,220 This way, the trigger's further away from the actual scroll position, 98 00:06:00,220 --> 00:06:03,690 thus fetching the asset well before you scroll to it. 99 00:06:03,690 --> 00:06:09,600 It ups our inital load to 269k but that's not a deal-breaker in my opinion. 100 00:06:09,600 --> 00:06:14,830 Lazy loading images is a great way to load all of the assets you want, but really 101 00:06:14,830 --> 00:06:18,680 keep that inital load time down and really increase your perceived performance.