Configuring Autoprefixer and Browserslist for Cross-Browser CSS

Does your layout break in clients' browsers and do fixes eat up weeks? We configure Autoprefixer and Browserslist turnkey: we eliminate cross-browser failures across all target browsers and cut style maintenance time dramatically.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Frequently Asked Questions

Autoprefixer Won't Save You: Where Cross-Browser CSS Breaks

Autoprefixer adds vendor prefixes based on Browserslist data — and that's enough as long as the target browser list reflects the real audience.

The problem is that the configuration file is often written once and then forgotten: it lives in the repository for years, accumulating copy-paste from other people's templates, while browser support changes over that time.

As a result, the build confidently adds prefixes where they haven't been needed for ages and stays silent where a property doesn't work without a prefix.

The first class of failures is properties that Autoprefixer doesn't touch by definition.

Logical properties, gap in flex containers, aspect-ratio, :has() — no prefixes exist for them, and on older engines the layout falls apart entirely: the grid collapses, spacing disappears, blocks overlap each other.

The second is outdated prefixes: if a browser that has been dropped from support remains in the configuration, the build will keep generating dead rules, bloating the stylesheet and confusing developers.

The third is differences between engines in behavior rather than syntax: different interpretation of flex item sizes, margin collapsing, sub-pixel rounding. A prefix won't help here — you need either headroom in the markup or an explicit reset.

For the user, it all looks the same: a button slides off the edge of the screen, a form stops submitting, a catalog shows empty cards. The client learns about it from support requests, not from reports — because testing was done in a single browser where everything was fine. Let's break down how this is addressed at the level of build configuration and regression checks.

What a well-tuned Autoprefixer and Browserslist configuration delivers

The configuration of Autoprefixer and Browserslist is not a "checkbox in the build" but two files that determine which CSS ships to production. Autoprefixer reads the Browserslist query and adds vendor prefixes only for the engines that are actually on the list.

If the list is vague — "latest versions" with no caveats — prefixes either get sprayed onto everything indiscriminately or fail to land where they are needed.

What changes in numbers

Style volume. With a correct list of target browsers, Autoprefixer stops duplicating properties for engines you do not have in your audience.

On a typical project, this removes 8–15% of the CSS bundle weight, and on legacy code with flexbox and grid — up to a quarter: prefixes for old engines go away, only the working ones remain.

Build time. Every extra browser in the query means an additional pass over all rules. Narrowing the list to the real audience speeds up style processing by 20–40% and noticeably cuts hot-reload time during development.

Failure class. The main pain is not "it broke everywhere" but "it broke for some." A dropdown menu falls apart in one engine, a grid collapses in another, a sticky element does not stick in a third.

These are expensive bugs: they are caught in prod, reproduced through a proxy, and fixed blindly. A well-tuned Browserslist eliminates this entire class of failures — because prefixes and fallbacks are set for a specific list, not "approximately."

Predictability instead of guesswork

The list of target browsers is fixed in the config and versioned alongside the code. This means layout behavior is reproducible: a build on a developer's machine, in a test environment, and in prod produces the same CSS.

Any argument of "well, it works on my machine" is settled by a single line in the config, not by manual checks in five browsers.

A separate effect is predictability when the audience updates. When the share of an old engine drops, you remove it from the list with a single edit and immediately see how much CSS has left the bundle.

Approaches to prefixing: manual, automatic, hybrid

Manual prefixing is when the engineer themselves adds vendor prefixes to properties that have not yet made it into a stable specification. This approach works on small projects and one-off fixes: every change is visible, and no additional build tools are needed.

The limitation is the human factor: a missed prefix for one browser is caught neither by a linter nor by tests until a complaint comes in from a user. Across hundreds of rules, this turns into constant manual work and desynchronization between files.

Automatic prefixing removes this burden: the bundler reads the list of target browsers, determines on its own which properties require prefixes, and adds them at the build stage. Autoprefixer does this based on real browser usage statistics rather than the developer's memory.

The key point is a correctly defined list of targets: it determines exactly what ends up in the final CSS.

Option When it fits Limitations
Manual prefixing Small projects, isolated properties, prototypes Grows in labor costs, easy to miss a browser, no single source of truth
Automatic (Autoprefixer + Browserslist) Production projects, team work, frequent releases Requires a configured browser list and a place in the build; with incorrect targets it produces extra or insufficient CSS
Hybrid approach Legacy code with manual prefixes and new code alongside Requires discipline: old rules are gradually cleaned up, otherwise duplicates and conflicts arise

The hybrid approach is transitional: automation is enabled for all new code, while manual prefixes in legacy are cleaned up as edits are made. This way the team does not rewrite the entire project at once, but also does not drag two parallel mechanisms along indefinitely.

The choice of approach is determined not by the size of the codebase, but by how predictable the list of target browsers is and how often it changes.

How we implement Autoprefixer and Browserslist: stages of work

We start with an audit of the markup: we look at which properties already require prefixes, where styles are assembled manually, and how much the current set of rules diverges from the project's actual audience.

Based on traffic analytics and the client's requirements, we pin down the target browsers — this directly determines how many prefixes need to be generated at all and which outdated workarounds can be removed.

  1. Markup audit. We analyze the existing styles, find properties that break in older engines, and identify places where prefixes are added by hand or, conversely, forgotten.
  2. Determining target browsers. We agree on the list of supported versions and lock it into the configuration — a single source of truth instead of scattered agreements within the team.
  3. Configuring Autoprefixer. We hook up processing to the style build, set the browserslist rule and the mode for removing unnecessary prefixes so we don't drag outdated code into production.
  4. Running the build. We rebuild the styles and verify the result: the needed prefixes are added automatically, duplicates and junk are removed.
  5. Cross-browser testing. We test key scenarios in the target engines, check responsiveness and interactive states, and record any discrepancies.
  6. Fixes and re-testing. We eliminate the defects found, adjust the browser list if necessary, and rebuild.
  7. Handover. We deliver the configured setup, documentation on the rules, and instructions on how to change the list of target browsers without risking breaking the markup.

After handover, prefix maintenance stops being a routine: the rule is updated in a single file, and the build itself brings the styles into line with it. Describe your task — we'll come back with an estimate and a work plan.

Browserslist configuration and browser support policy

Browserslist configuration is a single source of truth about which browsers are considered target.

The same list is read by Autoprefixer, the CSS minifier, and the script transpiler, so desynchronization between them is excluded: prefixes, syntax, and polyfills are guided by one support matrix.

The configuration file lives in the project root and is versioned alongside the code. We fix the support policy explicitly — market share, latest major versions, separate lines for mobile engines — rather than a vague "latest versions". This way the build is reproducible on any machine and in the pipeline.

  • .browserslistrc or a field in package.json — a single point of editing for all tools
  • List of target browsers with justification for each line: market share, major versions, mobile engines
  • Exception rules — dropping support for outdated engines with a date and reason
  • Environment separation: separate sets for development and for the published build
  • Verifying relevance via npx browserslist — which browsers actually made it into the selection
  • Policy documentation: what we support, what we don't, and when we revisit the decision
  • Review schedule — once a quarter or when a new major version of a key engine is released

Documentation here is not a formality: when six months later the question arises "why is this browser on the list", the answer should be in the repository, not in a chat thread.

Exception rules with a date and reason make it possible to safely restore support if the engine's share grows again.

Case study: how Autoprefixer configuration eliminated layout failures

The project is a customer portal for a service company: several dozen screens, a shared component library, built with PostCSS.

Styles were compiled without a single supported-browser profile: developers added prefixes by hand and duplicated properties "just in case." By release time, 40+ discrepancies had accumulated between local checks and production, and the stylesheet had grown so large that editing a single component triggered a rebuild of the entire bundle.

What it was like before configuration

Autoprefixer was in the processing chain, but without a Browserslist configuration — meaning it ran on defaults, with no explicit list of targets.

Some properties went into the build without the necessary prefixes, while others had prefixes for browsers the project no longer supported. The result: on two versions of mobile browsers the card grid broke, the sticky header overlapped content, and forms lost field alignment.

Each such failure was caught only at acceptance, and fixing it took anywhere from a few hours to a day.

What was changed

The list of target browsers was locked down in a separate configuration file — split into production and internal builds so that behavior was identical for all engineers.

Autoprefixer began adding only the prefixes actually needed for that list, rather than "just in case." At the same time, manual property duplicates and dead rules left over from old edits were cleaned out.

Metrics before and after

Metric Before After
Size of compiled CSS baseline −38%
Layout failures at acceptance per quarter 40+ 3
Time to edit a shared component full bundle rebuild targeted rebuild
Local / production discrepancies regular isolated

The reduction in size delivered more than just faster loading: fewer rules means fewer conflicts between them, so some failures disappeared on their own, without targeted fixes.

The remaining three cases turned out to be related not to prefixes but to component logic — they were handled separately.

Maintainability deserves a separate mention: a new engineer now sees the list of targets in a single file and doesn't have to guess which browsers are in scope. This eliminates an entire class of errors before they ever make it into the build.

How is Autoprefixer different from manual prefixing?

Manual prefixing is when an engineer adds -webkit-, -moz-, and other variants before each property themselves, relying on memory and compatibility tables.

Autoprefixer does the same thing, but at the build stage: it reads the CSS, checks it against a browser support database, and adds only the prefixes that are actually needed for the given list of targets.

The difference is not in the output result, but in who makes the decision about each prefix and when.

The key difference is the source of truth. With the manual approach, it lives in the developer's head: someone remembers about -webkit-backdrop-filter, someone else does not, and the same project accumulates uneven edits.

Autoprefixer relies on Browserslist — a single config where the target browsers and their minimum versions are defined. If the support policy changes, one line is edited, and the entire CSS is rebuilt for the new targets without a manual pass through the files.

The second difference is selectivity. Manual prefixing almost always happens "just in case": prefixes remain where browsers have long since stopped requiring them, and they bloat the stylesheet.

Autoprefixer adds a prefix only when the target browser would not understand the property without it, and removes the excess when targets change. Over a project's long history, this is a noticeable difference in the size and readability of the styles.

The third is reproducibility and maintenance. Manual prefixes live in the code for years, no one revisits them, and they quietly turn into junk. Automation is tied to the build: update the browser list — and you get up-to-date CSS on the next build.

A new engineer on the team does not need to know by heart which properties require prefixes — that rule lives in the config, not in someone's memory.

The manual approach is justified in isolated cases: a one-off landing page without a build, or debugging a specific property.

For a project that lives and evolves, automation via Autoprefixer and Browserslist delivers a predictable result and eliminates an entire class of compatibility errors.

Common technical concerns when setting up prefixing

Autoprefixer integrates into an existing build without rewriting styles: it works as a post-processing plugin and picks up the already compiled CSS.

If you have Webpack, Vite, Gulp, or a PostCSS chain, it is enough to add it to the list of handlers, and the order of the other steps does not change.

The only thing worth checking during integration is that prefixing runs after autoprefixing of properties and before minification, otherwise some vendor properties will be stripped by the optimizer.

On performance, there is usually one concern: will it slow down the build. Autoprefixer does not re-parse styles — it works on the same tree as the other PostCSS plugins, and on a typical project it adds fractions of a second to the build.

The main time is spent not on prefixing but on reading the Browserslist configuration, which is why it is cached between runs. In development mode with hot reload, prefixes are recalculated only for changed files.

With legacy browsers, the key point is not to "support everything" but to lock in a deliberate list of targets. Browserslist defines this list in one place, and it determines which prefixes will appear in the final CSS at all.

If the targets are vague, the file bloats with prefixes for browsers nobody uses; if they are too narrow, the layout breaks for part of the audience.

Will prefixing break the styles already written?

No. Autoprefixer only adds vendor properties and does not touch the ones you wrote manually. If a prefix is already there, a duplicate will not appear.

The risk arises in one case — when the project has its own plugin that adds the same prefixes: then properties get duplicated, and the order in the chain needs to be coordinated.

What happens if the targets in Browserslist become outdated?

The list of targets is a configuration, not a constant: it is reviewed when the audience changes. As long as it is up to date, only the necessary prefixes end up in the CSS, and the extra ones do not accumulate.

We lock the targets in a single file and check them during scheduled updates so that legacy browser support does not grow unnoticed.

Can changes be rolled back if something goes wrong?

Yes. The setup lives in the build configuration and in the targets file — both are versioned together with the code. A rollback is a return to the previous configuration without editing the styles themselves, so the risk to production is minimal.

Let's discuss your cross-browser layout task

Tell us which browsers and devices your interface needs to work on — we'll come back with an estimate and a work plan.

Autoprefixer and Browserslist in this combination solve a specific problem: the first adds vendor prefixes based on the actual list of target browsers, the second defines that list in a single configuration file rather than in the layout developer's head. The requirement changes — one line is edited, and the entire build is rebuilt for the new coverage.

We don't estimate "by eye" but from the support matrix. First we pin down which browsers and versions are actually needed based on your audience and analytics, then we check how the current layout behaves at the boundaries of that list.

Separately, we look at places where prefixes won't help: grids, flexible containers, non-standard properties, and system fonts require manual solutions. This way the estimate is tied to the scope of work, not to the number of lines of styles.

What the work includes:

  • auditing the current layout and determining the real matrix of supported browsers;
  • configuring Autoprefixer and Browserslist for this matrix, including separating rules for internal and public pages;
  • verifying the build: prefixes make it into the final CSS rather than getting lost at the minification stage;
  • manually refining properties that automation doesn't cover;
  • testing on target browsers and devices, including mobile;
  • committing the configuration to the repository so the rules don't "drift" during subsequent edits;
  • a short guide for the team: how to change the browser list without breaking the build.

We structure the work plan so that you see results at every step: first the support matrix and current state, then the configuration and edits, then testing on real browsers. Describe your task — we'll come back with an estimate, timelines, and a clear plan.

Our competencies:

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1393
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1368
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1139
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1152
  • Website development for SBH Partners
    Website development for SBH Partners
    1231
  • Website development for Red Pear
    Website development for Red Pear
    641