CSS Reset vs. Normalize: Qual Abordagem Escolher em Projetos Modernos

Conteúdo técnico toda semana
Receba artigos sobre arquitetura, padrões de projeto e engenharia de software. Direto no seu e-mail, sem enrolação.
Sem spam. Cancele a qualquer momento com 1 clique.
Neste artigo
O Problema Invisível
Abra o mesmo HTML em Chrome, Firefox e Safari. Os três renderizam diferente.
Cada navegador aplica uma User Agent Stylesheet — um CSS padrão embutido. Margens em <body>, padding em <ul>, tamanho de fonte em <h1>. Tudo varia sutilmente entre browsers.
Esse é o problema que CSS Reset e Normalize tentam resolver. Mas fazem isso de formas radicalmente diferentes.
Escolher errado não quebra nada de forma óbvia. Porém gera horas de debugging em inconsistências visuais que parecem bugs fantasmas.
User Agent Stylesheets: A Raiz de Tudo
Antes de comparar soluções, entenda o problema. Veja o que o Chrome aplica por padrão a elementos comuns:
/* Chrome User Agent Stylesheet (simplificado) */
body {
margin: 8px;
}
h1 {
font-size: 2em;
margin-block-start: 0.67em;
margin-block-end: 0.67em;
font-weight: bold;
}
ul, ol {
padding-inline-start: 40px;
}
a:-webkit-any-link {
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}O Firefox usa valores similares, mas não idênticos. O Safari diverge mais. Essas diferenças mínimas se acumulam e criam inconsistências reais em layouts complexos.
CSS Reset: A Abordagem Nuclear
A filosofia do Reset é simples: destrua tudo e reconstrua do zero.
O mais famoso é o Reset de Eric Meyer, criado em 2008. Ele remove margens, paddings, bordas e estilos tipográficos de praticamente todos os elementos HTML.
/* Eric Meyer's CSS Reset v2.0 (2011) */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, 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 */
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;
}Vantagens do Reset
- Previsibilidade total. Nenhum estilo herdado. Você sabe exatamente o que cada elemento faz.
- Consistência cross-browser. Se tudo é zero, não há divergência.
- Controle absoluto. Ideal para design systems com especificações rígidas.
Desvantagens do Reset
- Você precisa reconstruir parte da apresentação. Títulos perdem sua diferenciação tipográfica e listas perdem os marcadores. No reset de Meyer v2 mostrado aqui, os links mantêm a cor e o sublinhado definidos pelo navegador, salvo outras regras da página.
- Mais CSS para escrever. O reset economiza linhas, mas força reescrita de estilos básicos que eram úteis.
- Acessibilidade em risco. Sem cuidado, elementos perdem affordances visuais importantes.
Normalize.css: A Abordagem Cirúrgica
O Normalize.css, criado por Nicolas Gallagher e Jonathan Neal, segue filosofia oposta: preserve os estilos úteis, corrija apenas as inconsistências.
npm install normalize.cssUso em um projeto React:
// src/main.tsx
import 'normalize.css';
import './styles/global.css';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);Veja trechos representativos do Normalize.css v8.0.1:
/* Normalize.css v8.0.1 (trechos selecionados) */
/**
* 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 */
}
/**
* 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;
}
/**
* 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 */
}
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}Note a diferença. Cada regra tem um comentário explicando qual bug específico ela corrige e em qual navegador.
Vantagens do Normalize
- Preserva defaults úteis. Headings continuam com tamanhos diferentes. Listas mantêm bullets.
- Menos CSS adicional. Você não precisa reconstruir a tipografia básica.
- Documentação inline. Cada regra é justificada.
- Amplamente testado. Usado no Bootstrap, HTML5 Boilerplate e milhares de projetos.
Desvantagens do Normalize
- Menos previsível. Você herda estilos que podem conflitar com seu design system.
- Ainda carrega fixes para IE. A versão 8.0.1 inclui correções para Internet Explorer que podem ser desnecessárias se esses navegadores estiverem fora da matriz de suporte do projeto.
- Não resolve tudo. Você ainda precisa de overrides para muitos elementos.
A Terceira Via: Modern CSS Reset
Em projetos modernos, nem o Reset clássico nem o Normalize puro são ideais. Surgiram abordagens híbridas que pegam o melhor dos dois mundos.
Andy Bell's Modern CSS Reset
/* Modern CSS Reset por Andy Bell (trecho adaptado) */
/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Prevent font size inflation */
html {
-moz-text-size-adjust: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
}
/* Remove default margin in favour of better control in authored CSS */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
margin-block: 0;
}
/* Remove list styles on ul, ol elements with a list role */
ul[role='list'],
ol[role='list'] {
list-style: none;
}
/* Set core body defaults */
body {
min-height: 100vh;
line-height: 1.5;
}
/* Set shorter line heights on headings and interactive elements */
h1,
h2,
h3,
h4,
button,
input,
label {
line-height: 1.1;
}
/* Balance text wrapping on headings */
h1,
h2,
h3,
h4 {
text-wrap: balance;
}
/* A elements that don't have a class get default styles */
a:not([class]) {
text-decoration-skip-ink: auto;
color: currentColor;
}
/* Make images easier to work with */
img,
picture {
max-width: 100%;
display: block;
}
/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
font-family: inherit;
font-size: inherit;
}
/* Make sure textareas without a rows attribute are not tiny */
textarea:not([rows]) {
min-height: 10em;
}
/* Anything that has been anchored to should have extra scroll margin */
:target {
scroll-margin-block: 5ex;
}Essa abordagem é cirúrgica e moderna. Usa margin-block ao invés de margin. Aplica text-wrap: balance. Remove list-style apenas quando há role="list" — preservando acessibilidade.
Tailwind CSS Preflight
Se você usa Tailwind, já tem um reset embutido. O Preflight é baseado no modern-normalize com adições opinativas:
npm install -D tailwindcss @tailwindcss/vite/* O Preflight do Tailwind v4 é incluído automaticamente */
/* Mas você pode importar apenas o reset: */
@import "tailwindcss/preflight";O que o Preflight faz internamente:
/* Trechos do Preflight (Tailwind v4) */
*,
::after,
::before,
::backdrop,
::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html,
:host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
-webkit-tap-highlight-color: transparent;
}
img,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
img,
video {
max-width: 100%;
height: auto;
}O Preflight é agressivo. Remove todas as margens, zera paddings, remove bordas. É basicamente um Reset moderno, não um Normalize.
Comparação Prática: O Mesmo Componente
Veja como um card simples se comporta com cada abordagem:
// components/ArticleCard.tsx
export function ArticleCard() {
return (
<article>
<h2>Título do Artigo</h2>
<p>Um parágrafo com <strong>texto em negrito</strong> e um <a href="#">link</a>.</p>
<ul>
<li>Item um</li>
<li>Item dois</li>
<li>Item três</li>
</ul>
</article>
);
}Com Reset (Eric Meyer)
O <h2> passa a herdar a tipografia e a lista perde os marcadores. O reset de Meyer v2 não remove a cor nem o sublinhado dos links. Margens, tipografia e listas precisam receber os estilos que o projeto deseja.
Com Normalize
O <h2> mantém tamanho maior. A lista tem bullets. O link tem underline e cor azul. Parece "normal". Mas a margem do <h2> pode conflitar com seu spacing system.
Com Modern Reset (Andy Bell)
O <h2> perde margem mas mantém tamanho (herda do browser). A lista mantém bullets (sem role="list"). O link sem classe mantém estilos padrão. É o equilíbrio.
Criando Seu Próprio Base CSS
Em projetos sérios, recomendo criar uma base customizada. Aqui está meu template:
/* src/styles/base.css */
/* ========================================
1. BOX MODEL
======================================== */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* ========================================
2. RESET DE MARGENS
======================================== */
body,
h1, h2, h3, h4, h5, h6,
p,
figure,
blockquote,
dl, dd {
margin: 0;
}
/* ========================================
3. HTML & BODY
======================================== */
html {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
body {
min-height: 100dvh;
line-height: 1.6;
font-family: system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ========================================
4. TIPOGRAFIA
======================================== */
h1, h2, h3, h4, h5, h6 {
line-height: 1.2;
text-wrap: balance;
overflow-wrap: break-word;
}
p {
text-wrap: pretty;
overflow-wrap: break-word;
}
/* ========================================
5. MEDIA
======================================== */
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
img {
height: auto;
font-style: italic; /* Alt text styling */
}
/* ========================================
6. FORMULARIOS
======================================== */
input, button, textarea, select {
font: inherit;
color: inherit;
}
button {
cursor: pointer;
}
/* ========================================
7. LISTAS
======================================== */
ul[role='list'],
ol[role='list'] {
list-style: none;
padding: 0;
}
/* ========================================
8. LINKS
======================================== */
a {
color: inherit;
text-decoration-skip-ink: auto;
}
/* ========================================
9. ACESSIBILIDADE
======================================== */
:target {
scroll-margin-block: 5ex;
}
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
/* Remove animacoes para quem prefere */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}Importe como primeiro arquivo CSS do projeto:
// src/main.tsx
import './styles/base.css';
import './styles/tokens.css';
import './styles/components.css';
import App from './App';Quando Usar Cada Abordagem
A decisão depende do contexto. Aqui está meu framework de decisão:
Use Normalize quando:
- Está construindo um site de conteúdo (blog, documentação).
- Quer defaults sensatos sem muito CSS custom.
- A equipe é pequena e não tem um design system.
Use Reset quando:
- Tem um design system completo com tokens definidos.
- Cada pixel é especificado no Figma.
- Usa CSS-in-JS onde cada componente define seus próprios estilos.
Use Modern Reset (recomendado) quando:
- Projetos React, Next.js, Vue modernos.
- Quer controle sem destruir defaults úteis.
- Se preocupa com acessibilidade.
Use Preflight (Tailwind) quando:
- Já usa Tailwind CSS. Não adicione outro reset por cima.
Minha Opinião Sincera
O Normalize.css está morto para projetos novos. Lá, eu disse.
O Normalize.css 8.0.1 inclui correções para navegadores antigos. Antes de adotá-lo, compare suas regras com a matriz de navegadores do projeto e mantenha as que ainda forem necessárias.
O Reset do Eric Meyer também é uma relíquia. Foi revolucionário em 2008. Hoje, zerar font: inherit em todos os elementos e depois reconstruir tudo é trabalho desnecessário. É como demolir uma casa para trocar o piso.
O que eu uso em todo projeto novo: um Modern CSS Reset customizado com ~50 linhas. O template que mostrei acima cobre 99% dos casos. Ele reseta o que precisa (margens, box-sizing), preserva o que é útil (tamanhos de heading, list-style condicional) e adiciona melhorias modernas (text-wrap: balance, 100dvh, prefers-reduced-motion).
Se você usa Tailwind, não adicione nada. O Preflight já faz o trabalho. Adicionar Normalize por cima do Preflight é redundância que vi em projetos reais — e gera conflitos sutis.
Uma crítica que faço ao Preflight: ele é agressivo demais com links e headings. Remove toda diferenciação visual. Em projetos sem Tailwind aplicado a cada elemento (tipo durante prototipação), a página vira um bloco uniforme de texto. Isso atrapalha o desenvolvimento iterativo.
A verdade inconveniente é que a maioria dos desenvolvedores nunca leu o CSS base que importa. Copiam import 'normalize.css' de um tutorial de 2019 e seguem em frente. Depois gastam horas debugando por que o <button> não herda a font-family ou por que o <img> tem um gap misterioso embaixo.
Leia seu reset. Entenda cada linha. Remova o que não precisa. Adicione o que falta.
Cinquenta linhas de CSS intencional vencem 500 linhas de CSS copiado. Sempre.
Quando NAO usar CSS Reset (e o que fazer em vez disso)
Antes de copiar aquele reset.css do Eric Meyer no seu projeto, pare e avalie. Existem cenarios onde um CSS Reset completo trabalha contra voce:
1. Projetos com componentes de terceiros
Se você usa Material UI, Chakra, Ant Design ou outro design system, confira primeiro a base CSS recomendada pela biblioteca. Um reset global pode interferir nos componentes, dependendo da ordem, das camadas e da especificidade dos estilos.
O que fazer: use a base recomendada pela biblioteca e teste a integração antes de adicionar outra. Normalize preserva diversos estilos padrão. O Preflight do Tailwind é mais opinativo: remove margens, redefine bordas e tira a estilização padrão de títulos e listas. Ele também pode exigir ajustes ao integrar componentes de terceiros.
2. Landing pages rapidas e MVPs
Num projeto que precisa ir ao ar em dias, nao em semanas, cada minuto conta. O browser default ja renderiza headings maiores que paragrafos, links azuis clicaveis e listas com bullets. Um reset remove tudo isso e te obriga a reescrever do zero.
O que fazer: Comece com os defaults do browser. Adicione box-sizing: border-box e poucas regras globais. Refine depois.
3. Projetos com muito conteudo editorial
Blogs, documentacoes e sites de conteudo dependem da hierarquia visual nativa do HTML. Se voce resetar tudo, um <h1> fica igual a um <p>. A experiencia de leitura degrada silenciosamente.
O que fazer: Aplique Normalize com ajustes pontuais. Mantenha a diferenciacao semantica visual.
A regra de ouro: Se voce nao sabe explicar o que cada linha do seu reset faz, voce nao deveria estar usando ele.
Leia também

Escrito por
Marcos Soares
Fullstack Developer · CEO da Agência Poti
Fullstack Developer e CEO da Agência Poti. Mais de 20 anos construindo arquiteturas cloud-native com React, Next.js e sistemas distribuídos. Parceiro comercial do estúdio iellou design. Fundador do Vivo de Código.
Comentários
Participe da discussão
Seja o primeiro a comentar!
Continue Aprofundando
Conteúdo técnico toda semana
Receba artigos sobre arquitetura, padrões de projeto e engenharia de software. Direto no seu e-mail, sem enrolação.
Sem spam. Cancele a qualquer momento com 1 clique.


