Negotiating user preferences at request time

User preference media features such as prefers-color-scheme and prefers-reduced-motion can significantly affect both the CSS a page must deliver and the experience a user has during load. When a site inlines CSS for performance, it ideally wants to know the user's preferred color scheme or motion settings before serving the initial HTML, so the correct styles are present from the start and no flash of inaccurate color theme occurs.

Two client hint headers, Sec-CH-Prefers-Color-Scheme and Sec-CH-Prefers-Reduced-Motion, address this by letting servers obtain those preferences at request time. They are the first in a proposed series of user preference media features client hints headers.

How the headers fit into Client Hints

HTTP Client Hints, defined in RFC 8942, uses an Accept-CH response header for servers to advertise that they accept certain request headers for proactive content negotiation. The User Preference Media Features Client Hints Headers proposal adds hints that map one-to-one to the media features they report on, so prefers-color-scheme is conveyed via Sec-CH-Prefers-Color-Scheme.

These hints will most often be used as Critical Client Hints, meaning they change the resulting resource enough that the resource should be fetched consistently on every page load, including the very first one, to avoid jarring visual switches for the user.

The header values follow the Structured Headers for HTTP specification, with each value encoded as a string item. For instance, a user who prefers dark theme and reduced motion would produce:

Sec-CH-Prefers-Color-Scheme: "dark"
Sec-CH-Prefers-Reduced-Motion: "reduce"

These correspond to the CSS media queries @media (prefers-color-scheme: dark) {} and @media (prefers-reduced-motion: reduce) {}.

The full set of client hints mirrors the user preference media features in Media Queries Level 5.

Browser support and demos

Sec-CH-Prefers-Color-Scheme is supported in Chromium 93 and later; Sec-CH-Prefers-Reduced-Motion holds support from Chromium 108 onward. WebKit and Mozilla have not yet finalized their positions.

Demos for both headers are available for Sec-CH-Prefers-Color-Scheme and Sec-CH-Prefers-Reduced-Motion, with source code published on GitHub, demonstrating how inlined CSS responds to the user's preferences.

Request flow

  1. The client sends an initial request: GET / HTTP/2 with Host: example.com.
  2. The server responds with an Accept-CH header listing the hints it accepts, such as Sec-CH-Prefers-Color-Scheme and Sec-CH-Prefers-Contrast. When using a critical hint, it also sends Critical-CH and includes the hint name in the Vary header.
  3. The client retries the request, now supplying the appropriate hint, e.g., Sec-CH-Prefers-Color-Scheme: "dark".
  4. The server tailors its response accordingly, for example, inlining the dark-theme CSS.

Example in Node.js

An Express.js example based on the demo for Sec-CH-Prefers-Color-Scheme shows how to manage the hint server-side.

Privacy and security considerations

The Chromium implementation follows the core principles spelled out in Controlling Access to Powerful Web Platform Features — user control, transparency, and ergonomics. The security considerations from HTTP Client Hints and Client Hint Reliability also apply to this proposal.