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.

Visualising the Device Pixel Ratio

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"

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? 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 (or 600w)
  • 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 = 1
  • wider.jpg : DPR = 1200/600 = 2
  • widest.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.