CSS: To reset or not to reset

by Simeon Petrov

Thumbnail for CSS: To reset or not to reset
  • CSS

Why “reset”?

The general idea of a “reset” file is pretty simple

The goal of a reset stylesheet is to reduce browser inconsistencies in things like default line heights, margins and font sizes of headings, and so on. https://meyerweb.com/eric/tools/css/reset/

And I’ll add that removing all these “inconsistencies” also contributes to a faster and easier workflow for the developers. Or at least for me. Because writing 30 times margin: 0px in a single file is nothing I’m looking forward to.

So in short - I like to “reset” my pages so I can start working on a clean canvas. The reset for me is not only handling the “inconsistencies” between the browsers, but also removing any unnecessary styles, that I will remove repeatedly later on.

Multiple approaches or files exist out there, most notorious being

And while all of these can do the job completely fine, the flavor I’ve chosen is Andy Bell's A Modern CSS Reset , but with a little twist…

My CSS reset

/* Box sizing rules */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Remove default margin */
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd {
  margin: 0;
}

/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
:where(ul[role="list"], ol[role="list"]) {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Remove all button styles when you have a class*/
:where(button[class]) {
  all: unset;
}

/* Set core root defaults */
html:focus-within {
  scroll-behavior: smooth;
}

/* Set core body defaults */
body {
  min-height: 100vh;
  text-rendering: optimizeSpeed;
  line-height: 1.5;
}

/* A elements that don't have a class get default styles */
a:not([class]) {
  text-decoration-skip-ink: auto;
}

/* Make images easier to work with */
img,
picture {
  max-width: 100%;
  display: block;
}

/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
  font: inherit;
}

/* Remove all animations, transitions and smooth scroll for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
  html:focus-within {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

The “Why” behind my changes

Lists

:where(ul[role="list"], ol[role="list"]) {
  list-style: none;
  margin: 0;
  padding: 0;
}

I’ve cleared out not only the list-style, but also the default margin and padding of a list element. Even if I decide to add some space in my list rarely it’s the same as the browser. Also adjusting the selector’s specific with :where() - this helps A LOT later on when you style your elements later on:

ul[role="list"] {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

.some-list-class{
  margin-bottom: 30px;
}

Having the example from above, combining the selectors for an element and attribute results in a total specificity points of 11 (element 1 + attribute 10), while targeting a list with a single class like .some-list-class has a specificity of 10 and the problematic nature of CSS arises.. We can deal with this with multiple classes, duplication of the class and so many other ways… or just simply strip the specificity with the usage of where() . You can read more about this here - Using the Specificity of :where() as a CSS Reset .

Buttons

:where(button[class]) {
  all: unset;
}

The (relatively new for me) all property does wonders with buttons - clearing all the default “junk” with a single line is pure magic. Again like in the List example, using :where() helps later on with the specificity overwriting.