Type something to search...
CSS Resets vs. Normalize.css: Which Should You Use?

CSS Resets vs. Normalize.css: Which Should You Use?

Every browser ships with a default stylesheet. It's the reason an unstyled h1 is large and bold, a ul has bullets and indentation, and body has a small margin around the page. These defaults are called the user agent stylesheet, and while they're broadly similar across browsers, they're not identical. Small differences in margins, form control fonts, or how certain elements display can make the same page look slightly different in Chrome, Firefox, and Safari.

For as long as developers have cared about that, there have been two schools of thought on what to do about it. One says: reset everything to zero and build up from a blank slate. The other says: normalize the defaults so they're consistent, but keep the useful ones. This article compares the two approaches, looks at what each actually does, and helps you decide which fits your project in 2026.

Why Browser Defaults Matter

Before comparing solutions, it helps to be clear about the problem. Browser defaults cause two separate kinds of trouble.

The first is inconsistency. Historically, browsers disagreed on things like the default font size of h1 inside article, the line height of form controls, the display type of HTML5 elements, and how sub and sup affected line height. Those differences meant a layout could look correct in one browser and slightly off in another.

The second is opinionated defaults. Even when every browser agrees, many defaults don't suit a modern design. Headings have large margins. Lists have padding. Buttons use a system font rather than your site's font. Images are inline elements, which leaves a small gap below them. These aren't bugs, but you'll override them in almost every project.

Resets and normalizers address these two problems differently.

What a CSS Reset Does

A CSS reset removes most or all browser default styling. The idea is that if every element starts from zero, there are no inconsistencies left to worry about, and every visual decision is yours.

The best-known historical example is Eric Meyer's Reset CSS, which set margins, padding, borders, and font sizes to zero or inherit for a long list of elements:

/* An excerpt in the spirit of Meyer's reset */
html,
body,
div,
span,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
em,
img,
strong,
ol,
ul,
li,
form,
label,
table,
tr,
th,
td {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

ol,
ul {
  list-style: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

After this, an h1 looks exactly like a paragraph, and lists have no bullets. Everything is visually flat until you style it.

The more aggressive extreme is the universal reset:

* {
  margin: 0;
  padding: 0;
}

It's short, but it strips spacing from everything, including form controls, where browser defaults are often helpful.

Advantages of a Reset

  • Total control. Nothing appears on the page that you didn't write.
  • Predictability. You never inherit a surprise margin from an element you forgot about.
  • Good fit for component systems. When every element is styled through components or utility classes, default styles mostly get in the way.

Disadvantages of a Reset

  • You have to restyle everything. Headings, lists, emphasis, and tables all need styles again, even for simple content like a blog post rendered from Markdown.
  • Semantic cues can disappear. Removing list-style from lists can have accessibility side effects. Safari, for example, has historically not announced a ul as a list to VoiceOver when its list styling is removed, unless it has an explicit role="list".
  • Noisy DevTools. A long reset selector list shows up on every element you inspect.

What Normalize.css Does

Normalize.css, created by Nicolas Gallagher and Jonathan Neal, takes the opposite approach. Instead of removing defaults, it keeps the useful ones and fixes the inconsistent ones, so every browser renders elements the same way.

A few examples of the kinds of rules it contains:

/* Correct the line height in all browsers and prevent
   font size adjustments after orientation changes in iOS. */
html {
  line-height: 1.15;
  -webkit-text-size-adjust: 100%;
}

/* Render the main element consistently in IE. */
main {
  display: block;
}

/* Correct the font size and margin on h1 elements
   within section and article contexts. */
h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/* Prevent sub and sup from affecting line height. */
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

/* Inherit fonts in form controls. */
button,
input,
select,
textarea {
  font-family: inherit;
  font-size: 100%;
  line-height: 1.15;
  margin: 0;
}

Every rule is documented with a comment explaining which browser behavior it fixes. After Normalize.css, an h1 still looks like a heading, lists still have bullets, and paragraphs still have margins. They just look the same everywhere.

Advantages of Normalize.css

  • Useful defaults stay. Content from a CMS or Markdown still looks reasonable without extra styling.
  • Targeted. It only changes what's inconsistent, so it has less impact on the cascade.
  • Well documented. Each rule explains what problem it solves.

Disadvantages of Normalize.css

  • You still override a lot. Normalize.css doesn't remove heading margins or list padding, so a design system usually ends up overriding them anyway.
  • Aging fixes. Many rules target browsers that are no longer relevant, like Internet Explorer and old versions of Edge and Firefox. The original Normalize.css hasn't had a major release in years, so it carries fixes modern sites no longer need.

What About Modern Alternatives?

The line between resets and normalizers has blurred. Most popular base stylesheets today mix both ideas: normalize the handful of real inconsistencies that remain, then apply a few opinionated defaults that nearly every project wants.

A few well-known options:

  • modern-normalize by Sindre Sorhus is a trimmed-down, actively maintained take on Normalize.css that drops old browser fixes and adds sensible defaults like box-sizing: border-box.
  • sanitize.css by Jonathan Neal (a co-author of Normalize.css) combines normalization with opinionated defaults, such as border-box sizing and inheriting fonts in form controls.
  • Custom modern resets, like those popularized by Josh W. Comeau and Andy Bell, are short, readable stylesheets you copy into your project and adjust. They typically set box-sizing, remove default margins, make images block-level and responsive, and make form controls inherit fonts.
  • Framework preflights. Tailwind CSS includes Preflight, a base layer built on modern-normalize with more aggressive resets on top, such as removing heading styles and list styles.

These are closer to each other than the old "reset vs. normalize" debate suggests. Most of them agree on a small set of rules.

How Much Inconsistency Is Left in 2026?

The honest answer is: much less than when Normalize.css was created. Browsers now follow the HTML specification's rendering section closely, Internet Explorer is gone, and evergreen browsers update constantly. Many of the historical inconsistencies that justified a big normalizer have simply disappeared.

What still tends to matter:

  • Form controls. Buttons, inputs, and selects don't inherit the page font by default, and their sizing and appearance vary between engines.
  • Box sizing. The default content-box model is still the default everywhere, and most developers find border-box easier.
  • Media elements. Images and videos are inline by default, which leaves a gap below them from the text baseline.
  • Text size adjustment on mobile. iOS Safari can inflate text in landscape orientation unless you control it with text-size-adjust.
  • Heading sizes in sectioning elements. The HTML spec has been updated to remove the rule that shrinks h1 inside article and section, and browsers have been rolling out that change, so older and newer versions can still differ. Setting an explicit font-size on headings sidesteps it.

That's a short list, and it's why many teams now write a small custom base stylesheet instead of pulling in a large library.

Side-by-Side Comparison

AspectCSS ResetNormalize.css
PhilosophyRemove defaultsKeep and fix defaults
Headings after applyingLook like body textLook like headings
Lists after applyingNo bullets or paddingBullets and padding kept
Amount you must restyleEverythingOnly what you want to change
Good forDesign systems, app UIsContent-heavy sites, prototypes
Cascade impactBroadNarrow
Maintenance statusVaries (often copy-and-own)Original is largely unchanged; modern forks are active

Which Should You Use?

There's no single right answer, but here's a practical way to decide.

Choose a Reset If

  • You're building an application or design system where nearly every element is styled through components.
  • You use a utility-first framework, which almost certainly includes its own reset layer already.
  • You want every piece of spacing and typography to come from your own tokens.

In that case, a modern, minimal reset is a better choice than a classic heavy one. You get a blank slate without breaking form controls or list semantics.

Choose a Normalizer If

  • Your site renders a lot of long-form content from Markdown, a CMS, or user input, where you want reasonable defaults for elements you didn't specifically style.
  • You're building a quick prototype or a documentation site.
  • You'd rather adjust defaults than rebuild them.

In that case, modern-normalize is a good starting point, since it's maintained and doesn't carry legacy browser fixes.

Or Combine the Two

Many projects end up with a hybrid: a light normalizer or modern reset for the base, followed by a small layer of element styles for typography. With cascade layers, you can keep the base firmly beneath everything else:

@layer reset, base, components, utilities;

@import url("modern-normalize.css") layer(reset);

@layer base {
  h1,
  h2,
  h3 {
    line-height: 1.2;
    text-wrap: balance;
  }

  p {
    text-wrap: pretty;
  }
}

Because reset is the first layer declared, anything in base, components, or utilities beats it regardless of selector specificity. That solves one of the classic complaints about resets: long selector lists that made later styles harder to apply. Cascade layers are supported in all current major browsers. One caveat: @import rules must come before other rules in a stylesheet (apart from @charset and layer statements like the first line here), and each import is an extra request unless your build tool bundles it.

Common Mistakes

Using both a full reset and Normalize.css. They work against each other. The reset strips what the normalizer carefully fixes. Pick one approach.

Removing focus outlines in a reset. Some old resets included outline: 0 on everything. That makes a site unusable for keyboard users. If you want custom focus styles, replace the outline with :focus-visible styles rather than removing it.

Forgetting about third-party content. A universal reset affects embedded widgets and content you don't control. If you include those, scope your reset or use layers so their styles can still win where needed.

Treating the reset as untouchable. A copy-and-own reset is yours. If a rule causes more trouble than it solves in your project, remove it.

Conclusion

A CSS reset and Normalize.css solve related but different problems. A reset removes browser defaults so you can build from scratch. Normalize.css keeps the defaults but makes them consistent across browsers. In 2026, the inconsistencies that motivated Normalize.css are mostly gone, and the most popular solutions blend both ideas into a short, modern base stylesheet.

For most new projects, the practical choice is a small modern reset or modern-normalize, placed in a low-priority cascade layer. From there, you add only the base styles your design needs. If you want to go further and write your own, we cover how in Writing a Modern CSS Reset in 2026.

Tags :
Share :

Related Posts

A Complete Guide to CSS Container Queries

A Complete Guide to CSS Container Queries

For more than a decade, responsive design meant one thing: media queries. You asked the browser how wide the viewport was and adjusted your layout ac

Continue Reading
A Comprehensive Guide to Installing Next.js

A Comprehensive Guide to Installing Next.js

Next.js has emerged as a powerful framework for building React applications, offering features like server-side rendering, static site generation, an

Continue Reading
Advanced CSS with clamp(), min(), and max(): Simplifying Dynamic Styling

Advanced CSS with clamp(), min(), and max(): Simplifying Dynamic Styling

CSS has evolved significantly, and modern tools like clamp(), min(), and max() are powerful game-changers in dynamic styling. If you’ve struggl

Continue Reading