Dear Ms. FEWD,
All the developers are using responsive images these days. I’ve read about <picture>, but I’ve been told that’s just for “art direction”. What should I use when it’s the same image, but it just needs to be different sizes?
Dear Size Matters,
It’s true, part of a developer’s job today is ensuring that their code renders properly across multiple devices in addition to multiple browsers.
There are several ways to go about this. To start, we need to ask what we’re doing with this image. Is it content or presentation? Is the image the same across all viewports, or does it change? If it changes, how does it change?
For a content image that will be the same size across all viewports, but needs to flex with the browser, putting the following on your image will cause it to flex within its container:
This example shows one image using the above properties, and one image using the above properties in a container that was set at 50%. Move the side of your browser in and out, and watch the image resize.
Please note, with this example only the image width flexes – the size of the file will remain the same. This can cause a load time performance issue if you’re supporting very large desktop layouts and very small mobile layouts in the same responsive site. You don’t want the image to distort or be blurry, so you’d need to start with the largest size needed. This means you are forcing your mobile user to download much larger images than needed for their device. Only use this option if there is minimal size difference between the largest size and smallest size of your image.
If you have a difference between pixel densities within the image in mobile and image in desktop, or even something as basic as using different images assets based on their screen size, using the srcset attribute may be your best bet. Srcset looks at the image and finds the best image ratio based on the device-pixel ratio. In this next example, I show several options for implementing images with srcset:
In the first three examples, I define different groupings of different width images. The w descriptor is used in these examples to define the max width of the image being called. In addition to finding the best image out of the stack for your user’s browser, you can also see that the ones that use the w descriptor are additionally configured by default to flex with the browser.
In the fourth and fifth examples, I show the x descriptor. The x descriptor defines pixel density. You can see that just using the x descriptor in the fourth example does not allow the image to flex with the size of the browser, despite it rendering the best image in the group for that browser. You can either use the w descriptor, or, as shown in the fifth example, add the CSS from the first fiddle to make the images flex within the browser.
You mentioned the picture element, and I think it’s a great thing to go over. As you state, this is only if the artistic direction changes between viewports. This means the image is totally different for each viewport (height, width, content). It may be something as simple as the text on the image is unreadable in the smaller viewport, to needing to crop the image because it takes up valuable real estate on your user’s mobile device. A good rule to go by is if anything else other than the resolution of the image changes, go ahead and use picture.
Please note, for simplicity, this image does not flex with browser resize. It will totally change src on browser resize, however. If you needed it to flex as well, you could use the CSS from the first example.
I also want to go over responsive background images, as they can be tricky. Background-size will be your friend, in some capacity, with responsive background images. In this next example group, I’ve put borders around the containers so you can compare options and see how much whitespace each option may create.
In the first example, we use background-size: cover, which simply means the background image will cover the container. The image will keep its aspect ratio. In order to preserve the aspect ratio, the image may get cropped if the height or width ends up being bigger than the container.
In the second example, we use background-size:contain. The image will keep its aspect ratio. However, because the image is contained within the container, there could be a lot of whitespace within your container around the image as the image resizes.
The third and fourth options use background-size: 100% auto. The two values here are width and height of the background image within your container. I also define a top-padding with a percent value, instead of a height. This gives the container a flexible height, and reduces the whitespace, while the background-size of 100% auto keeps the image from distorting. In the fourth option, I use a media query to change the image served when the viewport is less than 400px in width. In addition, because the ratio changes with the new image, I also updated the padding-top percentage.
When making an image responsive and to prevent performance and load issues, the size of your image matters - but how you use it counts even more.
Do you have a front end development question? Ms. FEWD has answers. Email her at MsFEWD@tahzoo.com