eeeps / content-dpr-explainer

An explainer for the `Content-DPR` response header
1 stars 3 forks source link

👉 Note: this proposal has been superseded by EXIF-based intrinsic sizing


Content-DPR explainer

By default, browsers display images at their “density-corrected intrinsic size”. An 800×600, 1x image will display at 800×600 CSS px. A 1600×1200, 2x image will also display at 800×600 CSS px. Even though the two images have different resource dimensions, as far as layout is concerned, they are identically-sized.

The Content-DPR response header gives servers control over the density part of that equation, allowing them to serve arbitrarily-scaled responses without affecting (and breaking) layouts.

Example

Let’s say a server sends 400x300.jpg with the following header:

Content-DPR: 0.5

This instructs the user agent to give the image an intrinsic density of 0.5x. Thus, the image will have a density-corrected intrinsic size of 800×600 CSS px, no matter what markup or CSS delivers it.

Why?

Content-DPR was invented in conjunction with the DPR Viewport-Width, and Width client hints, so that servers could respond to these hints without breaking layouts, performing device-pixel-ratio-based selection, viewport-size-based selection, and resolution-based selection on the server-side.

Notably, the header solves other important use cases, all on its own.

But first—

The client hints use case

Let’s say a page author has chosen to craft a variable-device-pixel-ratio responsive image, with srcset.

Their markup might look like this:

<img
    src="https://github.com/eeeps/content-dpr-explainer/raw/master/small.jpg"
    srcset="medium.jpg 2x,
            large.jpg  3x"
    alt="A DPR-responsive JPEG"
/>

No matter which resource the browser selects, the density-corrected intrinsic size of the <img> will always be the same.

Here’s the equivalent client hints markup:

<img
    src="https://github.com/eeeps/content-dpr-explainer/raw/master/client-hints.jpg"
    alt="A DPR-responsive JPEG"
/>

Let’s say this request goes out from a 2.6x device, with the following hint:

DPR: 2.6

But the server only has 1x, 2x, and 3x versions readily available. Reasonably, it responds with the 2x version, along with the following header:

Content-DPR: 2

This ensures that, when the image arrives, the client knows its density, and it is given proper, consistent, density-corrected intrinsic dimensions.

Other use cases

But even in browsers that don’t implement the Width, DPR, and Viewport-Width request hints, support for the Content-DPR response header would open up new opportunities for servers (and CDNs) to perform image optimization via resizing, without risking breaking layouts that rely on images’ default (intrinsic) size.

For example:

Capping useful resolution

If a server receives a request for a very-large image, from a user agent that it knows does not have enough device pixels to take advantage of all of that resolution, it might reasonably choose to send a smaller version of the image. Currently, there is no way to do that without affecting the image’s intrinsic dimensions, potentially breaking layouts. Content-DPR would solve this.

Prioritizing speed over quality

If the server has been given some signal that the user is in a constrained-bandwidth context (perhaps an explicit signal, like Save-Data: on, or, perhaps an inferred one, based on measurements of previous response deliveries), it might want to respond with a down-scaled, low-resolution image. Again, this is impossible without either risking breaking some layouts, or universal support for Content-DPR.

Low-quality image placeholders

Authors commonly serve up low-quality versions of images as placeholders, so that something is visible immediately, even if the full image load has been intentionally deferred (via lazy-loading), or is simply slow.

Right now, these techniques require some work on the front end to ensure that the downscaled placeholder is stretched to match the final dimensions of the full image. Content-DPR would allow servers to implement foolproof features that could respond to requests, for, say,

https://give.me/the-img.jpg?placeholder=true

with downscaled images that behaved just like their full-scale counterparts, as far as layout is concerned.

Small adjustments

Rescaling by small amounts (especially when rescaling pixel-perfected or pallete-optimized images) is often a terrible choice, as anti-aliasing blurs edges and introduces many new colors. If a server is asked to produce a 895-pixel wide version of a 900-pixel-wide original, it is in everyone's best interest for the server to deliver the original, unmodified 900-pixel-wide-image, and tell the browser just to treat it as if it's 909-pixels wide by rescaling on the client.

Simmilarly, some image formats (e.g., JPEG) encode images in "blocks," and perform more efficently when image dimensions align to block-boundaries. When cropping or rescaling to arbitrary targets, it would be nice for servers to be able to send an image whose dimensions are aligned to block boundaries – and then tell the browser to slightly scale the image up-or-down on the client side.