Notes on Josh Comeau’s Custom CSS Reset

Avatar of Chris Coyier
Chris Coyier on (Updated on )

We recently talked with Elad Shechter on his new CSS reset, and shortly after that Josh Comeau blogged his.

We’re in something of a new era of CSS resets where… you kind of don’t need one? There isn’t that many major differences between browsers on default styling, and by the time you’re off and running styling stuff, you’ve probably steamrolled things into place. And so perhaps “modern” CSS resets are more of a collection of opinionated default styles that do useful things that you want on all your new projects because, well, that’s how you roll.

Looking through Josh’s choices, that’s what it seems like to me: a collection of things that aren’t particularly opinionated about design, but assist the design by being things that pretty much any project will want.

I’m gonna go through it and toss out 🔥 flamin’ hot opinions.

*, *::before, *::after {
  box-sizing: border-box;

Heck yes. We used to consider this a global holiday ’round here. Although, with more and more layout being handled by grid and flexbox, I’m feeling like this is slightly less useful these days. When you’re setting up a layout with fr units and flexin’ stuff, the box-sizing model doesn’t come into play all that much, even when padding and border are involved. But hey, I still prefer it to be in place. I do think if it goes into a CSS reset it should use the inheritance model though, as it’s easier to undo on a component that way.

* {
  margin: 0;

This is basically why the CSS-Tricks logo “star” exists. I used to love this little snippet in my CSS resets. There was a period where it started to feel heavy-handed, but I think I’m back to liking it. I like how explicit you have to be when applying any margin at all. Personally, I’d rock padding: 0; too, as list elements tend to have some padding pushing them around. If you’re nuking spacing stuff, may as well nuke it all.

html, body {
  height: 100%;

Probably a good plan. Josh says “Allow percentage-based heights in the application,” which I can’t say comes up much in my day-today, but what it does is stuff like the body background not filling the space the way you might expect it to.

Too bad body { height: 100vh; } isn’t enough here, but I feel like that’s not as reliable for some reason I can’t think of right now. Maybe something to do with the footer navigation in iOS Safari?

body {
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;

I can’t get into the -webkit-font-smoothing: antialiased; thing. I think it tends to make type dramatically thin and I don’t love it. I don’t mind it as a tool, but I wouldn’t globally apply it on all my projects.

I also generally like to put global typographic sizing stuff on the html selector instead, just because the “root” part of rem implies the <html> element — not the <body> — and I like sizing stuff in rem and then adjusting the root font-size at the root level in media queries.

That 1.5 value feels like a good default line-height (more of a 1.4 guy myself, but I’d rather go up than down). But as soon as it’s set, I feel magnetically pulled into reducing it for heading elements where it’s always too much. That could happen via h1, h2, h3 kinda selectors (maybe h4h6 don’t need it), but Josh has some CSS trickery at work with this snippet that didn’t make it into the final reset:

* {
  line-height: calc(1em + 0.5rem);

That’s clever in how the 0.5rem goes a long way for small type, but isn’t as big of an influence for large type. I could see trying that on a greenfield project. Prior art here is by Jesús Ricarte in “Using calc to figure out optimal line-height.”

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;

Good move for a CSS reset. The block display type there prevents those annoying line-height gaps that always kill me. And you almost never want any of these media blocks to be wider than the parent. I somehow don’t think picture is necessary, though, as it’s not really a style-able block? Could be wrong. I’d probably toss iframe and object in there as well.

p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;

Good move for sure. It’s bad news when a long word (like a URL) forces an element wide and borks a layout. I tend to chuck this on something — like article or .text-content or something — and let it cascade into that whole area (which would also catch text that happens to be contained in an improper element), but I don’t mind seeing it on specific text elements.

If doing that, you probably wanna chuck li, dl, dt, blockquote on that chain. Despite having attempted to research this several times (here’s a playground), I still don’t 100% know what the right cocktail of line-wrapping properties is best to use. There is word-break: break-word; that I think is basically the same thing. And I think it’s generally best to use hyphens: auto; too… right??

#root, #__next {
  isolation: isolate;

I don’t quite understand what’s happening here. I get that this is a React/Next thing where you mount the app to these roots, and I get that it makes a stacking context, I just don’t get why it’s specifically useful to have that stacking context at this level. At the same time, I also don’t see any particular problem with it.

All in all — pretty cool! I always enjoy seeing what other people use (and go so far as to suggest) for CSS resets.