TL;DR
If you as a web developer need to make images responsive to screen widths and device pixel ratios on your own, take this 6-step procedure:
Step 1: Figure out the maximum width of each image required by the design of your webpage. Let’s say, it is 624px
.
Step 2: Convert the original image file into two versions: one with the maximum width (624px
in our example) and the other with double the maximum width (1248px
). Image resizing can easily be done with tools like sips
, a command line tool of MacOS.
Step 3: Refer to these two image files with the following temporary <img>
element:
<img
sizes="100vw"
srcset="image1248.png 1248w"
src="image624.png"
/>
Step 4: Render the webpage with your favorite browser and click the RespImageLint bookmarklet. It gives you the correct value for the sizes
attribute and the widths of additional image files needed to minimize the loading time across all screen types.
Step 5: Revise the HTML code by incorporating RespImageLint’s suggestions. In our example, it is something like:
<img
sizes="
(max-width: 600px) calc(100vw - 70px),
(max-width: 766px) calc(100vw - 141.25px),
624px
"
srcset="
image624.png 624w,
image990.png 990w,
image1248.png 1248w
"
src="image624.png"
/>
Step 6: Convert the original image file into the ones suggested by RespImageLint, again using tools like the sips
command line tool of MacOS. Then save them as indicated in the HTML code written in Step 5.
Below I elaborate on each step, after a brief explanation of why I’m writing this article.
Why writing this article?
[Feel free to skip this section: all the sections below are independent of what is written in this section]
Putting images on a webpage is hard. “[T]here are … 927 things you could (and some you really should) do that often go overlooked”, wrote Chris Coiyer (2021).
In particular, implementing responsive images is really complicated. You have to think about various screen widths and device pixel ratios in order to decide which widths of each image to prepare for minimizing the loading time.
While many services out there help you automate the generation of responsive image files and the associated HTML code, what if you have to do it all yourself?
I was recently in such a situation. I tried to find the easy-to-follow procedure of making images responsive with the minimum amount of effort. This article reports what I have arrived at.
There are many articles on responsive images across the web. But, as far as I know, they are all too lengthy, not very helpful for a quick DIY implementation. The closest to this article in spirit is Archibald (2021), which proposes “the lazy way” of implementing responsive images. This article intends to improve this “lazy” approach.
Step 1: Maximum image width
The original image files are most likely to be a lot larger than the size required by the design of your webpage. So the first step is to figure out how large each image file needs to be given the design of your website.
The maximum width of images is usually given by the design for desktop screens. But not necessarily. In the example given by Archibald (2021), it is when the screen width is 799px beyond which the images are shrunk to leave side margins.
For the ease of exposition below, let’s say our website design requires the images that are 624px wide at most.
Step 2: Image file conversion (Part I)
The second step towards responsive images is to convert the original image file into two versions of it: one with the maximum width (624px in our example) and the other with double the maximum width (1248px in our example).
The former is for non-retina screens (1x) while the latter is for retina screens (2x), when the user’s screen width requires the maximum image width identified in Step 1.
Enough to deal with 2x screens only
You might ask, “What about those device pixel ratios (DPR) other than 2x?” As far as I understand, we can ignore them. Here’s why.
Osmani (2021) argues that “[t]he human eye may not be capable of distinguishing the difference between images that are a 2x-3x DPR vs. an even higher resolution.”
He also reports:
Twitter capped their image fidelity at 2x, resulting in 33% faster timeline image loading times. They found that 2x was a sweet spot of both good performance wins with no degradation in quality metrics.
For more on this approach adopted by Twitter, see O'Brien (2019).
So we just need to care about 2x screens, even though higher resolution screens are widely available in the market today.
Image resizing tools
Now the question is how to resize your original images. According to Hempenius (2018):
Two of the most popular image resizing tools are the sharp npm package and the ImageMagick CLI tool.
If you are a Mac user, there is a third alternative: sips
, which I find very easy to use. Dachis (2012) explains how to resize image files in a batch by using this command line tool installed in Mac OS by default. Following this article, you can do the following:
Make copies of your original image files and save them in a new folder.
In Terminal, moving to this folder with the
cd
command. Then execute the following command:
sips -Z 1248 *.png
which overwrites the original image files and resizes them to the width of 1248px (if the width is larger than the height) without distorting their aspect ratio.
If the height of an image is larger than its width, use the following command instead:
sips --resampleWidth 1248 *.png
This is what I have figured out by reading the documentation of sips
.
Step 3: Draft HTML code
Now write down a draft of the HTML code to embed each image:
<img
sizes="100vw"
srcset="image1248.png 1248w"
src="image624.png"
/>
Temporary sizes
value
The value for sizes
is temporary. It’s not easy to figure out the correct value for your webpage design (see Coyier 2020). It’s best to rely on an external tool that does all the hard job. That’s for Step 4 below.
Go with w
descriptor, not x
descriptor
The value for srcset
is also temporary, just including the largest image file at this moment.
Note that I use the w
descriptor. As far as I can see, the consensus among web developers is to use w
, not x
, for responsive images. Accoridng to Coyier (2020):
...
x
descriptors only account for a small percentage of responsive images usage. Why? They only let browsers adapt based on one thing: display pixel-density. A lot of times, though, our responsive images are on responsive layouts, and the image’s layout size is shrinking and stretching right along with the viewport. In those situations, the browser needs to make decisions based on two things: the pixel-density of the screen, and the layout size of the image. That’s wherew
descriptors and thesizes
attribute come in ...
Use src
for a fallback image file
Finally, the src
attribute refers to a fallback image file in case the user’s browser does not support sizes
or srcset
attributes.
In which width should the fallback image file be? I cannot find any tip on this (please post a comment if you know any). My own reasoning concludes that the 1x screen version of the maximum width (624px in our example) is good enough. Here's why:
The legacy browser that does not support sizes or srcset is likely to come with either the 1x desktop screen or the 320px-wide 2x screens of iPhone 4 and iPhone 5.
- The first 2x screen was released with iPhone 4 on June 24, 2010 (source: Wikipedia).
- The iOS Safari first supported
sizes
andsrcset
with its version 9, released on September 16, 2015 (source: Can I Use?). That was when iPhone 6 was released (source: Wikipedia). - The screen width of iPhone 4 and iPhone 5 is 320px (source: Wikipedia).
Consequently, the fallback image file should cater to iPhone 4 and iPhone 5’s 320px wide screens, which require an image width of 640px at most.
If the maximum image width is less than 640px, you may want to use a 640px-wide version as a fallback. Otherwise, the maximum image width is sufficient.
How sizes
and srcset
work
If you need to brush up your understanding of how sizes
and srcset
attributes work in tandem, I recommend Portis (2018) and Google Developers (undated), both of which clearly explain how browsers choose which image file to use based on the information given by the sizes
and srcset
attributes.
Step 4: RespImageLint
The fourth step is to obtain the optimal values for sizes
and srcset
attributes with the help of RespImageLint, a bookmarklet developed by Martin Auswöger.
Coyier (2020) explains what RespImageLint does succinctly:
Martin Auswöger’s RespImageLint ... programmatically resizes the page a bunch and writes out a
sizes
attribute that describes the actual, observed width of the image over a wide range of viewport sizes. It’s computers, doing math, so it’s right. So, if you want a super-accurate sizes attribute, I’d recommend just putting a wrong one on at first, running this tool, and copying out the correct one.
Plus, RespImageLint gives us the recommended value for srcset
.
Given these suggested values, we can now revise the HTML code written earlier in Step 3.
Step 5: Revise HTML code
In our example, RespImageLint suggests the following:
<img
sizes="
(max-width: 600px) calc(100vw - 70px),
(max-width: 766px) calc(100vw - 141.25px),
624px
"
srcset="
image624.png 624w,
image990.png 990w,
image1248.png 1248w
"
src="image624.png"
/>
See the value of sizes
. To get it right on your own, you have to go through the entire CSS style sheets back and forth. It’s best to rely on the automation provided by RespImageLint.
For srcset
, RespImageLint suggests the image widths of not only 624px and 1248px but also 990px. This additional image targets 2x mobile screens in the range of widths between...(let me do the math for you)...382px and 565px. Without this image file, these mobile devices would have to download the 1248px image whose file size is way bigger than necessary.
Step 6: Image file conversion (Part II)
The last thing we need to do is to convert the original image file into those suggested by RespImageLint and match the file paths for the converted images with the ones specified in the HTML code written in Step 5.
Now you are done for responsive images!
But there are a few other things to do for images. For a reminder, see the list in Coyier (2021).
In particular, the above HTML code for <img>
misses the alt
attribute. I once spent the whole day to figure out how to write the alt
text properly. See my blog post, Kudamatsu (2021), for what I have learned.
Changelog
Oct 1, 2023 (v1.1.0): Add a paragraph on resizing an image file with sips when the image's width is shorter than its height.
References
Archibald, Jake (2021) “Halve the size of images by optimising for high density displays”, jakearchibald.com, Jun 11, 2021.
Coyier, Chris (2020) “A Guide to the Responsive Images Syntax in HTML”, CSS-Tricks, May 26, 2020.
Coyier, Chris (2021) “Images are hard.”, CSS-Tricks, May 26, 2020.
Dachis, Adam (2012) “Batch Resize Images Quickly in the OS X Terminal”, Lifehacker, Nov 21, 2012.
Google Developers (undated) “Learn Images! — Descriptive syntaxes”, web.dev, undated.
Hempenius, Katie (2018) “Serve responsive images”, web.dev, Nov 5, 2018.
Kudamatsu, Masa (2021) “Mastering the art of alt
text for images”, Dev Community, May 19, 2021.
O'Brien, Nolan (2019) “Capping image fidelity on ultra-high resolution devices”, Twitter Engineering, May 9, 2019.
Osmani, Addy (2021) “The Humble <img>
` Element And Core Web Vitals”, Smashing Magazine, Apr 29, 2021.
Portis, Eric (2018) “w descriptors and sizes: Under the hood”, Observable, Mar 28, 2018.
Top comments (0)