This spec requires large amounts of work to section it and word it in ways that are normative. It is currently a very rough draft.
1. Introduction
This section is non-normative.
Currently, website authors have a choice when wishing to honour a user’s preference for a given setting:
They can choose to "use the platform" where the user must indicate their preference via their OS or, if lucky, they can override in the browser. This comes with a number of issues:
-
Relies on the user’s OS or browser offering the ability to change the setting
-
Relies on the user knowing how to change the setting in their OS or browser
-
No ability to override the setting for a specific site
-
No ability to sync preferences for a site across devices
Alternatively, sites can and do offer site-level settings, but this currently comes with a number of issues:
-
No integration with Media Queries 5 § 11. User Preference Media Features
-
No integration with conditional resource loading (e.g. using
<source media="(prefers-contrast: more)">
) -
No integration with JS APIs for retrieval of these preferences (e.g.
matchMedia
in CSSOM View § 4 Extensions to the Window Interface -
No integration with [USER-PREFERENCE-MEDIA-FEATURES-HEADERS]
-
No integration with the CSS Color Adjustment 1 § 2 Preferred Color Schemes concept
-
The various client storage mechanisms that could store these preferences can be cleared in a number of scenarios
Unsure how to link to html spec for the
The Web Preferences API aims to solve this by providing a way for sites to override the value for a given a user preference.
It is intended for this override to apply permanently and be scoped per origin. The override should be passed down to sub-resource where possible, see privacy section for details. This explainer refers to "site" but it should be read to mean origin.
2. Extensions to the Navigator
interface
[Exposed =Window ]partial interface Navigator {readonly attribute PreferenceManager ; };
preferences
2.1. preferences
attribute
When getting the preferences
attribute always return the same instance of the PreferenceManager
object.
3. PreferenceManager
interface
[Exposed =Window ]interface {
PreferenceManager attribute ColorSchemePref ?;
colorScheme attribute ContrastPref ?;
contrast attribute ReducedMotionPref ?;
reducedMotion attribute ReducedTransparencyPref ?;
reducedTransparency attribute ReducedDataPref ?;
reducedData sequence <PreferenceSupportData >getSupported (); };
Note: The exact set of preferences is down to the browser vendor, but it is expected that the set of preferences will be the same as those defined in [mediaqueries-5].
3.1. getSupported
method
getSupported()
method, when invoked, must run these steps:
-
Let supportedPreferences be a new empty sequence.
-
For each preference that the browser supports, add a new
PreferenceSupportData
object to supportedPreferences with the following properties:-
name
set to the name of the preference -
values
set to a sequence of strings representing the valid values for the preference
-
-
Return supportedPreferences.
3.1.1. PreferenceSupportData
interface
[Exposed =Window ]interface {
PreferenceSupportData readonly attribute DOMString ;
name readonly attribute FrozenArray <DOMString >; };
values
3.2. Preference attributes
3.2.1. Setting a preference attribute
-
Let preference be the preference attribute’s name.
-
Let validValues be the preference attribute’s valid values.
-
If value is not in validValues, return.
-
If value is the same as the preference override for preference, return.
-
Set the preference override for preference to value.
This algorithm needs more detail on where the overrides are stored. Also need to define what happens when a preference is overridden, with specific regard to sub-resources.
3.2.2. Getting a preference attribute
-
Let preference be the preference attribute’s name.
-
If no overrides have been set for the preference, return
null
. -
Let result be the preference override for preference.
-
Return result.
This algorithm needs more detail on where the overrides are stored.
3.2.3. colorScheme
preference
The colorScheme
preference represents the user’s preference for the color scheme of the site.
This is modeled after the prefers-color-scheme
user preference media feature as defined in Media Queries 5 § 11.5 Detecting the desire for light or dark color schemes: the prefers-color-scheme feature.
enum {
ColorSchemePref ,
"light" };
"dark"
3.2.4. contrast
preference
The contrast
preference represents the user’s preference for the contrast of the site.
This is modeled after the prefers-contrast
user preference media feature as defined in Media Queries 5 § 11.3 Detecting the desire for increased or decreased color contrast from elements on the page: the prefers-contrast feature.
Unlike the media feature this preference is not able to be set to custom
this is tightly coupled to the forced-colors
media feature.
enum {
ContrastPref ,
"no-preference" ,
"more" };
"less"
3.2.5. reducedMotion
preference
The reducedMotion
preference represents the user’s preference for reduced motion on the site.
This is modeled after the prefers-reduced-motion
user preference media feature as defined in Media Queries 5 § 11.1 Detecting the desire for less motion on the page: the prefers-reduced-motion feature.
enum {
ReducedMotionPref ,
"no-preference" };
"reduce"
3.2.6. reducedTransparency
preference
The reducedTransparency
preference represents the user’s preference for reduced transparency on the site.
This is modeled after the prefers-reduced-transparency
user preference media feature as defined in Media Queries 5 § 11.2 Detecting the desire for reduced transparency on the page: the prefers-reduced-transparency feature.
enum {
ReducedTransparencyPref ,
"no-preference" };
"reduce"
3.2.7. reducedData
preference
The reducedData
preference represents the user’s preference for reduced data usage on the site.
This is modeled after the prefers-reduced-data
user preference media feature as defined in Media Queries 5 § 11.6 Detecting the desire for reduced data usage when loading a page: the prefers-reduced-data feature.
enum {
ReducedDataPref ,
"no-preference" };
"reduce"
4. Usage Examples
This section is non-normative.
Each preference the browser supports will be exposed as a property on the navigator.preferences
object.
Feature detection for a given preference is as simple as:
const colorSchemeSupported= 'colorScheme' in navigator. preferences;
4.1. Setting a preference override
To set a preference override, the property can be set to a valid value for the preference. If an invalid value is set then this will be a no-op.
navigator. preferences. colorScheme= 'dark' ;
4.2. Clearing a preference override
To clear an override and return the preference to the browser default, the property can be set to null.
navigator. preferences. colorScheme= null ;
4.3. Getting a preference override
To get the value of a preference override, the property can be read. Each property will return the string value indicating the preference, or null if no override is set.
const colorScheme= navigator. preferences. colorScheme; // "light" | "dark" | null
4.4. The navigator.preferences.getSupported
method
This method allows a site to get the preferences supported by the browser. This is useful for sites that want to dynamically generate UI for overriding preferences.
It also allows sites to determine if a preference value is supported before attempting to set it.
const preferenceSupportData= navigator. preferences. getSupported(); console. log( preferenceSupportData); // [ { name: 'contrast', values: ['more', 'less', 'no-preference'] }, ... ]
5. Security and Privacy Considerations
The API is currently exposed even to insecure contexts. This is probably fine but should be justified in this section probably?
This section is non-normative.
5.1. Avoiding fingerprinting
This API exposes no new fingerprinting surfaces beyond that which already exist in the platform.
5.2. Permissions & User Activation
This API does not require any permissions or user activation. It exposes no new capabilities to a site beyond that which already exists in the platform.
A site can already store a value in local storage and read into the DOM to override a preference. This API simply makes the ergonomics of this better.
5.3. Sub-resources
Note: See #8 for discussion regarding this.
For the spec we can probably find an existing definition to reference, but for the purposes of this explainer:
-
Any same origin subresource (e.g. iframes) should get the overridden value.
-
Any cross-origin subresource that already has communication with the parent (e.g.
postMessage
) should get the override value. -
Any cross-origin subresource with no external communication (e.g. an SVG loaded as an image) should get the override value.
-
Any cross-origin subresource that has no communication with parent but can communicate externally should NOT get the override value.
Wherever the override value is passed down it should be done so in an opaque manner.
colorScheme
to dark
then the iframe should see prefers-color-scheme
as dark but shouldn’t read navigator.preferences.colorScheme
as dark
. 6. Acknowledgements
This section is non-normative.