The idea of CSS resets is fascinating to me. There’s something about bringing order to a chaotic system that is really pleasing. And also fine-tuning all of the rules to work just right for a particular project or use case.

Everyone has their own take on CSS resets (including me), and I love picking through them to see what I can learn.

Andy Bell recently wrote about his. I agree with him here:

In this modern era of web development, we don’t really need a heavy-handed reset, or even a reset at all, because CSS browser compatibility issues are much less likely than they were in the old IE 6 days. That era was when resets such as normalize.css came about and saved us all heaps of hell. Those days are gone now and we can trust our browsers to behave more, so I think resets like that are probably mostly redundant.

Modern CSS resets can be a lot leaner than resets of the past.

Andy has an interesting technique for handling resets on elements that typically have pretty good user defaults, like lists.

I will mention the situation with lists, though. I select only lists that do have a class attribute because if a plain ol’ <ul> or <ol> gets used, I want it to look like a list. A lot of resets, including my previous ones, aggressively remove that.

That ends up looking something like this:

/* Remove default padding */
ol[class] {
  padding: 0;

I think this technique is great, expecially if you’re working in a pure CSS or CSS preprocessor environment (or when you’re writing pure HTML/Markdown/etc). This doesn’t work for me because I often use MDX to replace the rendering of pure HTML elements with custom React components, and those usually have class names applied via Styled Components.

A few more bits from Andy that I will be stealing for my own reset:

body {
  scroll-behavior: smooth;

Not all browsers support that yet (Firefox does), but it doesn’t hurt to add it to projects now so that they get smooth scrolling once browsers get on board.

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

Remove animations for folks who set their OS to reduce motion. Brilliant.

If you want to dive right into the code, Andy’s reset is also on GitHub.

Another one of my favorite reset projects is CSS Remedy from the Mozilla development team (primarily Jen Simmons, I believe. Thanks Jen!)

CSS Remedy is a bit different than other resets:

CSS Remedy sets CSS properties or values to what they would be if the CSSWG were creating the CSS today, from scratch, and didn’t have to worry about backwards compatibility.

So many web developers have struggled with the quirks of CSS and wished we could do something about it, so it’s cool to see browser developers weigh on on how they might solve some of those problems.

I really encourage you to dig through the CSS Remedy code yourself. It’s all beuatifully commented and documented. It’s also very cool to read through the issues and pull requests on GitHub to see how best practices evolve as folks weigh in with their use cases.