Some things about responsive images
Let’s start by introducing some of the HTML/CSS you’ll find when dealing with images.
The <img>
tag: The most common and probably easiest option for displaying an image. It’s a tag you’ve probably seen before.
Use the src
attribute to link to the image you’d like to show. But you can also use srcset
and sizes
to specify responsive images. More on that later.
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
The alt
attribute: Used by screen readers and web crawlers to describe the image in case it doesn’t load. Important for the accessibility of your site: screen readers will read out this text. Use a full description of the image instead of something like “image”.
The <figure>
tag: Figures are used to group accessories for an image, like captions, code blocks, tables, or video. This avoids having to wrap the picture in <div>
blocks.
How to use: wrap your element in <figure>
tags, and then optionally add the extra things, like a <figcaption>
to add a caption.
<figure>
<img src="mundane_picture.jpg" alt="Amazing picture that would amaze you if you saw it. ">
<figcaption>Change your life with this amazing picture.</figcaption>
</figure>
Note you can have multiple images in one figure.
The <pre>
tag: Stands for preformatted text; use to display the text as-is between the tags. Usually displayed in a monospaced font like Courier.
The <code>
tag: Put any code you’d like to show on your webpage between these tags.
Here is an example of some code between <figure>
tags, with a caption.
<figure>
<figcaption>Your code title</figcaption>
<pre>
<code>
<!-- your code here -->
</code>
</pre>
</figure>
The <picture>
tag. Basically serves as a decision tree for images, deciding which one to load. Doesn’t do image optimisation, that’s what <img>
does. See below.
The <source>
tag: Works with the picture
tag to let you you choose between alternate media resources (like images or music) depending on certain conditions.
Here’s a query using the width of the screen to decide what picture to load.
<picture>
<source media="(min-width: 800px)" srcset="pic-big.jpeg">
<source media="(min-width: 400px)" srcset="pic-small.jpeg">
<img src="pic-tiny.jpeg" alt="A horse dancing erratically.">
</picture>
The first source
condition that is matched will be used.
The type
attribute: This looks something like <source type="image/webp" srcset="pic.webp”>
. The purpose of this attribute is to tell the browser what kind of file is inside the source
tags.
This is useful because if browser doesn’t support the file type, it won’t download the file. Without this attribute the browser would first download the file and then see if it could use it or not. By including type
information you’ll save your users some space with downloads.
Two image problems Link to heading
There are two common problems with displaying images to users. These are called art direction and resolution switching.
The first problem is one called art direction. If a user is on a big desktop screen, or a small mobile phone, should they see the same image? Or should the mobile user see a more cropped version of the image? Images should be changed depending on what display is used.
Look at this dog below.
The large screen shows the full image, while smaller screens show more of the dog and less of the background. This makes sense because the dog is the important part of the picture. You wouldn’ t get this effect if you just scaled down the image.
How do you get this effect? Use media
queries on a <picture>
tag to specify when to load each image.
<picture>
<source media="(max-width: 799px)" srcset="doggo-closeup.jpg">
<source media="(min-width: 800px)" srcset="wide-screen-doggo.jpg">
<img src="wide-screen-doggo.jpg" alt="Dog posing in front of roses and white mansion,">
</picture>
All cropped images should be of the same underlying picture, meaning you’ll only use one <alt>
tag to describe all the images.
The second problem is resolution switching. This is when you have the same image, but at different resolutions.
Why do you need different resolutions for the same image? As always, it comes down to the user. Some browsers specify they prefer low-resolution images; perhaps to save data, or because their display is low density. Sometimes the user has a small screen and they need a smaller, non-cropped version of the original image. Or another user might have a really good new smartphone, with a very good display, and they need a high resolution image to look good on that display.
You solve the resolution switching problem by providing a number of appropiate images, so that the browser can download the optimal one for each user. But: this only works for <img>
and the srcset
and sizes
attribute. It doesn’t work for <picture>
and media
attributes, like we used to solve the art direction problem.
To summarise, art direction refers to cropping images. You’ll end up with a number of cropped versions of the same image, each used for a different screen size. Resolution switching doesn’t crop images, but has different versions of the same image, each with a different size or resolution.
Using srcset and sizes Link to heading
You may have noticed we used the <picture>
element above to choose what image to display.
There’s another method: using srcset
and sizes
. Why would you want to use this?
Quoting this answer from Stack Overflow:
The
<picture>
element (and<source>
sub-elements) are the heavy guns you bring in when you want to do art direction on different sizes / aspect ratios of the image. The imgsrcset
attribute is much more lightweight and is all you need if you want to design for different resolution displays.
Using srcset
comes in two parts. Step one is to create the images. Step two is to write the srcset
markup.
You want four sizes of each image: a base one, one 2x the size, one 3x the size, and one 4x the size. You can modify them in a few ways: cropping out bits, making the image proportionally smaller, or with more compression.
You’ll create
- image-1x.jpg
- image-2x.jpg
- image-3x.jpg
- image-4x.jpg. Either your original image, or the largest image that you want to put on your site.
Note this doesn’t apply to SVG files, since they look good independent of your browser size and resolution.
Writing srcset Link to heading
There’s two common ways you can write this.
Specifying image density: using 1x, 2x etc after your file names
<img srcset="
/image-4x.jpg 4x,
/image-3x.jpg 3x,
/image-2x.jpg 2x,
/image-1x.jpg 1x "
src="/image-1x.jpg" >
Specifying image width: write the width of each file with w
as the suffix.
<img srcset="
/image-4x.jpg 4025w,
/image-3x.jpg 3019w,
/image-2x.jpg 2013w,
/image-1x.jpg 1006w "
src="/image-1x.jpg" >
Writing sizes Link to heading
sizes
does the following:
- specifies how wide the slot for the image should be in our layout.
- specifies what images to load, based on a media condition like how wide the device is. This won’t make sense for all use cases. If you have a small image slot, you wouldn’t load a big image, even if the viewport is large.
A simple(ish) example with sizes
:
<img
sizes="100vw"
srcset="small.jpg 400w, medium.jpg 800w, large.jpg
1600w"
src="fallback.jpg"
alt="...">
The 100vw
means this image is 100% of the viewport width. Images will be bigger for laptops and smaller for smartphones.
Here’s another example (from here) with both sizes
and srcset
together:
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
sizes
works well with srcset
if you specify your images with w
at the end. What happens is that the browser figures out through sizes
how wide the slot for the image is. Then it looks at the srcset to figure out what would be the best image to load.
You can get help to write sizes
: use https://ausi.github.io/respimagelint/ or other tools.
Remember: Browsers choose their own image Link to heading
Despite all the work you put into optimising srcset
and sizes
, you aren’t commanding the browser to use an image. You are just suggesting some candidates, and the browser makes its own decision on what image to show.
Here are some factors that might influence the decision:
- the average internet speed of the current session
- the preferences of the user (e.g. data saver mode on Chrome)
- caching. If the user has a bigger image already cached, it won’t request the smaller one; it can just rescale the larger to the smaller one. If the user has a smaller image cached, the browser will request the bigger one; it won’t want to stretch the small image because it’ll look grainy.
References Link to heading
Image Performance - Mat Marquis
MDN docs on Responsive Images