Understanding the Device Pixel Ratio
From the fundamentals Link to heading
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 px
.
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.
Interpreting DPR Link to heading
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? Link to heading
You use 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.
Great.
How do I know what multiple of x to use? Link to heading
Notice above that somebody has written in 1.5x
and 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
px
) - the DPR of the device
Say you have a viewport that is 600 px
wide, and you have the following images to use:
orig.jpg
with width of 600 (or600w
)wider.jpg
with width of 1200 (1200w
)widest.jpg
with width of 2000 (2000w
)
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 = 1wider.jpg
: DPR = 1200/600 = 2widest.jpg
: DPR = 2000/600 = 3.33
So you would put 1x
next to orig.jpg
, 2x
next to wider.jpg
, and 3.33x
next to widest.jpg
.
I’m lost. Link to heading
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 pt
, or mm
, or 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.