DEV Community

Cover image for Progressive Enhancement: Respecting web browser preferences in a post ES6 world
Jaime Rios
Jaime Rios

Posted on

Progressive Enhancement: Respecting web browser preferences in a post ES6 world

Cover Image By: Tom Davidson on Flickr.


After Google IO, and watching a few talks, about elevating web capabilities, I got inspired. So here is a bridge for you guys.

What is Progressive Enhancement?

In a nutshell, Progressive Enhancement is a philosophy for developing web applications and this are the principles:

  • Basic content should be accessible to all web browsers.
  • Basic functionality should be accessible to all web browsers.
  • Sparse, semantic markup contains all content.
  • Enhanced layout is provided by externally linked CSS.
  • Enhanced behavior is provided by unobtrusive, externally linked JavaScript.
  • End-user web browser preferences are respected.

An alternative to PE is Graceful Degradation(GD). The difference is that PE goes from simple to complex while GD goes the other way around.

I've written before about accessibility and will write another post for common heuristics for web development.

More than persuading you to support IE or holding back on CSS Grid, my goal is to make you aware of new APIs we can use in order to comply with the last point on the list: End-user web broser preferences are respected.

Respecting web browser preferences

Even if you are not aware of it, the browser exposes information about the user preferences, so let us walk through a few of them.

Font system default

Another reason for using the system's default font is web performance, since there are no additional files to fetch from a server. There are three ways to accomplish this:

  1. Using the system-ui value:
    This is a value for font-family that represents the default user interface font. Except for Firefox, it is supported by most recent modern browsers.

  2. Apply system fonts by calling them using font-family:
    I recommend hiding this behind a feature query, as a fallback.

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
Enter fullscreen mode Exit fullscreen mode
  1. Using a polyfill. Depending on your use case, this might be a last resource alternative. This is available as an npm package and this is the link:

Do Not track

This might be a controversial one. But the only fact that the user does not want you to, should be enough reason to stop monitoring their behavior. This is an opinion, but privacy is a human right.

The Do Not Track API is supported by modern browsers except Safari

Here is what an implementation might look like:

 * "1" if DNT is enabled
 * "0" if the user opted-in for tracking
 * "unspecified" otherwise

if (navigator.doNotTrack === 0) {
    // Initialize Google Analytics scripts
} else if (!navigator.doNotTrack) {
    // Ask user if it is ok to track
} else {
Enter fullscreen mode Exit fullscreen mode

Here is Do Not Track on MDN.

Default to user preferred language

Depending on your app, there might be an internationalization(i18n) implementation in your app. There is a way to default to user's language if supported, Instead of inferring it from their IP, location or your app preferences.

User prefers-color-scheme

prefers-color-scheme is a media feature that as the name implies, allows us to detect if the user has requested the system use a light or dark color theme.

This was shipped on Firefox 67, it is supported on Safari 12.1 but as the time of this writing, support is still missing in most modern browsers.

Here is the link to prefers-color-scheme on MDN.

User prefers-reduced-motion

Similar to the previous point, we can detect if the user prefers to have less animations. This might be due to accessibility concerns, or mere preference. I can see why this might be a concern if you have rich CSS animations, 3D Graphics or VR.

The implementation in CSS is rather simple, here is what the code looks like:

.animation {
  animation: vibrate 0.3s linear infinite both; 

@media (prefers-reduced-motion: reduce) {
  .animation {
    animation: none;
Enter fullscreen mode Exit fullscreen mode

Further resources:

prefers-reduced-motion on MDN.
Here is a great article if you would like to look further into this:

That's all folks, thanks for your taking the time to read this. You can read my other posts on or say hi on Twitter.


Top comments (2)

austinstanding profile image
Austin Standing

Thanks for the insights!

You may want to re-read this line:

The Do Not Track API is supported by modern browsers expect Safari

papaponmx profile image
Jaime Rios

I just updated it, thanks for the input.