CSS Reset vs Normalize vs Layer
Reset wipes UA styles, normalize preserves useful defaults consistently, layers order both — pick a base strategy without fighting components.
- css
- reset
- normalize
Every page starts with the user-agent stylesheet: margins on body, list bullets, blue underlined links, bold headings. Resets strip those defaults aggressively. Normalize-style sheets make defaults consistent across browsers while keeping sensible behaviors. @layer decides whether your base loses to components and utilities on purpose.
Docs: MDN cascade, Reboot/Normalize history, modern alternatives like modern-normalize.
Reset (scorched earth)
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
}
html {
-webkit-text-size-adjust: 100%;
}
body {
min-height: 100%;
line-height: 1.5;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
list-style: none; /* apply carefully — see a11y note */
}
Classic resets zero margins on everything and remove list styles. That forces you to re-add spacing and list semantics styling — good for design systems with intentional type ramps; noisy for content sites.
A11y note: if you remove list markers with list-style: none, some VoiceOver versions historically stopped announcing lists unless you compensate (e.g. role="list" or other mitigations). Prefer intentional list styling over blind global nukes.
Normalize / opinionated base
Normalize aims for predictable UA behavior:
- Correct
displayon HTML5 elements - Consistent heading sizes / form font inheritance
- Fix legacy browser bugs
@layer reset {
/* excerpt of a modern base, not a full library copy */
body {
margin: 0;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
button,
input,
select,
textarea {
font-family: inherit;
font-size: 100%;
}
}
You’re not inventing design — you’re removing cross-browser surprises.
Layer them so utilities win
@layer reset, base, components, utilities;
@layer reset {
/* modern-normalize or your reset */
}
@layer base {
body {
font-family: var(--font-sans);
color: var(--text);
background: var(--surface);
}
a {
color: var(--link);
}
:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
}
Without layers, a reset shipped late in the bundle can clobber component CSS. With layers, order is explicit.
Which to pick
| Context | Strategy |
|---|---|
| Design system / app shell | Minimal reset + tokens + components in layers |
| Content/marketing site | Lighter normalize; keep heading defaults, tune type |
| Embedding third-party widgets | Don’t global-reset inside their subtree |
| Tailwind-like setup | Preflight (opinionated reset) + utilities layer |
Interview out-loud
“A reset removes most UA margins and defaults so the design system owns spacing. Normalize makes browsers behave consistently while keeping useful defaults. I put base styles in a low @layer under components and utilities so overrides don’t need specificity hacks. I’m careful with list-style resets for accessibility.”
Footguns
- Double-applying reset and a framework preflight.
- Resetting
buttonstyles then forgetting focus rings. * { margin: 0 }without a spacing system — inconsistent ad-hoc margins return.- Unlayered reset after layered components.
- Copy-pasting a 2012 reset with obsolete IE fixes and aggressive
outline: none.
Minimal modern reset many apps need
Beyond box-sizing and margin zero on body:
@layer reset {
img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: anywhere; }
:focus:not(:focus-visible) { outline: none; }
:focus-visible { outline: 2px solid var(--brand, #0b6bcb); outline-offset: 2px; }
}
That last focus pair prevents mouse-focus rings without killing keyboard visibility — better than a blunt global outline: none.
Related
- Cascade layers @layer
- CSS architecture ITCSS overview
- box-sizing border-box
- Outline vs border for focus
Further reading
Related guides
- Accent Color and Form ControlsUse accent-color to theme native checkboxes, radios, ranges, and progress — what it paints, what it skips, and when to custom-style instead.
- Auto-fit vs Auto-fillauto-fit collapses empty tracks; auto-fill keeps them. Use both with minmax for responsive card grids without media-query soup.
- BEM Naming MethodologyBlock, Element, Modifier naming for CSS — how it limits specificity wars, what to name, and when utility or CSS modules beat strict BEM.
- blend-mode Basicsmix-blend-mode vs background-blend-mode — how pixels combine, isolation, and the stacking/readability traps in product UI.
- box-sizing border-boxWhy border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.