1. Introduction
Existing solutions for the responsive image use cases rely on a suite of markup (picture
and srcset
) which allows authors and browsers to decide how images on the web should adapt to varying contexts, so that different users receive different resources, tailored to their particular context.
Authors know the most about the page which an image is appearing; user agents know the most about the end user’s current context and preferences. Servers, however, often know the most about the available resources, and are well-situated to make good decisions in more-scalable, easier-to-implement-and-maintain ways, via proactive content negotiation. Servers require a bit of extra information about the page and user, though, in order to make those decisions; that information may be delivered in a secure, privacy-preserving way via these client hints.
By moving this decision-making to the server, we:
-
de-couple responsive image decision making from markup. This:
- makes markup much easier to author and maintain.
- allows the responsive image decision making to evolve more easily over time.
-
move responsive image decision making to the place where the resources live. This:
- allows responsive image decision making to be informed by image content.
- allows resource generation to be informed by incoming requests.
< img src = "https://media.shoeshoppe.biz/cool-shoe-hero.jpg" sizes = "(min-width: 800px) 800px, 100vw" alt = "A cool shoe" />
...and send the following Accept-CH and Permissions-Policy response headers along with their root HTML document:
Accept-CH: Sec-CH-DPR, Sec-CH-Width Permissions-Policy: ch-dpr=(self "https://media.shoeshoppe.biz"), ch-width=(self "https://media.shoeshoppe.biz")
A user agent running on a 3x device, with a 400-px-wide viewport, then sends the following headers along with the image request:
GET https://media.shoeshoppe.biz/cool-shoe-hero.jpg Sec-CH-Width: 1200 Sec-CH-DPR: 3
media.shoeshoppe.biz
might note that cool-shoe-hero.jpg
contains photographic content, and that the apparent-quality benefits of sending a full-3x, 1200-pixel-wide version won’t outweigh the cost in increased filesize. So it sends an 800-pixel-wide, 2x response instead, and modifies the response resource’s EXIF resolution in order to ensure that resulting img
has the expected density-corrected intrinsic width of 400px.
2. Responsive Image Hints
2.1. The Sec-CH-Width
Header Field
The Sec-CH-Width
request header field gives a server the layout width of the image, in device pixels (or printed dots). It is a Structured Header whose value MUST be an integer greater than or equal to 0.
For fetches triggered by img
elements, its value SHOULD be calculated by multiplying the source set’s current source size by the Window
's current devicePixelRatio
, and taking the ceil() of the result.
It MUST NOT be sent when the user-agent is using a fallback source size. Which is to say, if an img
's current source size is 100vw
because any of the conditions in step 5 of parse a sizes attribute returned true, Sec-CH-Width
MUST NOT be sent.
Note: We should probably specify how user-agents track this state? I guess by setting a property like fallback sizes used (or whatever) on img
.
Note: the source size may be zero. Servers should plan to receive requests for images to fit zero-width layout containers, and respond as best they can; for instance, with images clamped to some minimum (greater-than-zero) width.
-
this markup:
< img src = "a.jpg" sizes = "33vw" > - a 1000-px-wide viewport, and
- a
devicePixelRatio
of 2,
...a user agent calculates the Sec-CH-Width
value to be the source size (33vw
, which in this context equals 330px
) * the devicePixelRatio
(2
), and attaches the following header to the request for a.jpg
:
Sec-CH-Width: 660
Note: do we need to talk about fetches initiated by CSS (probably)? Other sorts of fetches?
Vary: Sec-CH-Width
, this, for instance, allows the same 1000-pixel-wide cached resource to satisfy both 500px@2x and 1000px@1x requests, as both get Sec-CH-Width: 1000
in their cache key.
If servers want to know the layout width of the image in CSS px, they need both the Sec-CH-Width and Sec-CH-DPR hints: the img
's clientWidth is equal to the value of Sec-CH-Width divided by the value of Sec-CH-DPR.
Note: does this get sent when there’s no sizes
?
2.2. The Sec-CH-Viewport-Width
Header Field
The Sec-CH-Viewport-Width
request header field gives a server information about the user-agent’s current viewport width. It is a Structured Header whose value MUST be an integer greater than or equal to 0.
For fetches within web contexts, its value SHOULD be the Window
's current innerWidth
.
Note: innerWidth
(and innerHeight
) return zero when there is no viewport, which can happen when an iframe
is styled with display: none
or after a call to iframe.remove()
. Servers should plan for zero-values, and respond as best they can; for instance, in the case of image requests, with resources clamped to some minimum (greater-than-zero) size.
Note: window.innerWidth includes scrollbar width. Do we want to use the width of the initial containing block (minus any scrollbar width); gettable with document.documentElement.clientWidth
), instead?
Given:
-
this markup:
< img src = "a.jpg" > - and a
innerWidth
of 1000,
...a user agent attaches the following header to the request for a.jpg
:
Sec-CH-Viewport-Width: 1000
In the absence of any other client hints, the server does the best it can and sends back a 1000-pixel-wide response.
2.3. The Sec-CH-Viewport-Height
Header Field
The Sec-CH-Viewport-Height
request header field gives a server information about the user-agent’s current viewport height. It is a Structured Header whose value MUST be an integer greater than or equal to 0.
For fetches within web contexts, its value SHOULD be the Window
's current innerHeight
.
Note: window.innerHeight includes horizontal scrollbar width. Do we want to use the height of the initial containing block (minus any scrollbar height); gettable with document.documentElement.clientHeight
), instead?
Given:
-
this markup:
< img src = "a.jpg" > - and a
innerHeight
of 1000,
...a user agent attaches the following header to the request for a.jpg
:
Sec-CH-Viewport-Height: 1000
In the absence of any other client hints, the server does the best it can and sends back an image optimized for a 1000-pixel-tall viewport.
2.4. The Sec-CH-DPR
Header Field
The Sec-CH-DPR
request header field gives a server information about the user-agent’s current device pixel ratio. It is a Structured Header whose value MUST be an decimal greater than 0.
For fetches within web contexts, its value SHOULD be the Window
's current devicePixelRatio
.
Servers that send resources in response to requests including Sec-CH-DPR SHOULD adjust those resource’s intrinsic resolutions via metadata to ensure that, even as the resolution of the width is changing, its density-corrected intrinsic width does not.
Given:
-
this markup:
< img src = "a.jpg" > - and a
devicePixelRatio
of 2,
...a user agent attaches the following header to the request for a.jpg
:
Sec-CH-DPR: 2
The default (1x) version of a.jpg is 800x600. The server sees the Sec-CH-DPR
header and sends a 2x, 1600x1200 response. It tells the user agent to treat the returned resource as 2x by ensuring that it contains the following EXIF metadata, before the image data:
XResolution: 144 XResolutionUnit: Inch PixelXDimensions: 800 PixelYDimensions: 600
And it sends the following Vary
header along with the response, so that Sec-CH-DPR header field is added to the cache key:
Vary: Sec-CH-DPR
2.5. Integration with Fetch
This specification’s integration with Fetch is defined as part of the [client-hints-infrastructure] specification.
3. Security and Privacy Considerations
3.1. Secure Transport
Client Hints will not be delivered to non-secure endpoints (see the secure transport requirements in Section 2.2.1 of [RFC8942]). This means that information about the user’s device pixel ratio and viewport size will not be leaked over plaintext channels, reducing the opportunity for network attackers to build a profile of a given agent’s behavior over time.
3.2. Delegation
Client Hints will be delegated from top-level pages via Permissions Policy. This reduces the potential for passive fingerprinting by:
-
Sending fewer hints to third parties.
-
Never doing so indiscriminately. Information can only be revealed to third parties after the root page author explicitly asks it to be revealed to them.
-
Ensuring that everyone (users, user agents, privacy advocates...) can see who is getting what information.
That delegation is defined as part of append client hints to request.
3.3. Access and Accuracy Restrictions
The information in the Client Hints defined above reveals extra information about the user’s context. User agents ought to exercise judgement before granting access to this information, and MAY impose restrictions above and beyond the secure transport and delegation requirements noted above. For instance, screen readers may choose not to indicate that they have no viewport, to ensure that their users are not served separate content. Similarly, user agents might offer users control over when hints are revealed to servers, gating them based on privacy modes or settings.
User agents may also choose to reduce the accuracy of these values, by rounding to reduce variation between users, and/or adding jitter to increase variation for a single user.
Servers MUST NOT require any of these hints in order to deliver content, and MUST NOT depend on pixel-accurate values in order to deliver acceptable experiences.
4. Interface and Processing model
TODO!? Or do the "in web contexts" notes above, cover this? Do we need an IDL interface? Related - do I need ABNFs, or are the simple structured header types enough?
5. Implementation Considerations
5.1. The Sec-CH prefix
TODO (start with https://github.com/WICG/ua-client-hints/blob/master/index.bs#L282 or https://github.com/WICG/ua-client-hints/blob/master/index.bs#L554)
6. IANA Considerations
This document intends to define the Sec-CH-Width
, Sec-CH-Viewport-Width
, and Sec-CH-DPR
HTTP request header fields, and register them in the permanent message header field registry ([RFC3864]).
6.1. Sec-CH-Width
Header Field
Header field name: Sec-CH-Width
Applicable protocol: http
Status: standard
Author/Change controller: IETF
Specification document: this specification (§ 2.1 The Sec-CH-Width Header Field)
6.2. Sec-CH-Viewport-Width
Header Field
Header field name: Sec-CH-Viewport-Width
Applicable protocol: http
Status: standard
Author/Change controller: IETF
Specification document: this specification (§ 2.2 The Sec-CH-Viewport-Width Header Field)
6.3. Sec-CH-DPR
Header Field
Header field name: Sec-CH-DPR
Applicable protocol: http
Status: standard
Author/Change controller: IETF
Specification document: this specification (§ 2.4 The Sec-CH-DPR Header Field)