---
title: 'Better responsive images with srcset and sizes attributes'
date: '2022-10-25'
tags: ['responsive', 'image', 'srcset', 'sizes', 'html', 'attributes']
summary: 'A guide to using the srcset and sizes attributes to create responsive images'
images:
  [
    '/static/images/banners/brown-wooden-house-on-green-grass-field-near-green-mountains-during-daytime__dangcong__TMa0l7fdSW8.jpeg',
  ]
authors: ['default']
---

## Introduction

`srcset` and `sizes` are two HTML attributes that can be used to create responsive images.
They are used to specify the image source and the size of the image. They are used together to create images that are optimized for the device they are being displayed on.

In this article, I will not be going into the details of how responsive images work. I will be focusing on how to use the `srcset` and `sizes` attributes.

Let's take a look at the basic `img` element:

```html
<img src="image.jpg" alt="image" />
```

The `src` attribute is used to specify the image source.
Web browsers will download the image and display it in all devices with the same size
no matter what the device's screen size, pixel density, or viewport size is.

So if you have a `2000px` wide image, it will be displayed as a `2000px` wide image on a 4K monitor - which is fine,
but it will also be downloaded and displayed as a `2000px` wide image on a `320px` wide mobile phone screen - of course, it will fit the screen,
but it's unnecessarily large and will take a long time to download.

That's where the `srcset` and `sizes` attributes come in.
We will use them to provide different image sources/sizes for different devices and let the browser decide which image to download and display.

```html showLineNumbers
<img
  src="image.jpg"
  srcset="image-320.jpg 320w, image-640.jpg 640w, image-1280.jpg 1280w"
  sizes="(max-width: 320px) 280px, (max-width: 640px) 640px, 1280px"
  alt="image"
/>
```

The `srcset` and `sizes` values look a bit complicated (and easy to forget <Twemoji emoji="face-with-rolling-eyes" />), but they are not that hard to understand.

## srcset

The `srcset` attribute is used to specify the image sources and their sizes.
The image sources are separated by **commas**, and each image source is followed by its size in pixels with the following parts:

1. `image-source` - the image's URL (e.g. `image-320.jpg`)
2. A **space**
3. `image-size` - the image's **intrinsic size** in pixels (e.g. `320w`) - notice the `w` at the end of the size instead of `px` to indicate that the size is in pixels.

In the example above, we have three image sources: `image-320.jpg`, `image-640.jpg`, and `image-1280.jpg`.

- The first image source is `image-320.jpg` and it's `320px` wide.
- The second image source is `image-640.jpg` and it's `640px` wide.
- The third image source is `image-1280.jpg` and it's `1280px` wide.

So now we have a set of images with different sizes, but how do we tell the browser which image to use <Twemoji emoji="thinking-face" />?

Here comes the `sizes` attribute.

## sizes

The `sizes` attribute defines a set of media conditions and help the browser decide which image to use when the conditions are met.

Each size is separated by **commas**, and being constructed with the following parts:

1. A **media condition** - a set of media features and values that define the condition (e.g. `(max-width: 320px)`).
   Notice that the condition is wrapped in parentheses, like a css media query.
   In this case, the condition is that the viewport's width is _less than or equal to `320px`_.
2. A **space**
3. A **size** - the size of the image to use when the condition is met (e.g. `280px`).

And here are the steps of how the browser decides which image to use:

1. Looks at the device's screen size.
2. Looks at the `sizes` attribute and finds the first condition that matches the device's screen size.
3. Uses the size defined in the condition to find the image source with the same size in the `srcset` attribute, if there isn't one, it will use the first image that is larger than the size defined in the condition.
4. Load the image and display it.

And that's it, we have created a responsive image <Twemoji emoji="partying-face" />.

Take a look at the example above, let's say we are on a mobile phone with a screen size of `400px` wide.

- The first condition match that screen is `(max-width: 640px)`.
- The size defined in the condition is `640px`.
- The image source with the same size in the `srcset` attribute is `image-640.jpg`.
- The browser will load the image and display it.

## Beyond the basics

- For the `sizes` attribute, you can use `vw` instead of `px` to define the size.
  This is useful when you want to use the viewport width as the size.
  For example, if you want to use the viewport width as the size, you can use `100vw` as the size.

- Combine `srcset` & `sizes` with `loading="lazy"` to improve performance.
  When the `loading` attribute is set to `lazy`, the browser will not load the image until it is visible in the viewport.
  This is useful when you have a lot of images on the page and you want to improve the page's performance.

- Better add `width` and `height` attributes to the `img` element.
  When the `width` and `height` attributes are added to the `img` element, the browser will reserve the space for the image before it is loaded.
  This is useful to prevent layout shifts and improve the experience to your visitors.

- And don't forget to add a fallback image with the `src` attribute.
  When the browser doesn't support the `srcset` and `sizes` attributes, it will use the image source defined in the `src` attribute.

At the end, the `img` element should look like this:

```html showLineNumbers
<img
  src="image.jpg"
  srcset="image-320.jpg 320w, image-640.jpg 640w, image-1280.jpg 1280w"
  sizes="(max-width: 320px) 280px, (max-width: 640px) 640px, 1280px"
  loading="lazy"
  alt="image alt text"
  width="1280"
  height="720"
/>
```

Happy coding <Twemoji emoji="clinking-beer-mugs" />.
