My CSS reset

A quick breakdown of how I reset the browser's default styling before I start writing my first lines of CSS.

What's a 'CSS reset'?

Every browser has their own default CSS styling for elements. A CSS reset is a set of styles which help even out the inconsistencies between each browser. Even though browsers are getting more and more alike there's still a few things I like to "reset" before I start writing the CSS for my project.

The reset

Previously I used Eric Meyer's classic CSS reset whenever I started a project. Nowadays I just reuse some of his styles, a combination of Josh Comeau's and Andy Bell's resets, and some of my own.

Language: css
*,
*::before,
*::after {
    box-sizing: border-box;
}

* {
    margin: 0;
}

body {
    line-height: 1.5;
}

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

input,
button,
textarea,
select {
    font: inherit;
}

button {
    color: inherit;
    border: 1px solid currentColor;
    background-color: transparent;
    border-radius: 0;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

a {
    color: inherit;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

Breakdown

Here's what's what.

1. Box-sizing

Language: css
*,
*:before,
*:after {
   box-sizing: border-box;
}

The default box-sizing is content-box, meaning that the width/height of an element is determined by it's padding, border and width/height. An element with width: 200px and padding: 40px will be 280px (40px on the left side and 40px on the right side) wide. There are so few scenarios where I would want that to happen that it's best to reset it to a more valuable default.

This reset makes sure that every element has the right box-sizing by using the *-selector and it's psuedo elements.

2. Removing all margins

Language: css
* {
   margin: 0;
}

Yes, you read that right. I remove all margins. Why? Because I want to explicitly set them myself. There's so few cases where the default margins of elements help me. The only real use case I can think of is wherever there's HTML generated from a rich text field in a CMS and I have no control over the markup. But even then I still want to fix the spacing myself with a combination of a parent class and some variant of the lobotomized owl selector.

3. Body

Language: css
body {
    line-height: 1.5;
}

The body is the parent of everything. I give it line-height: 1.5 so that the text on my site has a nicer line-height than the default. Sometimes I even go with 1.6 to let the text breath even more.

Remember: this doesn't mean that I don't have tighter line-heights on other elements. I override this wherever I see fit, like for buttons or headings.

4. Avoid overflowing images

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

By default, if the width of an image is wider than its container, it will overflow the container. max-width: 100% takes care of this problem.

Images are also inline by default, so writing display: block makes them easier to work with, like adding margin for instance.

5. Change the default link styling

Language: css
a {
    color: inherit;
}

Unstyled links are blue. color: inherit makes them the same color as its closest parent's color (and if no parent is found it fallbacks to the default text color of the document). This is nice for links in menus or something, but perhaps not the best fallback for rich text. There are accessibility concerns here, as the blue default have become the de facto standard for links on the web. However, I'm taking my chances and always try to make sure that my links differentiate enough from normal text.

I do keep the default underline, so that's a good thing.

6. Fix the font on input elements

Language: css
input,
button,
textarea,
select {
    font: inherit;
}

It's so frickin stupid that I have to even write this reset, but input elements (like the ones above) does not inherit things like font-family, line-height, color or font-size from body by default.

The font: inherit shorthand thankfully takes care of this.

FYI, this could also have been written like below, but I prefer the simplicity of using the shorthand for the sole reason that it's fewer lines.

Language: css
input,
button,
textarea,
select {
  font-family: inherit;
  font-size: inherit;
  font-stretch: inherit;
  font-style: inherit;
  font-variant: inherit;
  font-weight: inherit;
  line-height: inherit;
}

7. Remove the default button styling

Language: css
button {
    color: inherit;
    border: 1px solid currentColor;
    background-color: transparent;
    border-radius: 0;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

Buttons look like buttons by default, but I prefer to remove all styling and start from scratch. It's a bit risky, so in case you don't have control over all the HTML in your project you shouldn't do this.

I also add cursor: pointer so that the cursor changes to a hand when hovering. However, not everyone is a fan of this. Here I would have to disagree a little bit with my idol Adam Silver. We as users are so used to seeing the cursor hand on buttons (find me a website that doesn't have it on their search or menu buttons) that I believe the conventions have changed.

iOS annoys me

iOS does this thing with buttons that if you double-tap them (which you often do by accident) you'll zoom in on them. touch-action: manipulation removes this odd behaviour.

The curious -webkit-tap-highlight-color is added to remove iOS Safari's irritating effect that appears when you tap a button with your finger.

Be cautious of both these in case they serve some good in the case of accessibility, but for now I don't know if they do.

8. Recude motion for people who prefers reduced motion

Language: css
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

This is taken straight from a previous version of Adam Bell's CSS reset. It's a nifty little hack to prevent you from displaying animations to users who prefers less movement when browsing.

Conclusion

That's it, that's my go-to CSS resets. Keep in mind that I still revert the browser's user agent styles here and there throughout a project (like .some-class-name {list-style: none}), but the above-mentioned styles are the ones I need to reset/revert on a global level.