Sometimes `sizes` is quite important.

Paraphrased question from email:

I just read your article Responsive Images: If you’re just changing resolutions, use srcset. In the age of “responsive websites,” srcset does not help in certain situations. For example, I have a popular products slider. On mobile, I have one image per slide where the images are 320px wide. On desktop, I have six images per slide where each is 160px wide. So the desktop images are smaller on desktop, not bigger.

How do I handle this situation with srcset?

I tried to be careful with that post title: “If you’re just changing resolutions, use srcset.” In this case, we’re changing the size of the images not just at certain resolutions, but at specific breakpoints as well, which means we’re also going to need to use the sizes attribute to get the most out of responsive images. The entire job of the sizes attribute is to tell the browser what size the image will be shown at, as per our CSS.

A demo! Resize the width to see it alternate between the “Desktop” and “Mobile” views.

See the Pen Responsive Images Slider by Chris Coyier (@chriscoyier) on CodePen.

As the email mentioned, the “Desktop” version actually renders the images smaller (160px) than the “Mobile” version (320px).

Let’s also account for 2x displays. To prepare ourselves, let’s have three versions of each image:

  • 160px (for 1x desktop displays)
  • 320px (for 2x desktop displays, or 1x mobile displays)
  • 640px (for 2x mobile displays)

With srcset, that looks like this:

<img srcset=" food-big.jpg 640w, foot-medium.jpg 320w, food-small.jpg 160w"
/>

Notice we’re not yet using the sizes attribute. Browsers will assume you’re probably going to render this image at 100vw wide. That’s unfortunate because the browser may download a larger image than it needs, which is what we’re trying to fight against with responsive images in the first place.

On my 2x desktop display, I can tell it’s downloading the 640px version, but it really only needs the 320px version.

It’s our CSS that controls how big these images render. In fact, we have a media query in this demo that says, “Hey browser, only render the images at 160px wide on Desktop displays.”

@media (min-width: 600px) { .slider img { width: 160px; }
}

You’d think the browser would know that, and it does — it just needs to download and parse the CSS first. The browser wants to make a decision about what to download faster than that. So, let’s tell it with the sizes attribute.

<img srcset=" food-big.jpg 640w, foot-medium.jpg 320w, food-small.jpg 160w" sizes="(min-width: 600px) 160px, 320px"
/>

That’s saying, “OK, we’ll be rendering this image 160px wide on Desktop. Otherwise, let’s go with 320px wide.” With that in place, we can see the browser is making the right choice:

The browser is now only choosing to download the 320px version, which is correct on a 2x display where the images are being rendered at 160px.

And just to be sure, here’s a narrow viewport (like “mobile” would be):

We’re back to downloading the 640px version, which is correct, since at this viewport size, the sizes attribute is telling the browser we intend to render at 320px and we’re on a 2x display.

There is even more nuance here

I showed this demo to Eric “Sizes Master” Portis, who confirmed all this, but had some browser-specific things to add. I’ll summarize (but note the date of this blog post because these things tend to change):

  • Firefox does exactly as described above.
  • Chrome does too, except that it will always use the larger version if it has that version in cache. So, if it has a 640px version in cache, it knows it really only needs a 320px version, but since it doesn’t have a 320px version in cache, it’ll use the 640px version instead.
  • Safari does too, except that after it has made its choice, it never changes (like if you resize the browser window).
  • An interesting part about srcset is that the spec allows it to make choices however it wants, perhaps using stuff like network conditions to decide. Most browsers don’t do anything like this yet, except Chrome which downloads the smallest resource should it get a Save-Data header on the HTML document.
  • Joe McGill also noted: “For older iOS devices that don’t support w descriptors in srcset, the first source item in the list will be used, so you may want to lead with your preferred default size if you’re supporting legacy iOS devices.” In other words, those older iOS devices may have supported earlier syntaxes of responsive images, but only with x descriptor (like big-image.jpg 2x), so perhaps specify a good default image as the first in your srcset.

It might be helpful to look at Eric’s fork to more easily see what gets downloaded:

See the Pen Responsive Images Slider by Eric Portis (@eeeps) on CodePen.

Random notes

  • I snagged those food photos from Unsplash.
  • I uploaded them to Cloudinary so that I could use URL params to resize them instead of having to deal with that myself.
  • They are all squares, not because I downloaded them like that, but because I sized them that way in CSS and prevented squishing with object-fit. That means image data is being downloaded that isn’t needed, so I either should have cropped them myself or used Cloudinary URL params to do that.
  • I used the Pug HTML preprocessor for my demo just to reduce code repetition.

This is easier to look at:

img(srcset=` ${img_base}w_640${img_1} 640w, ${img_base}w_320${img_1} 320w, ${img_base}w_160${img_1} 160w,
` sizes=sizes)

…than the output:

<img srcset=" https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 640w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 320w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/><img srcset=" https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 640w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 320w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/><img srcset=" https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 640w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 320w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/>

The post Sometimes `sizes` is quite important. appeared first on CSS-Tricks.

The Four Big Ways Jetpack Helps with Image Performance

We’ve been working with Jetpack around here as a sponsor. It’s a great match because as someone with a bunch of self-hosted WordPress sites, Jetpack is one of those no-brainer plugins for me. Jetpack can do a ton of good things for any site in a variety of very different ways. Here’s one way to think about it: it brings the power of WordPress’ own massive servers to you.

For now, let’s just focus on one angle of what Jetpack can do for you: image performance. Jetpack does a ton for you in this regard, solving some non-trivial performance upgrades. Let’s take a look at what I see as the four big boosts you get from Jetpack on your images.

1) WordPress does responsive images for you

OK, I cheated with the first one because you don’t actually need Jetpack to benefit from this. But it’s an important and foundational concept for fast images. Just by using WordPress, you get basic responsive images for free.

If you already know what I’m talking about, here’s an example of the output you’ll see in the DOM of a published WordPress post with an image in it uploaded via the Media Uploader:

It’s wonderful to get this for free, as writing out responsive images syntax by hand is quite cumbersome.

If you are new to the idea of responsive images, the big idea is this: rather than a single image going to any browser visiting your website, you have multiple images in different sizes and the most-correct one is delivered. Imagine instead of a mobile phone downloading a 1600 pixel wide image (way bigger than it needs), it only downloads a 320-pixel wide image, saving a ton of downloading time.

We’ve written lots about responsive images over the years.

2) You get a CDN

Read a bit about web performance and you’ll be unanimously told: “use a CDN.” A CDN is a Content Delivery Network, essentially web servers designed specifically to make serving assets like images super fast. They call it a network because it isn’t just one server, it’s many servers physically located all over the world so that when your website is requested from different locations all around the world, the files being sent back come from geographically closer locations (faster!). Not to mention it does other clever things like not requiring cookies for each web request like your own server probably does.

Literally, flip a switch in Jetpack and you’ll be using an image CDN:

It’s called Photon.

Site speed is impacted by many factors and one of them is content delivery. Using what is referred to as a content delivery network (or CDN) helps by:

  • Delivering your content from high-speed and dedicated data centers.
  • More files can be downloaded simultaneously by the browser.
  • Distributed data centers (ie in different geographic locations) improve download speeds and provide redundancy.
  • By distributing load and save bandwidth you reduce your existing hosting costs (or keep them in check).

3) You get optimization

Una Kravets calls image optimization an easy performance win for designers. It’s an easy thing to see. Try taking a screenshot of something, exporting something from Photoshop, or grabbing some stock photography. Then drop it onto a tool like ImageOptim and watch the bytes fall away as it optimizes it. Massive savings.

But wouldn’t it be nice if it wasn’t on you to manually optimize all your images before using them? Computers are supposed to help us with menial tasks, right?! When you flip on the CDN feature of Jetpack, your images are now hosted on Photon, and you can see in the Photon docs how it handles things like resizing and quality for you.

4) You get lazy loading

Lazy loading is the idea that you don’t load anything at all unless you need it. In the case of images, don’t download the image unless it’s visible on the page. As in, don’t download an image that is three quarter down an article that a user might never scroll down to, but if they do, then download it.

You know what they say, the fastest web request is one that is never made. Jeremy Wagner, for Google, says:

When we lazy load images and video, we reduce initial page load time, initial page weight, and system resource usage, all of which have positive impacts on performance.

This is another flip-a-switch feature that works on any theme. Turn it on, you got lazy loading.

All Together Now

  1. You get responsive images with WordPress, which by itself can be a major performance win.
  2. With Jetpack, those responsive images are CDN-hosted, providing a speed boost and great caching for the images that are downloaded.
  3. Just because you’re using responsive images and a CDN doesn’t automatically mean those images are optimized, but they are on Photon.
  4. Last, nothing is downloaded at all unless the images are in view (lazy loading), which is the most efficient thing you can do.

Pretty compelling.

The post The Four Big Ways Jetpack Helps with Image Performance appeared first on CSS-Tricks.

Fallbacks for Videos-as-Images

Safari 11.1 shipped a strange-but-very-useful feature: the ability to use a video source in the <img> tag. The idea is it does the same job as a GIF (silent, autoplaying, repeating), but with big performance gains. How big? “20x faster and decode 7x faster than the GIF equivalent,” says Colin Bendell.

Not all browsers support this so, to do a fallback, the <picture> element is ready. Bruce Lawson shows how easy it can be:

<picture> <source type="video/mp4" srcset="adorable-cat.mp4"> <!-- perhaps even an animated WebP fallback here as well --> <img src="adorable-cat.gif" alt="adorable cat tears throat out of owner and eats his eyeballs">
</picture>

Šime Vidas notes you get wider browser support by using the <video> tag:

<video src="https://media.giphy.com/media/klIaoXlnH9TMY/giphy.mp4" muted autoplay loop playsinline></video>

But as Bendell noted, the performance benefits aren’t there with video, notably the fact that video isn’t helped out by the preloader. Sadly, <video> it is for now, as:

there is this nasty WebKit bug in Safari that causes the preloader to download the first <source> regardless of the mimetype declaration. The main DOM loader realizes the error and selects the correct one. However, the damage will be done. The preloader squanders its opportunity to download the image early and on top of that, downloads the wrong version wasting bytes. The good news is that I’ve patched this bug and it should land in Safari TP 45.

In short, using the <picture> and <source type> for mime-type selection is not advisable until the next version of Safari reaches the 90%+ of the user base.

Still, eventually, it’ll be quite useful.


Fallbacks for Videos-as-Images is a post from CSS-Tricks