Reset de tipografia moderno aproveita container queries e fontes variáveis em CSS puro

- Leitura
- 8 min
- Tabelas
- 1
- Código
- 5
- Fontes
- 1
Um reset publicado pelo CSS-Tricks, batizado de tidy-typography.css, reúne clamp(), unidades de container query e propriedades experimentais de texto para resolver quebra de linha, hifenização e tipografia fluida direto no CSS.
Reset CSS↳CSS31 conteúdosArquitetura CSS: CSS FuncionalDev (Back & Front) · set 2019Entendendo posicionamento com CSS de uma vez por todasDev (Back & Front) · jul 2025Sites que combinam estética e usabilidade: reflexos da evolução do CSSDev (Back & Front) · fev 2025Ver tudo em Dev (Back & Front) → tradicionalmente resolve margem zerada e box-sizing, deixando decisões tipográficas pro CSS do projeto ou pra algum script de correção de órfãos. O CSS-Tricks publicou um reset batizado de tidy-typography.css que reúne, num só arquivo, escolhas que hoje já dá pra fazer só com CSS: quebra de linha sem palavra solta, tipografia presa ao tamanho do container (não ao da tela), hifenização configurável e ajustes finos de fontes variáveis. A ideia não é importar o arquivo inteiro: é copiar a declaração que resolve o incômodo da vez, porque parte do conjunto ainda é experimental e o suporte entre navegadores é desigual.
Para quem constrói front-end, o ganho prático é trocar JavaScript de UI (bibliotecas de balanceamento de título, hifenização manual, detecção de idioma pra aspas) por propriedades nativas que o navegador já entende ou simplesmente ignora quando não suporta. Essa degradação graciosa é o ponto central do reset: nenhuma declaração quebra o layout num navegador sem suporte, ela só deixa de se aplicar.
Renderização e fallback antes de qualquer fonte carregar
Antes de falar de tamanho de fonte, o reset cobre o básico de como o texto é desenhado na tela:
html {
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-synthesis: none;
text-size-adjust: none;
}
body {
font-size-adjust: from-font;
}font-synthesis: none impede o navegador de inventar negrito ou itálico quando a família tipográfica não tem aquele estilo. text-rendering e o font-smoothing são dicas de renderização, principalmente para WebKit, e o resultado varia por plataforma. Já text-size-adjust: none desliga a inflação automática de fonte no mobile, que pode fazer um layout calculado de propósito saltar de tamanho na rotação da tela, enquanto font-size-adjust: from-font usa as métricas da própria fonte pra reduzir esse salto durante a troca por uma webfont.
Tipografia fluida que não erra o tamanho do container
Tipografia fluida baseada em viewport (vw) não sabe a largura do elemento onde está: um título numa sidebar estreita acaba escalando como se ocupasse a tela inteira. A solução do reset troca vw por cqi, a unidade de container query:
.article-container {
container-type: inline-size;
}
:root {
--step-0: clamp(1rem, 0.9rem + 1cqi, 1.125rem);
--step-3: clamp(2rem, 1.6rem + 3cqi, 2.75rem);
}container-type: inline-size transforma o wrapper num container de consulta, e os filhos passam a escalar com base na largura desse container, não da tela. O mesmo título se comporta direito numa coluna de artigo ou numa sidebar de 300px, sem media query específica por componente. Na minha leitura, vale lembrar que declarar container-type cria um novo contexto de containment no elemento, o que pode interferir em comportamentos de layout que dependiam do fluxo normal ali dentro, então convém aplicar no wrapper certo, não em qualquer ancestral.
Ritmo vertical: cortando o half-leading
line-height inclui um espaço acima da altura das maiúsculas e abaixo da linha de base, o chamado half-leading, que fica evidente quando o texto precisa alinhar rente a outro elemento. text-box-trim: trim-both remove essa sobra, e text-box-edge: cap alphabetic mede do topo das maiúsculas até a linha de base alfabética, substituindo os ajustes de margem negativa feitos fonte por fonte.
:is(h1, h2, h3, h4, h5, h6), p, blockquote, figcaption, li {
text-box-trim: trim-both;
text-box-edge: cap alphabetic;
}
@supports selector(:heading) {
:heading {
text-box: trim-both cap alphabetic;
}
}O seletor :heading, que casaria com h1 a h6 e com [role="heading"], é proposta do Selectors Level 5 e ainda não existe em nenhum navegador, por isso fica atrás de um @supports selector().
Blocos balanceados, sem órfãos e sem reembaralhar enquanto alguém digita
O reset usa três valores de text-wrap para três problemas diferentes, e misturar os três no lugar errado produz efeito ruim:
| Valor | Efeito | Melhor uso |
|---|---|---|
balance | Distribui o texto entre as linhas do bloco | Títulos e blocos curtos, até cerca de 6 linhas |
pretty | Evita só a palavra solta na última linha, sem balancear o bloco inteiro | Parágrafos e listas |
stable | Impede que o texto se reorganize a cada palavra nova | Campos contenteditable |
Os três substituem scripts de correção de órfãos que rodavam no cliente pra medir e reposicionar quebras de linha. Em navegador sem suporte, a declaração é ignorada e o texto volta ao comportamento padrão, sem quebrar o layout.
Hifenização sob controle, sem escada de hífens
hyphens: auto depende de dicionário por idioma, então o atributo lang precisa estar correto no HTML ou no CSS pra funcionar. O problema é que o comportamento padrão pode gerar fragmentos minúsculos ou várias linhas hifenizadas seguidas, e o reset ataca isso com um conjunto de propriedades mais novas:
p {
hyphens: auto;
lang: en;
hyphenate-limit-chars: 6 3 3;
hyphenate-character: "‐";
hyphenate-limit-lines: 2;
hyphenate-limit-zone: 8%;
hyphenate-limit-last: always;
-webkit-hyphens: auto;
-webkit-hyphenate-limit-before: 4;
-webkit-hyphenate-limit-after: 3;
-webkit-hyphenate-limit-lines: 2;
}
pre, code, var, samp, kbd, :is(h1, h2, h3, h4, h5, h6) {
hyphens: manual;
-webkit-hyphens: manual;
}hyphenate-limit-chars controla o tamanho mínimo da palavra quebrável e o número de caracteres antes e depois do hífen; hyphenate-limit-lines evita o efeito escada de hífens empilhados; hyphenate-limit-zone reduz a frequência geral das quebras; hyphenate-limit-last protege a última palavra do parágrafo. Safari ainda depende dos equivalentes com prefixo, por isso os dois conjuntos aparecem juntos. Código, variáveis e títulos ficam com hyphens: manual: uma palavra de código quebrada pode mudar de significado, e um título hifenizado costuma parecer erro de diagramação.
Pontuação suspensa e sublinhados que respeitam a tinta
Sinais de pontuação não têm o mesmo peso visual das letras, então uma aspa no início de linha parece ligeiramente recuada em relação ao texto abaixo. hanging-punctuation: first allow-end last deixa a pontuação especificada sair fracionadamente da borda do bloco de texto, de forma que as margens leiam como realmente alinhadas.
Sublinhados têm um problema parecido: o navegador aplica espessura e posição fixas, independente do peso real da fonte. text-decoration-thickness: from-font lê a espessura pensada pelo desenhista da fonte, text-underline-offset dá espaço pras descendentes respirarem, e text-decoration-skip-ink: auto interrompe o traço onde uma descendente cruza a linha, em vez de desenhar por cima da letra.
Fontes variáveis: tamanho óptico e correção de peso no modo escuro
Fontes variáveis costumam trazer um eixo de tamanho óptico, o opsz, que deixa a fonte usar traços mais finos em tamanhos grandes de exibição e traços mais grossos e legíveis em tamanhos pequenos. font-optical-sizing: auto delega essa escolha ao tamanho renderizado de fato, com um @supports (font-variation-settings: normal) cobrindo a sintaxe antiga que alguns navegadores ainda pedem.
Em resumo: texto claro sobre fundo escuro lê mais pesado do que o mesmo peso sobre fundo claro, e fontes com eixo GRAD (grade) permitem compensar essa percepção sem alterar a forma nem a largura dos glifos, como uma mudança de peso de verdade faria. O reset troca uma variável --vf-grad dentro de @media (prefers-color-scheme: dark), e fontes sem esse eixo simplesmente ignoram a declaração.
Um detalhe menos óbvio aparece ao misturar uma fonte monoespaçada no meio de texto corrido: a altura-x costuma destoar mesmo com o mesmo font-size declarado. size-adjust, definido uma vez dentro do @font-face, reescala a saída renderizada daquela fonte especificamente, sem tocar no valor de font-size usado no resto do CSS.
Números tabulares, emoji consistente e aspas por idioma
Números numa tabela precisam ter a mesma largura pra formar coluna limpa; números no meio de um parágrafo não precisam disso e devem acompanhar o texto ao redor. font-variant-numeric: tabular-nums lining-nums resolve o primeiro caso; oldstyle-nums proportional-nums resolve o segundo, deixando os dígitos na altura da caixa baixa.
font-variant-emoji: emoji ou text torna explícita a escolha entre emoji colorido e monocromático: sem essa declaração, quem decide é o navegador ou a plataforma, e o resultado varia mais do que parece razoável. A recomendação do reset é aplicar em containers específicos, não globalmente no body.
A propriedade quotes declara a ordem de aspas por :lang(), e o elemento nativo q insere o par certo via open-quote e close-quote, sem precisar fixar caractere no conteúdo. Envolver essas regras em :where() mantém especificidade zero, então um projeto consegue sobrescrever o estilo de aspas com uma classe simples. Sub e sobrescrito sintetizados (o navegador só encolhe o texto e desloca a linha de base) ganham alternativa com font-variant-position, que usa os glifos desenhados pra essa posição quando a fonte os tem, embora a maioria das famílias só traga numerais nessa variante, não o alfabeto completo.
:is() e :where(): a diferença que importa num reset
:where() sempre resolve para especificidade zero, o que é útil justamente porque cada regra do reset é um valor padrão opinativo, e qualquer projeto precisa conseguir sobrescrever com uma classe comum:
:where(h1, h2, h3, h4, h5, h6) {
margin-block: 0.5em;
}:is() resolve outro problema, o de repetição: a lista de seletores de título aparece várias vezes numa folha de estilo tipográfica, e agrupar evita esquecer um nível. A diferença prática é que :is() carrega a especificidade do argumento mais específico da lista, enquanto :where() não carrega nenhuma.
Onde isso vale a pena, e onde não
Muita dessa CSS tira trabalho que antes vazava pro JavaScript: text-wrap assume a correção de órfãos, as unidades de container query mantêm a escala de um componente presa à sua própria largura, e text-box-trim evita as margens negativas usadas antes pra compensar entrelinha. quotes, font-variant-position e font-optical-sizing devolvem detalhes menores pro idioma e pra fonte, em vez de uma coleção de correções pontuais.
O suporte de navegador vai continuar mudando, principalmente para text-wrap e text-box-trim. Declarações não suportadas são ignoradas, mas isso só ajuda quando a tipografia sem o reforço já é aceitável por conta própria. Uma notícia, uma página de marketing e uma interface de produto editável não pedem as mesmas coisas do texto: o conjunto que cabe no seu projeto depende da fonte escolhida, do tipo de conteúdo e dos navegadores que você ainda precisa suportar. Vale ler o código completo do tidy-typography.css no artigo original do CSS-Tricks antes de decidir o que entra na sua folha de estilo.
Fonte: CSS-Tricks
Highlights
- tidy-typography.css usa container queries (cqi) em vez de viewport (vw) para tipografia fluida que respeita o tamanho real do elemento
- text-wrap: pretty evita palavra solta sem balancear bloco inteiro; text-wrap: balance redistribui títulos e citações; text-wrap: stable para campos editáveis
- Troca scripts de balanceamento de órfãos, hifenização manual e detecção de idioma por propriedades CSS nativas que o navegador entende ou ignora graciosamente
- text-box-trim e text-box-edge removem half-leading, alinhando texto rente a elementos vizinhos sem margem negativa por fonte
- Fontes variáveis ganham eixo GRAD para compensar peso visual em modo escuro sem alterar forma dos glifos
Este artigo foi escrito por Carina Ferreira, colunista de front-end. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.
Vercel lança plugin que ensina agentes do Google Antigravity a deployar com as APIs certas
O Vercel Plugin, disponível no marketplace do Antigravity (IDE agêntico do Google), dá a agentes de IA orientação sobre APIs e padrões da Vercel, incluindo um exemplo de backend Python deployado via Vercel Sandbox.













