The Publishing Project

Feature detection and vendor prefixes in CSS

CSS has had to deal with vendor prefixes from very early on and some of those prefixes are still in use today. This post will look at how to use prefixes and how to automate the process, and how to use @supports to test if a feature is supported.

Adding CSS prefixes

That we’re still dealing with vendor prefixes shows how long some of them have lasted and provides an object lesson on how to handle features in development

Developers didn’t think of vendor prefixes as a way to preview features, they shipped them in production, something the CSS Working Group considers harmful.

Once you add a flag or vendor prefix and developers start using it in production, it becomes harder for browsers to change the feature works or its syntax. With flags, your users must actively enable it.

The standard way

The easiest way to handle different vendor prefixes is to just list them all. Browsers will ignore any rule they don’t understand and if they understand more than one rule in a selector, the last one in document order wins; that’s why we put the unprefixed version last.

.myClass {
  -webkit-transition: all 1s linear;
  -moz-transition: all 1s linear;
  -ms-transition: all 1s linear;
  transition: all 1s linear;
}

Although most vendor prefixes have been consolidated we should still be careful which ones we use and in what order:

  • Microsoft and Opera adopted Blink for their browsers so all the prefixed rules in Blink apply to Edge and Opera too
  • IE 11 may stay with us a while longer so we still need the -ms- prefix for some properties
  • Blink still uses -webkit- prefixed properties from before the fork

Automating the process

If we’re willing to put our CSS through a build process or use technologies like SASS/SCSS or LESS that already require a compilation step we can also automate vendor prefixes with tools like Autoprefixer either as a standalone tool or with your favorite task runner.

This example uses gulp-autoprefixer and gulp-sourcemaps to automatically add prefixes to all the CSS files under the src.

const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');

exports.default = () => (
  gulp.src('src/**/*.css')
    .pipe(sourcemaps.init())
    .pipe(autoprefixer())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist'))
);

By default, Autoprefixer uses data from caniuse.com to determine what prefixes to use for the default set of browsers.

Test browser support for a feature using @supports

CSS way to test if a browser supports a given feature is to use @supports to query if a browser supports a feature.

@supports (display: grid) {
  .container {
    display: grid
  }
}

This example checks if the browser supports CSS grid (the display: grid rule) and uses it if it’s supported. If the browser doesn’t understand @support or display: grid it will ignore the full @supports block altogether.

For more information on @supports see MDN’s @supports article