Adopting progressive enhancement in CSS

May 04, 2021css-practicescss

CSS is forgivable, using an unknown CSS property might not break the whole site, but there is a good chance some parts won’t work as expected for some users. Providing fallbacks is needed to support old browsers while adopting new features.

Progressive enhancement is a strategy in web design that puts emphasis on web content first. Basic content and functionality should be accessible to all web browsers. Enhanced behavior is provided progressively. - Wikipedia

In CSS, progressive enhancement can be applied to fallback strategy, starting out with mostly basic widely-supported CSS features, then adding newer ones progressively.

You provide a baseline experience that works for all users, regardless of support or failures, and then enhance the user experience for more modern browsers.

This is a a useful technique that allows web developers to focus on developing the best possible websites while making those websites work on multiple unknown user agents.

Floats are well-supported way back to IE4, Flexbox is well-supported in modern browsers but has problems in older browsers like IE, Grids are way newer than Flexbox.

Layout features aren’t as easy to provide graceful fallbacks for as color, shadow, or gradient simple properties. If layout properties are ignored, your entire design will likely fall to pieces.

Because of this, you need to use CSS feature queries (@supports) to detect whether visiting browsers support those layout features, and selectively apply different layouts depending on the result.

CSS feature queries let you specify declarations that depend on a browser’s support for one or more specific CSS features. The rule may be placed at the top level of your code or nested inside any other conditional group at-rule.

@supports (display: grid) {
  div {
    display: grid;

If the browser understands display: grid, then all of the styling inside the brackets will be applied. Otherwise all of that styling will be skipped.

Well, not all browsers support feature queries. And the browsers that do not understand feature queries will skip all blocks of code inside. That’s probably bad. You want to structure your code knowing that the oldest browsers won’t support feature queries or the feature you are testing for.

/* fallback code for older browsers */

@supports (display: grid) {
    code for newer browsers
    including overrides of the code above, if needed

One thing can make progressive enhancement easier is that the design doesn’t require to look exactly the same everywhere, it can be simplified in old or mobile browsers, more complicated and fancier in modern desktop browsers to take advantages of modern powerful CSS features.

Is your business critical to support a tiny amount of users using IE? If not, then you’ll be amazed how few fallbacks you need to write.

This strategy doesn’t work well when you’re uncertain about number of old browsers you want to support, it’s time consuming when writing tons of fallbacks using old technologies that you might not need at all. In this case consider using graceful degradation instead.