I think, as front-end developers, we’re well aware that different browsers (and versions) support different things. We make choices based on web features we’d like to use balanced with what statistics tell us about our users and what browsers they use. Only 0.01% of users left on IE 9, we might see from our Google Analytics, OK, let’s start using Flexbox and .classList.
Enter Autoprefixer. Autoprefixer, over time, became a nearly ubiquitously part of CSS build processes because it helped 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";
.
Browserlist 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 Browserlist.

With Autoprefixer, just by having a Browserlist 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 Browserlist 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 Browserlist.
For example, your linting setup can be configured to warn you if you use code that isn’t supported outside of your Browserlist 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 Browserlist, 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.
Browserlist is a Good Idea is a post from CSS-Tricks