Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.

Use a CSS reset or normalize stylesheet

A CSS reset or normalize is used to ensure consistent styling across browsers.

Utilities
Quick take
Typical fix time 10 min
  • Choose normalize.css for preservation or modern reset for clean slate
  • Install with pnpm: `pnpm add normalize.css`
  • Import before your custom styles
  • Check if your CSS framework includes a built-in reset
Why it matters: CSS resets eliminate browser default inconsistencies—ensuring your designs look identical across Chrome, Firefox, Safari, and Edge.

Rule Details

A CSS reset or normalization eliminates browser default styles and provides a consistent foundation for custom styling across all browsers and devices. In practice that usually means reaching for normalize.css (opens in new tab) when you want sensible defaults preserved, or CSS Remedy (opens in new tab) when you want a more opinionated reset baseline.

Code Examples

Traditional CSS Reset (Meyer's Reset)

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/
 
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbrev, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
 
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}
 
body {
	line-height: 1;
}
 
ol, ul {
	list-style: none;
}
 
blockquote, q {
	quotes: none;
}
 
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
 
table {
	border-collapse: collapse;
	border-spacing: 0;
}

Normalize.css (Preserve Useful Defaults)

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
 
/* Document
   ========================================================================== */
 
/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */
 
html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}
 
/* Sections
   ========================================================================== */
 
/**
 * Remove the margin in all browsers.
 */
 
body {
  margin: 0;
}
 
/**
 * Render the `main` element consistently in IE.
 */
 
main {
  display: block;
}
 
/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */
 
h1 {
  font-size: 2em;
  margin: 0.67em 0;
}
 
/* Grouping content
   ========================================================================== */
 
/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */
 
hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}
 
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
 
pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}
 
/* Text-level semantics
   ========================================================================== */
 
/**
 * Remove the gray background on active links in IE 10.
 */
 
a {
  background-color: transparent;
}
 
/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */
 
abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}
 
/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
 
b,
strong {
  font-weight: bolder;
}
 
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
 
code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}
 
/**
 * Add the correct font size in all browsers.
 */
 
small {
  font-size: 80%;
}
 
/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
 
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
 
sub {
  bottom: -0.25em;
}
 
sup {
  top: -0.5em;
}
 
/* Embedded content
   ========================================================================== */
 
/**
 * Remove the border on images inside links in IE 10.
 */
 
img {
  border-style: none;
}
 
/* Forms
   ========================================================================== */
 
/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */
 
button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}
 
/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */
 
button,
input { /* 1 */
  overflow: visible;
}
 
/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */
 
button,
select { /* 1 */
  text-transform: none;
}
 
/**
 * Correct the inability to style clickable types in iOS and Safari.
 */
 
button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}
 
/**
 * Remove the inner border and padding in Firefox.
 */
 
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}
 
/**
 * Restore the focus styles unset by the previous rule.
 */
 
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}
 
/**
 * Correct the padding in Firefox.
 */
 
fieldset {
  padding: 0.35em 0.75em 0.625em;
}
 
/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */
 
legend {
  box-sizing: border-box; /* 1 */
  color: inherit; /* 2 */
  display: table; /* 1 */
  max-width: 100%; /* 1 */
  padding: 0; /* 3 */
  white-space: normal; /* 1 */
}
 
/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */
 
progress {
  vertical-align: baseline;
}
 
/**
 * Remove the default vertical scrollbar in IE 10+.
 */
 
textarea {
  overflow: auto;
}
 
/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */
 
[type="checkbox"],
[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}
 
/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */
 
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}
 
/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */
 
[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}
 
/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */
 
[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}
 
/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */
 
::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}
 
/* Interactive
   ========================================================================== */
 
/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */
 
details {
  display: block;
}
 
/*
 * Add the correct display in all browsers.
 */
 
summary {
  display: list-item;
}
 
/* Misc
   ========================================================================== */
 
/**
 * Add the correct display in IE 10+.
 */
 
template {
  display: none;
}
 
/**
 * Add the correct display in IE 10.
 */
 
[hidden] {
  display: none;
}

Modern CSS Reset (Andy Bell's Modern CSS Reset)

/* Modern CSS Reset by Andy Bell */
/* https://piccalil.li/blog/a-modern-css-reset */
 
/* Box sizing rules */
*,
*::before,
*::after {
  box-sizing: border-box;
}
 
/* Remove default margin */
* {
  margin: 0;
}
 
/* Remove list styles on ul, ol elements with a list role, 
   which suggests default styling will be removed */
ul[role='list'],
ol[role='list'] {
  list-style: none;
}
 
/* 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;
  }
}

CSS Remedy (Modern Approach)

/* CSS Remedy - A fresh approach to CSS resets */
/* https://github.com/mozdevs/cssremedy */
 
/* Use a better box model (opinionated) */
*,
::before,
::after {
  box-sizing: border-box;
}
 
/* Use a more readable tab size (opinionated) */
:root {
  tab-size: 4;
}
 
/* 1. Use a more readable tab size (opinionated)
   2. Correct the line height in all browsers
   3. Prevent adjustments of font size after orientation changes in iOS */
html {
  tab-size: 4; /* 1 */
  line-height: 1.15; /* 2 */
  -webkit-text-size-adjust: 100%; /* 3 */
}
 
/* Remove the margin in all browsers */
body {
  margin: 0;
}
 
/* Improve consistency of default fonts */
body {
  font-family:
    system-ui,
    -apple-system, /* Firefox supports this but not yet `system-ui` */
    'Segoe UI',
    Roboto,
    Helvetica,
    Arial,
    sans-serif,
    'Apple Color Emoji',
    'Segoe UI Emoji';
}
 
/* Allow percentage-based heights in the application */
html,
body {
  height: 100%;
}
 
/* Making sure code elements don't affect line-height */
code,
kbd,
samp,
pre {
  font-family:
    ui-monospace,
    SFMono-Regular,
    Consolas,
    'Liberation Mono',
    Menlo,
    monospace;
  font-size: 1em; /* Correct the odd `em` font sizing in all browsers */
}
 
/* Add the correct font weight in Chrome, Edge, and Safari */
b,
strong {
  font-weight: bolder;
}
 
/* Add the correct font size in all browsers */
small {
  font-size: 80%;
}
 
/* Remove the gray background on active links in IE 10 */
a {
  background-color: transparent;
}
 
/* Remove the border on images inside links in IE 10 */
img {
  border-style: none;
}
 
/* Change the fill color to match the text color in all browsers */
svg:not([fill]) {
  fill: currentColor;
}
 
/* Hide the overflow in IE */
svg:not(:root) {
  overflow: hidden;
}
 
/* Show the overflow in Edge and IE */
hr {
  overflow: visible;
}
 
/* Standardize the style used to render abbr elements */
abbr[title] {
  border-bottom: none; /* Remove the bottom border in Chrome 57- */
  text-decoration: underline; /* Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari */
  text-decoration: underline dotted; /* Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari */
}
 
/* Add the correct display in Edge and IE */
details {
  display: block;
}
 
/* Add the correct display in all browsers */
summary {
  display: list-item;
}
 
/* Add the correct display in IE */
template {
  display: none;
}
 
/* Add the correct display in IE 10 */
[hidden] {
  display: none;
}

Why It Matters

CSS resets eliminate browser default inconsistencies—ensuring your designs look identical across Chrome, Firefox, Safari, and Edge.

Framework Integration

Installing with Package Managers

# Normalize.css
pnpm add normalize.css
 
# Modern CSS Reset
pnpm add modern-css-reset
 
# CSS Remedy
pnpm add @csstools/css-remedy
 
# Sanitize.css
pnpm add sanitize.css

React Implementation

// App.jsx
import 'normalize.css' // Import at the top
import './App.css' // Your custom styles
 
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>My Application</h1>
      </header>
      <main>
        <p>Content with consistent styling across browsers</p>
      </main>
    </div>
  )
}
 
export default App

Next.js Implementation

// pages/_app.js
import 'normalize.css'
import '../styles/globals.css'
 
export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}
 
// Or with CSS imports in _document.js
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'
 
export default function Document() {
  return (
    <Html>
      <Head>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Vue.js Implementation

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import 'normalize.css'
import './assets/styles/main.css'
 
createApp(App).mount('#app')
<!-- App.vue -->
<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link>
      <router-link to="/about">About</router-link>
    </nav>
    <router-view/>
  </div>
</template>
 
<style>
/* Additional custom styles after reset */
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
 
nav {
  padding: 30px;
}
 
nav a {
  font-weight: bold;
  color: #2c3e50;
}
 
nav a.router-link-exact-active {
  color: #42b983;
}
</style>

Angular Implementation

// styles.scss (global styles)
@import '~normalize.css';
 
// Custom base styles
html {
  font-size: 16px;
  line-height: 1.5;
}
 
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  color: #333;
  background-color: #fff;
}
 
// Additional global styles
*, *::before, *::after {
  box-sizing: border-box;
}
 
img {
  max-width: 100%;
  height: auto;
}

Custom Reset Creation

Building Your Own Modern Reset

/* custom-reset.css - Modern CSS Reset */
 
/* 1. Use a more-intuitive box-sizing model */
*, *::before, *::after {
  box-sizing: border-box;
}
 
/* 2. Remove default margin and padding */
* {
  margin: 0;
  padding: 0;
}
 
/* 3. Allow percentage-based heights in the application */
html, body {
  height: 100%;
}
 
/* 4. Add accessible line-height and improve text rendering */
body {
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
 
/* 5. Improve media defaults */
img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
}
 
/* 6. Remove built-in form typography styles */
input, button, textarea, select {
  font: inherit;
}
 
/* 7. Avoid text overflows */
p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}
 
/* 8. Create a root stacking context */
#root, #__next {
  isolation: isolate;
}
 
/* 9. Remove list styles on ul, ol elements with a list role */
ul[role='list'], ol[role='list'] {
  list-style: none;
}
 
/* 10. Set core root defaults */
html:focus-within {
  scroll-behavior: smooth;
}
 
/* 11. Remove all animations and transitions 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;
  }
}
 
/* 12. Modern font stack */
body {
  font-family: 
    system-ui,
    -apple-system,
    'Segoe UI',
    Roboto,
    'Helvetica Neue',
    Arial,
    'Noto Sans',
    sans-serif,
    'Apple Color Emoji',
    'Segoe UI Emoji',
    'Segoe UI Symbol',
    'Noto Color Emoji';
}
 
/* 13. Improve consistency of default fonts for code */
code, kbd, samp, pre {
  font-family:
    ui-monospace,
    SFMono-Regular,
    'SF Mono',
    Consolas,
    'Liberation Mono',
    Menlo,
    monospace;
}
 
/* 14. Add the correct display in all browsers */
details {
  display: block;
}
 
summary {
  display: list-item;
}
 
template {
  display: none;
}
 
[hidden] {
  display: none;
}

Project-Specific Reset

/* project-reset.css - Tailored for specific project needs */
 
/* Base reset */
@import 'normalize.css';
 
/* Project-specific additions */
:root {
  --font-family-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
  --line-height-base: 1.6;
  --line-height-heading: 1.2;
}
 
html {
  font-size: 16px;
  scroll-behavior: smooth;
}
 
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}
 
body {
  font-family: var(--font-family-sans);
  line-height: var(--line-height-base);
  color: #1a1a1a;
  background-color: #ffffff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
 
/* Typography improvements */
h1, h2, h3, h4, h5, h6 {
  line-height: var(--line-height-heading);
  font-weight: 600;
  margin-bottom: 0.5em;
}
 
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.75rem; }
h4 { font-size: 1.5rem; }
h5 { font-size: 1.25rem; }
h6 { font-size: 1rem; }
 
p {
  margin-bottom: 1rem;
}
 
/* Link improvements */
a {
  color: #0066cc;
  text-decoration: none;
}
 
a:hover, a:focus {
  text-decoration: underline;
}
 
/* Form improvements */
button {
  cursor: pointer;
  border: none;
  background: none;
  font: inherit;
}
 
button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
 
input, textarea, select {
  width: 100%;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 0.5rem;
}
 
input:focus, textarea:focus, select:focus {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
  border-color: #0066cc;
}
 
/* Utility classes */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
 
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
}
 
@media (min-width: 768px) {
  .container {
    padding: 0 2rem;
  }
}

Build Tool Integration

Webpack CSS Reset Plugin

// webpack-css-reset-plugin.js
const fs = require('fs')
const path = require('path')
 
class CSSResetPlugin {
  constructor(options = {}) {
    this.options = {
      reset: options.reset || 'normalize', // 'normalize', 'modern', 'meyer', 'custom'
      customResetPath: options.customResetPath,
      inject: options.inject !== false, // Default to true
      ...options
    }
  }
  
  apply(compiler) {
    compiler.hooks.beforeRun.tapAsync('CSSResetPlugin', (compiler, callback) => {
      this.injectReset(compiler)
      callback()
    })
  }
  
  injectReset(compiler) {
    const resetCSS = this.getResetCSS()
    
    if (this.options.inject) {
      // Inject reset CSS into the main entry
      const entryPath = path.resolve(__dirname, 'src/reset-injection.js')
      
      const injectionCode = `
        // Auto-injected CSS Reset
        const resetCSS = \`${resetCSS}\`
        
        if (typeof document !== 'undefined') {
          const styleElement = document.createElement('style')
          styleElement.textContent = resetCSS
          document.head.insertBefore(styleElement, document.head.firstChild)
        }
      `
      
      fs.writeFileSync(entryPath, injectionCode)
      
      // Modify webpack entry to include reset
      const originalEntry = compiler.options.entry
      compiler.options.entry = [entryPath, originalEntry]
    }
  }
  
  getResetCSS() {
    switch (this.options.reset) {
      case 'normalize':
        return this.getNormalizeCSS()
      case 'modern':
        return this.getModernResetCSS()
      case 'meyer':
        return this.getMeyerResetCSS()
      case 'custom':
        if (this.options.customResetPath) {
          return fs.readFileSync(this.options.customResetPath, 'utf8')
        }
        throw new Error('Custom reset path not provided')
      default:
        return this.getNormalizeCSS()
    }
  }
  
  // CSS content methods would be implemented here...
}
 
module.exports = CSSResetPlugin

PostCSS Reset Plugin

// postcss-auto-reset.js
const postcss = require('postcss')
const fs = require('fs')
const path = require('path')
 
module.exports = postcss.plugin('postcss-auto-reset', (options = {}) => {
  return (root, result) => {
    const resetType = options.reset || 'normalize'
    const resetCSS = getResetCSS(resetType, options.customPath)
    
    // Parse reset CSS and prepend to existing CSS
    const resetRoot = postcss.parse(resetCSS)
    
    // Insert reset rules at the beginning
    resetRoot.each(node => {
      root.prepend(node.clone())
    })
  }
})
 
function getResetCSS(type, customPath) {
  switch (type) {
    case 'normalize':
      return require('normalize.css')
    case 'modern':
      return fs.readFileSync(path.join(__dirname, 'modern-reset.css'), 'utf8')
    case 'custom':
      return fs.readFileSync(customPath, 'utf8')
    default:
      return require('normalize.css')
  }
}
 
// Usage in postcss.config.js
module.exports = {
  plugins: [
    require('postcss-auto-reset')({
      reset: 'normalize'
    }),
    require('autoprefixer'),
    require('cssnano')
  ]
}

Testing CSS Reset Implementation

Automated Testing

// css-reset-tester.js
const puppeteer = require('puppeteer')
 
class CSSResetTester {
  async testReset(url) {
    const browser = await puppeteer.launch()
    const page = await browser.newPage()
    
    await page.goto(url)
    
    const resetTests = await page.evaluate(() => {
      const body = document.body
      const computedStyle = getComputedStyle(body)
      
      return {
        hasMargin: computedStyle.margin !== '0px',
        hasPadding: computedStyle.padding !== '0px',
        boxSizing: computedStyle.boxSizing,
        fontFamily: computedStyle.fontFamily,
        lineHeight: computedStyle.lineHeight
      }
    })
    
    // Test common elements
    const elementTests = await page.evaluate(() => {
      const elements = {
        h1: document.querySelector('h1'),
        p: document.querySelector('p'),
        ul: document.querySelector('ul'),
        button: document.querySelector('button'),
        input: document.querySelector('input')
      }
      
      const results = {}
      
      for (const [tag, element] of Object.entries(elements)) {
        if (element) {
          const style = getComputedStyle(element)
          results[tag] = {
            margin: style.margin,
            padding: style.padding,
            fontSize: style.fontSize,
            fontFamily: style.fontFamily
          }
        }
      }
      
      return results
    })
    
    await browser.close()
    
    return {
      body: resetTests,
      elements: elementTests
    }
  }
  
  validateReset(testResults) {
    const issues = []
    
    if (testResults.body.hasMargin) {
      issues.push('Body has default margin - reset may not be applied')
    }
    
    if (testResults.body.hasPadding) {
      issues.push('Body has default padding - reset may not be applied')
    }
    
    if (testResults.body.boxSizing !== 'border-box') {
      issues.push('Box-sizing not set to border-box - consider modern reset')
    }
    
    return {
      isValid: issues.length === 0,
      issues
    }
  }
}
 
// Usage
const tester = new CSSResetTester()
tester.testReset('https://example.com').then(results => {
  const validation = tester.validateReset(results)
  console.log('Reset Test Results:', validation)
})

Best Practices

  1. Choose Appropriately: Select reset based on project needs (normalize for preservation, modern for clean slate)
  2. Load First: Ensure reset CSS loads before other stylesheets
  3. Framework Awareness: Check if your CSS framework includes a reset
  4. Consistent Approach: Use the same reset across all pages
  5. Modern Techniques: Consider modern resets with better accessibility features
  6. Test Thoroughly: Verify reset works across all target browsers
  7. Document Choice: Document which reset is used and why
  8. Keep Updated: Regularly update reset to latest stable version

Choosing the Right Reset

Choose between normalize.css (opens in new tab) and CSS Remedy (opens in new tab) based on how much browser default behavior you want to preserve versus flatten.

Decision Matrix

Reset TypeUse CaseProsCons
Normalize.cssGeneral purpose, preserves useful defaultsConsistent across browsers, well-testedLarger file size, some unwanted defaults
Meyer's ResetComplete control, minimal starting pointSmall size, removes everythingToo aggressive, removes useful defaults
Modern ResetModern applications, accessibility-focusedIncludes modern best practicesNewer, less battle-tested
CSS RemedyProgressive enhancement approachThoughtful defaults, modern featuresStill in development
Custom ResetSpecific project needsTailored to exact requirementsMore maintenance, requires expertise

Framework Considerations

/* Bootstrap includes Reboot (based on Normalize) */
@import '~bootstrap/scss/bootstrap';
 
/* Tailwind CSS includes Preflight (modern reset) */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
 
/* Bulma includes a normalize-based reset */
@import '~bulma/bulma';

Remember to check if your chosen CSS framework already includes a reset to avoid conflicts or redundancy.

Verification

Automated Checks

  • Use browser or CI tooling where applicable to verify the fix.

Manual Checks

  • Confirm the rule in the final rendered output or runtime behavior.
  • Test one primary path and one edge case affected by the change.
  • Re-check shared abstractions so the fix is applied consistently.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Verify that a CSS reset or normalization is implemented to ensure consistent styling across different browsers and devices.

Fix

Auto-fix issues

Implement a modern CSS reset like normalize.css, CSS remedy, or a custom reset to eliminate browser default styling inconsistencies.

Explain

Learn more

Explain how CSS resets eliminate browser default styles to provide a consistent foundation for custom styling across all browsers.

Review

Code review

Review stylesheets, component styles, and responsive states related to Use a CSS reset or normalize stylesheet. Flag exact selectors, declarations, or breakpoints that violate the rule in the rendered UI.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

Chrome DevTools
developer.chrome.comTool

Rules that often go hand-in-hand with this one.

Include a print stylesheet

A print stylesheet is provided and correctly optimized for printed pages.

CSS
Avoid embedded and inline CSS

Embedded and inline CSS are avoided except for critical CSS and performance optimization.

CSS
Use @layer to manage CSS cascade order explicitly

CSS Cascade Layers (@layer) are used to give the codebase explicit, predictable control over specificity and cascade order, eliminating the need to fight specificity with !important.

CSS
Use :has() to style parent elements based on their descendants

Use the CSS :has() relational pseudo-class to select and style an element based on what it contains, replacing JavaScript DOM manipulation for many common styling scenarios.

CSS

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385