I am currently available for freelance/contract work. Book a meeting so we can talk about your project.

Progressive enhancement with @supports (video)

Posted on

Designing beautiful websites is getting easier. Flexbox and grid enable layouts that were impossible before. Transforms and filters add visual effects that would be difficult to build otherwise. Unfortunately, not all browsers support all those cool new features yet.

Internet Explorer is no longer the anchor holding us back. Today’s browsers all support these sometimes experimental features to a different degree. Some support grid, some support backdrop-filter, some support WebP, some support sticky headers. No single browser supports every upcoming feature.

We can approach this situation in several ways, and they all have their drawbacks:

  • We can avoid using the new capabilities until all browsers support them. That could take years.
  • We can go all-in on our favorite browser and ignore all others. Our layouts will look good in a single browser, but break in many of the others.
  • We can use “polyfills” that enable the features in more browsers, usually through a lot of JavaScript. Throwing more code at a problem adds complexity and new points of failure to our products.

Trying to make the exact same design happen in every browser is not worth these tradeoffs. Instead, we can deliver a basic styling that is “good enough” and works everywhere. We can then enhance that version with the new features only for browsers that support them.

With @supports, we can adjust the styling based on which features a browser supports. We could use a plain layout everywhere, and improve it with grid in browsers that understand it.

.my-container {
  display: block;
}
 
/* test if this browser supports grid */
@supports (display: grid) {
  .my-container {
    display: grid;
  }
}
.my-container {
  display: block;
}
 
/* test if this browser supports grid */
@supports (display: grid) {
  .my-container {
    display: grid;
  }
}

We can also test if a browser supports custom properties (CSS variables) and only use them when it does. For browsers that don’t support this feature yet, we define fallbacks outside of the @supports-block.

body {
  background-color: #f6f9fc;
  color: #28303f;
}
 
/* test if this browser supports custom properties */
@supports (--anything: red) {
  body {
    background-color: var(--body-background);
    color: var(--body-text);
  }
}
body {
  background-color: #f6f9fc;
  color: #28303f;
}
 
/* test if this browser supports custom properties */
@supports (--anything: red) {
  body {
    background-color: var(--body-background);
    color: var(--body-text);
  }
}

As soon as a new browser supports a feature, the feature-gated styles will work for it. This is much more future-proof than building IE-only stylesheet like we did a few years ago. @supports is the future.

Debug
none
Grid overlay