Back to CSS
CSS
easy
mid

What is your approach to achieving cross browser consistency in production CSS?

Start from a baseline: a CSS reset/normalize, then build with well-supported standards and check caniuse. Use feature detection (`@supports`) over browser sniffing, progressive enhancement, autoprefixer for vendor prefixes, fluid/intrinsic layouts that tolerate variation, and a real cross-browser test matrix (BrowserStack + the main engines). Accept pixel-perfect-everywhere is the wrong goal — robust and acceptable is.

6 min read·~10 min to think through

Cross-browser consistency is about controlling variability, not chasing pixel-perfection on every engine. The approach is a layered one.

1. Start from a known baseline

Browsers ship different default styles. A CSS reset (reset.css) or normalize.css flattens those differences so you start from the same place everywhere. Set box-sizing: border-box globally while you're at it.

2. Build on well-supported standards

  • Check caniuse.com before relying on a feature.
  • Know your support matrix — which browsers/versions the product actually targets (look at analytics; don't guess).
  • Modern evergreen browsers (Chrome, Firefox, Safari, Edge) are mostly consistent now — Safari is the usual outlier (date inputs, fl/grid quirks, -webkit- needs).

3. Feature detection, not browser sniffing

css
@supports (display: grid) {
  .layout { display: grid; }
}
/* fallback for browsers without grid */

@supports (and JS feature checks) ask "can the browser do X?" instead of the fragile "is this Chrome?".

4. Progressive enhancement

Build a solid baseline experience that works everywhere, then layer on enhancements for capable browsers. The page should be usable even if a fancy feature isn't supported.

5. Tooling handles the boring parts

  • Autoprefixer / PostCSS — adds vendor prefixes automatically based on your browserslist.
  • Babel + a browserslist config — transpiles JS to your targets.
  • A linter to catch risky properties.

6. Design for tolerance

Rigid pixel layouts break across rendering engines. Fluid units, Flexbox/Grid, intrinsic sizing (minmax, clamp), and gap produce layouts that absorb small differences instead of shattering.

7. Actually test

  • A real test matrix: the major engines (Blink, Gecko, WebKit) × desktop/mobile.
  • BrowserStack / Sauce Labs / LambdaTest for engines you don't have locally — Safari/iOS especially if you're on Windows.
  • Visual regression testing (Percy, Chromatic, Playwright screenshots) catches unintended differences in CI.
  • Test on real mobile devices, not just emulators.

8. Set the right expectation

"Pixel-perfect on every browser" is the wrong goal — it's expensive and brittle. The goal is functionally correct and visually acceptable on your support matrix, with graceful degradation outside it.

Senior framing

The senior answer leads with reset baseline → standards + caniuse → feature detection → progressive enhancement → tooling → test matrix, and explicitly reframes the goal away from pixel-perfection toward robustness and graceful degradation. Naming @supports, autoprefixer/browserslist, visual regression testing, and "Safari is the modern IE" shows hands-on experience, not theory.

Follow-up questions

  • Why is feature detection better than browser sniffing?
  • What does progressive enhancement mean in practice?
  • How would you set up cross-browser testing in CI?

Common mistakes

  • Browser sniffing with user-agent strings instead of @supports.
  • Skipping a reset/normalize baseline.
  • Chasing pixel-perfection on every browser.
  • Only testing in Chrome on a fast desktop.

Edge cases

  • Safari/iOS quirks: 100vh, date inputs, smooth scrolling, -webkit- prefixes.
  • Font rendering genuinely differs across OSes — can't fully normalize.
  • Print stylesheets and high-contrast modes are easy to forget.

Real-world examples

  • Marketing sites with wide audiences, e-commerce checkout, anything with significant Safari/iOS traffic.

Related questions