Browserslist is a Good Idea

As front-end developers, we're well aware that different browsers (and versions) support different web platform features. We make choices based on the support of those features balanced with what analytics tell us about what browsers our users use. For example, if our Google Analytics tell us only 0.01% of users are left on IE 9, perhaps we'll decide it's OK to start using Flexbox and .classList.

Enter Autoprefixer. Autoprefixer has become a ubiquitous part of CSS build processes because it helps us with cross browser support almost effortlessly. Even though IE 10 only supported an older Flexbox syntax, we didn't have to worry about that because Autoprefixer did it's best to port the modern syntax to the older one, and it did a great job at that.

Autoprefixer allows you to configure what browsers you wanted to target with the prefixing. This means you don't have to generate prefixes for every browser ever (resulting in potentially more code output than you want) but instead only generate prefixes for the browsers you've decided to support. There are lots of ways to use Autoprefixer, but let's say it's a part of your Grunt build:

grunt.initConfig({
  autoprefixer: {
    options: {
      options: {
        browsers: ['last 2 versions', 'ie 8', 'ie 9']
      }
    },
    your_target: {
      // Target-specific file lists and/or options go here.
    },
  },
});

As you might guess, that Autoprefixer configuration will process based on the last 2 versions of all major browsers as well as specifically do what is needed for IE 8 and IE 9.

That's great, but Autoprefixer isn't the only tool out there making choices about browser versions.

Indeed.

I bet many of you have worked with Babel or at least heard of it. You write as modern of JavaScript as you like, and it processes it into JavaScript that will run in older browsers. There is a project called babel-preset-env which allows you to configure what browsers Babel will compile down to. For example:

"babel": {
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": ["Edge 15"]
        }
      }
    ]
  ]
},

There we are specifically targeting Edge 15. Just as one little example, Babel won't even bother converting anything in const a = `string`; because Edge 15 supports const and `backticks`. But if we told it to also target IE 10, we'd get var a = "string";.

Browserslist is about a single configuration for all tools that need to know what browsers you support.

We just looked at two major tools that can be configured based on which browsers to support: Autoprefixer and Babel. Doesn't it make sense to be targeting the same list of browsers? (Yes.)

Enter Browserslist.

browserl.ist helps you see exactly what browsers you're targetting based on a configuration string.

With Autoprefixer, just by having a Browserslist configuration, it will automatically use it.

{
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "IE 10"
  ]
}

That's an example of having the configuration stored in your `package.json` file. There are other ways to make sure a Browserslist configuration is available though, like having a BROWSERSLIST environment variable or a `.browserslistrc` config dotfile.

Babel still requires babel-preset-env.

There are other interesting tools using Browserslist.

For example, your linting setup can be configured to warn you if you use code that isn't supported outside of your Browserslist setup. This is done with the eslint-plugin-compat plugin for ESLint.

On the CSS side, the same can be done with stylelint and the stylelint-no-unsupported-browser-features plugin.

Those things feel like a natural extension of Browserslist, and it's really cool they exist already. Perhaps slightly more surprising is PostCSS Normalize, which actually builds a CSS "reset" (Normalize isn't really a reset, but you know what I mean, it handles cross browser differences in CSS) based on the browsers your target.

If you'd like to read a bit more, check out the article Autoprefixer 7.0 and Browserslist 2.0 from the developers behind these projects.

Even better, check out an example repo of all of these things combined together in a minimal example.