From the fundamentals
The viewport of a device is the size of the screen area. This doesn’t include the space the browser window takes up with its menu, bookmarks etc.
Different devices have different viewport sizes. Laptops and monitors have larger viewports than smartphones do.
A website will display on the viewport of the device. This is where HTML and CSS code is displayed.
Web developers use CSS to style and position elements. There are many units they can choose from. One of these units is called the CSS pixel, or
Each viewport is some number of CSS pixels wide and high. A smartphone viewpoint might be 320 x 568 CSS pixels. A larger smartphoen might have a viewport of 360 x 640 CSS pixels. A laptop viewport will be much bigger.
The screen of each device is made up of physical square pixels. This pixel is different from a CSS pixel.
There isn’t a one-to-one mapping between CSS pixels and device pixels. Some devices use four smaller pixels to one CSS pixel, arranged in a 2x2 grid. Some use one, and some use nine (3x3 grid). There can even be a fractional ratio between the two, like 1.5 or 2.25.
The number of device pixels that make up a CSS pixel in one direction is its Device Pixel Ratio (DPR). You can interpret this as the width (or height) of the grid of device pixels that fit inside one CSS pixel.
Every device has a different DPR. Higher resolution devices have a higher DPR. These devices can see sharper images because they devote more screen pixels to each CSS pixels. This means nuances in the image are better represented.
As a developer, it makes sense that you want to know the DPR of each device that views your webpage. If the device has a high DPR, you can serve it a big, high resolution image. If the device has a low DPR, you can serve it a smaller image.
You wouldn’t serve a high resolution image to a device with low DPR. It’d be wasted kilobytes because the screen can’t render all the detail properly.
DPR applies in two situations: for a device, and for an image. This can be confusing.
Let’s stop and think: what is DPR really measuring?
- For a device: the ratio of how many device pixels fit into each CSS pixel
- For an image: the ratio of how many image pixels fit into each CSS pixel
Looks like there’s a one-to-one mapping between device pixels and image pixels. They’re measuring the same thing in both cases.
How do I choose what image to serve?
srcset. Look at this code:
<img srcset="hd.jpg 2x, sd.jpg 1.5x" src="base.jpg">
This gives the browser three images to choose between. It suggests to use
hd.jpg for devices with a DPR close to 2, because that image has
2x next to it. For devices with DPR around 1.5,
sd.jpg will be suggested. The backup image is
base.jpg and is suggested for devices with DPR around 1.
How do I know what multiple of x to use?
Notice above that somebody has written in
2x next to the different images. It would help to know how to choose this number for an image.
Your multiple depends on
- the viewport size (in CSS pixels, or
- the DPR of the device
Say you have a viewport that is 600
px wide, and you have the following images to use:
orig.jpgwith width of 600 (or
wider.jpgwith width of 1200 (
widest.jpgwith width of 2000 (
The DPR is the ratio of the picture width to the viewport width. It’s calcuated like this:
(picture width) / (viewport width)
orig.jpg: DPR = 600⁄600 = 1
wider.jpg: DPR = 1200⁄600 = 2
widest.jpg: DPR = 2000⁄600 = 3.33
So you would put
1x next to
2x next to
3.33x next to
Here’s how I understand it.
Firstly, higher resolution devices have more pixels available to display the image.
Let’s say there were two devices that were 4 inches wide. Device 1 can fit 2000 pixels in that space, and device 2 can only fit 1000.
Device 1 is 2000 pixels wide, so it could display the image with width
2000w perfectly. But device 2 is 1000 pixels wide, so it can’t display this image perfectly. It would have to “average out” the colour values of some pixels. There’s no point serving this device with the
2000w image: it’s just unnecessary data downloading. You’d give it a smaller image.
Device 2 would even struggle with the image with width
1200w. It would still have to average out some pixels. But it’s a lot better than the
2000w image, and a lot smaller too.
Remember, the CSS pixel is just a unit of measurement, like
in. It doesn’t correspond to any physical pixels. This means that even if a viewport is
600px wide, it doesn’t mean the image is represented by 600 physical pixels on the device. Neither is the scaled down to 600 pixels and then scaled back up. The
px unit is just a unit of length.