CSS Reset Moderno com @layer: O que muda no reseter.css 3 e Como Instalar

reseter.css 3 é um CSS reset moderno que coloca todo seu código em @layer reset: qualquer CSS que você escrever fora de um layer vence, independentemente da especificidade ou da ordem de carregamento. Essa mudança corrige o erro mais comum dos resets escritos manualmente e chega junto com propriedades lógicas, um build com Lightning CSS e várias mudanças visuais que convém revisar antes de atualizar.

:white_check_mark: yoDEV Testado · 15 de outubro de 2026 Instalamos reseter.css 2.1.0 e 3.0.1 do npm e os comparamos no Chromium 141 sem interface contra um reset escrito manualmente, em três cenários de ordem de carregamento e de layers. Os resultados que reportamos como nossos saem desse teste.

O que é um CSS reset moderno?

Um CSS reset elimina os estilos que cada navegador aplica por padrão (margens, indentação de listas, fontes dos formulários, imagens inline) para que você parta de uma base previsível. Um modern CSS reset vai além: não coloca tudo em zero. Conserva os valores razoáveis (os títulos mantêm suas margens, as listas sua indentação), aplica box-sizing: border-box a todos os elementos, usa propriedades lógicas para funcionar também em layouts da direita para a esquerda e foi pensado para que seus estilos sempre vençam.

Esse último ponto é onde quase todos falham. Um reset deveria ser o CSS mais fraco da página. Na prática, os resets escritos manualmente costumam usar seletores mais fortes que os estilos dos componentes que vêm depois.

CSS reset ou Normalize.css: qual usar?

Normalize.css não apaga os estilos do navegador: os iguala entre navegadores e conserva os que são úteis. Um reset parte de uma base mais limpa e decide ele mesmo os valores padrão. reseter.css 3 se situa em um ponto intermediário: remove margens e preenchimentos com o seletor universal, mas os devolve com valores de navegador em títulos e listas.

A documentação oficial do reseter.css inclui uma tabela comparativa. Segundo essa tabela, reseter.css visa navegadores com mais de 3 por cento de uso global e Normalize.css as últimas três versões de cada navegador. Além disso, reseter.css publica uma versão minificada pronta para usar, enquanto que com Normalize.css você tem que minificá-la você mesmo.

O que @layer muda na especificidade CSS de um reset?

Com as camadas em cascata (cascade layers, @layer) você decide qual grupo de estilos vence antes de que entre em jogo a especificidade CSS. Os estilos que não estão em nenhum layer vencem todos os que estão. Como o reset vive em @layer reset e o CSS da sua aplicação não tem layer, sua aplicação vence, use o seletor que usar cada lado.

Testamos o erro clássico. Um reset escrito manualmente costuma ter algo assim:

button, input[type='submit'] { padding: 0 }

E depois seu componente diz:

.btn { padding: 12px }

Cenário <button class="btn"> <input type="submit" class="btn">
Reset escrito manualmente + .btn 12px 0px
reseter.css 3 + .btn 12px 12px
reseter.css 3 + .btn, com seu CSS carregado antes 12px 12px

Com o reset escrito manualmente, o botão de envio fica com padding: 0 porque input[type='submit'] tem especificidade (0,1,1) e .btn apenas (0,1,0). Com reseter.css 3 decide primeiro o layer, assim a competição de especificidade nunca ocorre.

A terceira linha é a verdadeira novidade em relação à versão 2. reseter.css 2.1.0 já envolvia quase todos seus seletores em :where(), o que deixa a especificidade em zero, assim raramente perdia para seus componentes. O que não podia garantir era a ordem de carregamento. Uma regra de especificidade zero em sua aplicação (por exemplo :where(.stack) > * + * { margin-block-start: 24px }) carregada antes do reset dava 0px com a 2.1.0 e 24px com a 3.0.1. Com layers, deixa de importar em que ordem seu bundler injeta o CSS.

Qual regra fica fora do layer?

Há uma regra que se deixa sem layer propositalmente:

:where(dialog):not([open]), [hidden]:not([hidden="until-found" i]) { display: none; }

Graças a ela, o atributo hidden continua funcionando mesmo que uma classe defina display. Em nosso teste, .card { display: flex } sobre um <div class="card" hidden> continuou oculto com reseter.css 3 e ficou visível com o reset escrito manualmente. As notas da versão não mencionam, mas é a decisão correta.

Como se instala reseter.css?

Você pode instalá-lo com npm ou pnpm, ou carregá-lo de um CDN. No momento de publicar esta nota, a última versão é a 3.0.1, publicada em 11 de outubro de 2026, e o guia oficial fixa todos os comandos para essa versão:

npm install reseter.css@3.0.1
# ou
pnpm add reseter.css@3.0.1

Com um bundler, importe primeiro o reset e depois seus estilos:

import "reseter.css";
import "./app.css";

Sem bundler, use o CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reseter.css@3.0.1/dist/index.min.css">
<link rel="stylesheet" href="/styles.css">

O guia de início repete esse mesmo padrão de duas linhas para React, Vue, Svelte, SvelteKit, Next.js, Nuxt, Astro, Remix, Angular, Laravel, Django, Rails, WordPress e Eleventy.

Quanto pesa reseter.css?

Segundo o changelog do próprio projeto para a 3.0.1, dist/index.min.css pesa 951 bytes com compressão Brotli. Nós medimos 1.178 bytes com gzip para o build completo e 377 bytes para o build mini. Se você se preocupa com o CSS que bloqueia o primeiro render, também pode lhe servir Critical 9: como extrair o CSS crítico sem navegador.

reseter.css completo ou mini?

Use o build completo, a menos que uma biblioteca de UI já dê estilo a seus controles de formulário. Nesse caso use o mini (import "reseter.css/mini"), e carregue apenas um dos dois, conforme indica a documentação. O mini deixa de fora formulários, links e diálogos, e além disso tem outras diferenças que medimos:

O quê Completo Mini
Peso da fonte de h2 700 400 (normal)
Margem entre parágrafos (p + p) 16px 0
Borda de inputs de texto 1px solid a do navegador
Fonte dos controles pilha system-ui a do navegador
textarea resize vertical both

A que mais surpreende é o peso dos títulos: com o mini, todos os títulos ficam com peso normal.

Como usar reseter.css com frameworks que usam @layer?

Se seu framework ou seu sistema de design coloca seus estilos base dentro de um layer, declare a ordem dos layers antes de qualquer outra coisa. Os layers se ordenam conforme a primeira vez que se declaram, e o que se declara depois vence. Se o @layer base do seu framework se declara primeiro e reseter.css é importado depois, o reset vence seus estilos base.

Reproduzimos: com @layer base { h2 { margin-block: 0 } } declarado antes de importar reseter.css, o h2 conservou 19,92px de margem. Uma única linha no início resolveu:

@layer reset, base;

Com essa declaração, a margem do h2 passou a 0, como se esperava. As notas da versão alertam que os frameworks com layers podem precisar de atenção à ordem das camadas. Em 15 de outubro de 2026, o guia de início oficial não explica como fazê-lo.

O que se quebra ao atualizar de reseter.css 2 para 3?

A 3 é uma versão maior conforme semver, e as mudanças visuais são reais. Estes são os valores computados que mudaram entre a 2.1.0 e a 3.0.1 no Chromium:

Área Elemento 2.1.0 3.0.1
Títulos margem superior de h2 0 19.92px
Títulos text-wrap de h1–h4 auto balance
Listas padding-inline-start de ul 0 40px
Listas marcadores de ul[role="list"] disc none
Formulários estilo de borda de botões solid outset (a do navegador)
Formulários fonte de input/button/select Arial pilha system-ui
Formulários resize de textarea both vertical
Mídia display de img, svg inline block
Mídia max-width de img none 100%
Raiz text-size-adjust de html auto none

Há quatro áreas que precisam de revisão visual: títulos (recuperam suas margens), listas (recuperam sua indentação), formulários (nova fonte e bordas de botão padrão) e mídia (as imagens passam a ser blocos, o que pode quebrar ícones inline).

Por baixo também muda o código. Não há mais fontes Sass, o CSS publicado é gerado com Lightning CSS e o repositório passou para pnpm. As propriedades agora são lógicas (margin-block, padding-inline-start, max-inline-size) em vez de físicas. Se você importava rotas internas do pacote, use apenas as que aparecem no campo exports de package.json. A documentação recomenda import "reseter.css" e reseter.css/mini.

O que faz text-size-adjust: none?

Desativa o agrandamento de texto que navegadores móveis aplicam a páginas que não foram projetadas para telas pequenas. Conforme MDN, um site realmente responsivo não precisa desse agrandamento, e desativá-lo não impede que o usuário faça zoom. Se seu site ainda tem layouts que não são responsivos, revise como ficam em um telefone depois de atualizar.


E você? Qual regra do seu reset ou de seus estilos base lhe deu mais problemas ao competir contra os estilos de um componente?

Qual CSS reset você usa hoje?
  • Um próprio, escrito manualmente
  • Normalize.css ou similar
  • O que vem com meu framework
  • Prefiro outra opção (conte-nos qual)
0 votantes

Comente abaixo ou, se este artigo chegou até você por email, responda direto ao email: sua resposta é publicada aqui.

Relacionado: Panda CSS 2.0: O Compilador Reescrito em Rust e Como Migrar Sem Quebrar seu Build