Defina os padrões de texto da página em body, permita que as propriedades herdadas cheguem aos componentes e direcione as regras de layout de forma deliberada. Este guia mostra como criar e verificar uma página HTML local em um Mac sem fazer cada elemento desfazer uma regra universal.
Por que uma regra universal interfere nos padrões dos componentes?
O seletor universal * corresponde a todos os elementos. Portanto, uma declaração dentro dessa regra se aplica diretamente a cada elemento correspondente; ela não apenas fornece um valor a ser herdado pelos descendentes. Também não corresponde diretamente a pseudoelementos, que exigem seletores como *::before. Seletores universais.
Considere este trecho de CSS para um componente que contém um parágrafo e um span de texto aninhado:
/* Illustrative fragment: assumes a .tile with text descendants. */
* {
color: #303840;
}
.tile {
color: #245d75;
}
O próprio bloco recebe a cor azul para o texto. O parágrafo e o span recebem diretamente a cor escura da regra universal. A cor do componente não pode ser propagada por essas declarações por meio da herança comum. Segundo as regras padrão do CSS, as propriedades herdadas obtêm o valor computado do elemento pai quando a cascata não fornece um valor para essa propriedade no elemento. CSS Cascading and Inheritance Level 4, Defaulting.
Isso pode causar confusão porque * tem especificidade zero. A especificidade compara declarações concorrentes no mesmo elemento dentro da origem e da camada da cascata aplicáveis. Uma declaração em um elemento pai não é um seletor concorrente que corresponda ao elemento filho. Portanto, tornar o seletor do pai mais específico não resolve esse problema de herança. Especificidade.
A mudança útil é remover a declaração universal de texto e estabelecer o padrão em body. Os descendentes poderão herdá-lo até que um componente ou elemento forneça outro valor. A MDN identifica color como uma propriedade herdada e explica que a herança segue o valor computado do elemento pai. Herança.
Quais padrões devem ficar na página, em um componente ou em todos os elementos?
Antes de escrever um seletor amplo, decida se a propriedade deve se propagar por uma subárvore de texto, descrever uma caixa ou estabelecer uma regra intencional para todas as caixas. A tabela a seguir aplica essa distinção a uma pequena página criada manualmente.
| Resultado desejado | Posicionamento recomendado | Motivo |
|---|---|---|
| O texto comum da página compartilha uma cor e uma tipografia básicas | body |
Fornece um ponto de partida comum para o texto por meio da herança |
| Um bloco e seu texto comum compartilham outra cor | .tile |
Estabelece um novo valor herdado dentro desse componente |
| Uma única legenda tem outra cor | .caption |
Aplica a exceção ao elemento que precisa dela |
| Um painel tem preenchimento, borda ou plano de fundo | A classe do painel | Mantém a decoração da caixa associada ao elemento responsável por ela |
| As caixas usam um modelo de dimensionamento consistente | Uma regra deliberada de box-sizing |
Estabelece uma convenção explícita de dimensionamento |
| As margens padrão dos títulos podem ser substituídas facilmente | Um seletor direcionado para títulos, opcionalmente agrupado em :where() |
Limita o padrão aos elementos pretendidos |
A herança depende da propriedade. Consulte a entrada Inherited na referência da propriedade, em vez de presumir que todas as declarações em body chegam aos descendentes. Por exemplo, as bordas não são herdadas por padrão. Herança.
Uma regra universal de dimensionamento ainda pode ser apropriada. Com border-box, a largura declarada de um elemento inclui o preenchimento e a borda; as margens ficam fora dessa largura. Essa é uma decisão específica sobre o modelo de caixa, não um motivo para aplicar universalmente todos os padrões da página. box-sizing.
Crie uma demonstração local completa no Mac
Use o TextEdit no modo de texto simples ou um editor de código que já tenha. No TextEdit, escolha File > New e depois Format > Make Plain Text. Cole o documento completo abaixo, escolha File > Save e dê a ele o nome page-defaults.html. Se aparecer uma solicitação, escolha Use .html. A Apple documenta esse fluxo de trabalho no guia de HTML do TextEdit.
Este exemplo usa rótulos fictícios e formas desenhadas com CSS. É um único documento completo com uma folha de estilos incorporada, portanto, não há arquivos adicionais para preparar. O código foi inspecionado aqui; sua renderização não foi executada em um navegador do Mac.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page defaults demonstration</title>
<style>
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
font-size: 1rem;
line-height: 1.5;
color: #303840;
background-color: #f4f5f6;
}
main {
max-width: 44rem;
margin: 0 auto;
padding: 2rem 1rem;
}
h1 {
line-height: 1.2;
}
.tile {
margin: 1.5rem 0;
padding: 1.25rem;
border: 2px solid currentColor;
border-radius: 0.75rem;
color: #245d75;
background-color: #ffffff;
}
.tile h2 {
margin-top: 0;
}
.shape {
width: 4rem;
height: 4rem;
background-color: currentColor;
}
.shape--round {
border-radius: 50%;
}
.caption {
color: #66523c;
}
</style>
</head>
<body>
<main>
<h1>Shape notes</h1>
<p>Page sample: <span>Label A</span>.</p>
<section class="tile">
<h2>Tile B</h2>
<div class="shape shape--round" aria-hidden="true"></div>
<p>Component sample: <span>Label C</span>.</p>
<p class="caption">Caption D has its own text color.</p>
</section>
<p>Page sample: <span>Label E</span>.</p>
</main>
</body>
</html>
Abra page-defaults.html no navegador. Ao reabrir o código-fonte no TextEdit, escolha TextEdit > Settings > Open and Save e ative Display HTML files as HTML code instead of formatted text se quiser que o TextEdit exiba a marcação de forma consistente. Trabalhar com documentos HTML no TextEdit do Mac.
Verifique o limite da herança com três edições
Essas verificações transformam o documento em um pequeno exercício de diagnóstico. Salve o código-fonte e recarregue o navegador depois de cada edição. Guarde uma cópia do documento original ou desfaça cada alteração antes de tentar a próxima.
- Altere somente a cor de
bodypara#4b465f. O texto ao redor deLabel AeLabel Edeve mudar. O bloco mantém sua própria cor. - Restaure a cor da página e, em seguida, altere somente
.tileparacolor: #526637. O texto comum do título e do parágrafo deve acompanhar a mudança, incluindoLabel C.Caption Dmantém sua cor explícita. - Restaure a cor do bloco e adicione temporariamente
* { color: #303840; }no início da folha de estilos. O parágrafo que contémLabel Cagora recebe essa declaração direta. Remova a regra temporária depois.
Essas verificações ilustram a diferença entre um componente estabelecer um valor herdado e um descendente receber uma declaração própria. O comportamento esperado do texto segue as regras de herança e valores padrão da especificação.
Qual é o contrato entre a página HTML e sua folha de estilos?
Mantenha o carregamento de recursos separado do comportamento dos seletores. O exemplo incorpora seu CSS em um elemento style. Se preferir uma folha de estilos separada, mova apenas o conteúdo desse elemento para um arquivo de texto simples chamado page-defaults.css, salvo junto ao arquivo HTML. Substitua o elemento style inteiro pela linha a seguir dentro de head. Este é um fragmento de substituição, não outro documento completo.
<link rel="stylesheet" href="page-defaults.css">
O tipo de link stylesheet identifica um recurso CSS externo usado para apresentar o documento. O nome de arquivo em href precisa apontar para o arquivo que você realmente salvou; a declaração não cria esse arquivo. O padrão HTML define essa relação em Tipo de link: stylesheet.
Neste exemplo, o contrato resultante é simples: o HTML fornece elementos e classes, enquanto o CSS fornece a apresentação deles. Renomear .tile na folha de estilos exige atualizar a classe correspondente no HTML. Mover o arquivo CSS exige atualizar a referência ao recurso. Nenhuma dessas alterações requer um seletor mais específico.
Se a versão externa parecer sem estilos, primeiro confirme que o arquivo CSS existe com o nome esperado e que seu conteúdo contém CSS, não o documento HTML que o envolve. Volte à versão incorporada para isolar erros no carregamento de recursos antes de alterar a cascata.
Quando usar :where() ou camadas da cascata?
Use esses recursos quando resolverem um problema adicional. O exemplo completo acima não depende de nenhum dos dois.
Use :where() para padrões direcionados com especificidade zero
Suponha que a página cresça e passe a incluir vários níveis de títulos. Este fragmento opcional de folha de estilos estabelece espaçamento compartilhado e permite que seletores comuns de títulos o substituam facilmente:
/* Optional fragment: add to the example stylesheet. */
:where(h1, h2, h3) {
margin-bottom: 0.75rem;
}
h2 {
margin-bottom: 1rem;
}
O seletor inteiro :where() tem especificidade zero, inclusive seus argumentos. Mas substituir * por :where(*) não corrige o problema de cor anterior: isso ainda corresponde a todos os elementos e fornece uma declaração direta. Use a herança para resolver esse problema. A MDN documenta :where() como amplamente disponível nos navegadores desde janeiro de 2021; consulte a tabela de compatibilidade caso seja necessário oferecer suporte a um navegador mais antigo. A pseudoclasse :where().
Para um navegador sem suporte a :where(), use uma lista comum de seletores, como h1, h2, h3, para esses padrões de espaçamento e depois coloque exceções com a mesma especificidade mais adiante, na mesma folha de estilos e camada. Isso mantém os padrões direcionados, embora a especificidade deixe de ser zero. Especificidade.
Use camadas quando grupos de regras precisarem de uma ordem explícita
Em uma folha de estilos maior, este fragmento opcional demonstra uma ordem de camadas declarada. Ele é separado do exemplo completo, e não substitui todo o CSS dele.
/* Optional fragment for browsers supporting cascade layers. */
@layer defaults, components;
@layer defaults {
p {
margin-bottom: 1rem;
}
}
@layer components {
.tile p {
margin-bottom: 0.5rem;
}
}
Para declarações normais do autor, as camadas posteriores têm precedência sobre as anteriores; declarações normais sem camada têm precedência sobre as declarações em camadas. As declarações importantes invertem a ordem das camadas, portanto, adicionar !important altera essa disposição. As camadas organizam regras concorrentes; elas não fazem um filho estilizado diretamente herdar o valor do elemento pai. A regra at @layer.
A MDN registra disponibilidade entre navegadores para @layer desde março de 2022. Se um navegador mais antigo que você precisa atender não oferecer suporte, mantenha a apresentação essencial fora dos blocos de camada e use a abordagem sem camadas mostrada no exemplo completo. Não coloque a única cópia dos estilos necessários dentro de um recurso sem suporte. Suporte a camadas da cascata.
Como corrigir uma folha de estilos existente sem adicionar mais sobrescritas?
Trabalhe com uma propriedade de cada vez. Para um problema de cor do texto, localize a regra ampla que atribui a cor diretamente aos descendentes. Remova essa declaração da regra universal, estabeleça o valor da página em body e mantenha as cores dos componentes nos elementos raiz dos componentes. Mantenha as declarações específicas de elementos somente quando o design exigir uma exceção.
Em seguida, repita as três edições da demonstração. Se o texto comum de um componente ainda não acompanhar o elemento pai, procure uma declaração que direcione esse descendente. Se alterar a borda de um componente não mudar as bordas de nenhum dos descendentes, isso é esperado: a herança de bordas é diferente da herança da cor do texto. Herança.
Um padrão sustentável tem um responsável claro. Coloque a tipografia da página no limite da página, a apresentação do componente no limite do componente e as exceções deliberadas nos elementos que precisam delas. Reserve as declarações universais para decisões que você realmente pretende aplicar a todos os elementos correspondentes e, em seguida, verifique esses limites com uma pequena página local.
Fontes
- CSS Cascading and Inheritance Level 4 — W3C.
- Seletores universais — MDN Web Docs.
- Especificidade — MDN Web Docs.
- Herança — MDN Web Docs.
- box-sizing — MDN Web Docs.
- Trabalhar com documentos HTML no TextEdit do Mac — Apple Support.
- Padrão HTML: Tipo de link stylesheet — WHATWG.
- Pseudoclasse CSS :where() — MDN Web Docs.
- Regra CSS @layer — MDN Web Docs.