Everyone reaches for the global box-sizing: border-box reset at some point. It’s in every starter template, every boilerplate, every “modern CSS setup” article. I’ve used it too. But after running into its problems enough times, I stopped. Here’s why.

What it does

The browser default is content-box. Your declared width applies to the content only, padding and border add on top. border-box flips it: width and height include padding and border.

One property, two mental models. The problem is forcing everyone onto one of them.

The appeal

A width: 300px box stays 300px even after you add padding or borders. That matters in grids and component layouts. “Why did this overflow?” questions disappear when every element follows the same sizing model. Easy to see why it caught on.

Why normalize.css doesn’t justify it

normalize.css isn’t a reset. It preserves useful browser defaults and smooths out cross-browser inconsistencies. Its philosophy is “keep defaults when they’re reasonable.”

Official reference: https://necolas.github.io/normalize.css/

Global border-box does the opposite: it overrides a fundamental default for everything. The two can coexist technically, but they’re pulling in different directions.

The real problems

The cognitive cost is higher than it looks. Any developer who expects content-box will miscalculate sizes, and that includes your future self six months later, third-party library authors, and anyone copying components between projects.

Third-party CSS is where it quietly bites you. Libraries that assume content-box break in subtle ways that take time to diagnose. You didn’t write that CSS, you can’t easily change it, and you end up debugging someone else’s layout math.

Portability is where it really gets you. Copy a component from a project with global border-box to one without it and sizing breaks. You usually can’t change the global rule in either project, so every paste requires a sizing audit.

”Just document it” doesn’t work

The usual counter-argument: set it globally, document it in your README or style guide. In theory, fine. In practice, documentation gets read after something breaks, not before. By the time a developer finds that note, they’ve already spent an hour debugging a layout that shouldn’t behave the way it does.

What to do instead

If you want predictable sizing in specific places, use the inheritance pattern scoped to where it actually matters:

html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }

Opt in per component rather than opting out. Or just set it directly on the elements where it counts — layout containers, grids, cards — and leave everything else alone.

The honest take

Global border-box trades one set of problems for another. The predictability benefit is real, but so are the portability issues, the third-party conflicts, and the cognitive overhead for anyone who didn’t set it up themselves. For most projects, the escape hatch you never use isn’t worth the confusion it creates.