Pular para o conteúdo
murad.guide

Introdução Completa à Web

Capítulo 8

Seletores e cascata

6 min de leitura 1.024 palavras 2 gravuras

Este capítulo ensina a pintar este parágrafo de um jeito e aquele de outro. O palco é a Casa da Restinga, cafeteria fictícia em Natal. Este volume tem 23 capítulos. O exemplo está em exemplos/08-seletores-cascata/.

No capítulo 7, um seletor p pegava todos os parágrafos. Agora a classe escolhe um grupo. A cascata decide quem vence quando duas regras pedem a mesma propriedade.

Trabalhe na cópia inicio da etapa. Leia e digite o código; mude uma coisa. Antes de recarregar, anote sua previsão. Depois confira com a referência completa. Se nada mudar, confira o arquivo salvo e o caminho aberto. Blocos adicionais do capítulo podem ser digitados no console; o exemplo completo mostra a aplicação daquela etapa.

O que você vai aprender

Classe em vez de pintar todas as tags

Dois h1 na mesma página podem ter papéis diferentes. Um é a marca da casa. Outro é o título de um post. A tag é a mesma. A classe diferencia.

<h1 class="marca">Casa da Restinga</h1>
<h2 class="titulo-post">A torrada das seis</h2>
.marca {
  color: maroon;
}

.titulo-post {
  color: seagreen;
}

O ponto no CSS marca “isto é uma classe”. No HTML o atributo é class="marca", sem ponto.

Prefira classe para estilo. Seletor de tipo (h1, p, a) vale quando você quer mesmo todos. Esses casos são poucos. Errar para o lado das classes.

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Casa da Restinga</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <h1 class="marca">Casa da Restinga</h1>
    <p class="intro">Cafeteria fictícia em Natal.</p>
    <p class="aviso">A mesa da janela pega vento.</p>
  </body>
</html>

Pare e experimente. Acrescente class="aviso" ao parágrafo de intro. Recarregue. Os dois devem receber o estilo de .aviso. Tire a classe extra.

Quando empatam, a última vence

Duas regras com o mesmo seletor e a mesma propriedade: a que aparece por último no CSS ganha.

.marca {
  color: maroon;
}

.marca {
  color: seagreen;
}

O h1.marca fica seagreen. Não é mágica. É ordem no arquivo. Cada propriedade se desempata sozinha. Uma regra pode perder na cor e ainda aplicar a borda, se a outra não falar de borda.

.marca {
  border: 1px solid black;
  color: maroon;
}

.titulo {
  color: seagreen;
}

Com class="marca titulo", a cor fica seagreen se .titulo vier depois. A borda permanece: .titulo não a contradiz.

Leia. Copie. Mude uma coisa. Preveja. Recarregue. Confira. Inverta as duas regras .marca. A cor deve trocar.

Duas regras iguais: a última declaração de color vence

Especificidade: classe pesa mais que tag

Nem sempre a última vence. O navegador compara especificidade. Classe pesa mais que tipo. Um .titulo vence um h1 mesmo que o h1 venha depois.

.titulo {
  color: orange;
}

h1 {
  color: seagreen;
}

O h1 class="titulo" fica orange. A classe é mais específica.

Um jeito tosco de pensar: tipo vale 1, classe vale 10, id vale 100. O maior número ganha. O modelo não é perfeito — uma classe ainda ganha de muitos tipos — mas ajuda a ler o conflito.

Por isso este volume pede classes no visual. Se tudo é classe, os números empatam e a ordem no arquivo resolve. Menos guerra.

Erro comum: pintar com p e depois estranhar um .aviso que “não obedece”. Confira quem é mais específico antes de repetir a regra.

Duas classes no mesmo seletor

Sem espaço, .marca.titulo pede um elemento que tenha as duas classes. Com espaço, .marca .titulo pede um .titulo dentro de um .marca. O espaço muda o significado.

.marca.titulo {
  color: maroon;
}

.titulo {
  color: seagreen;
}

.marca.titulo é mais específico (duas classes). Vence .titulo (uma classe).

Juntar tag e classe, h1.marca, também aumenta a conta. Evite. Se você precisa da tag no seletor para “ganhar”, o HTML provavelmente quer outra classe.

Pare e experimente. Coloque um espaço em .marca.titulo e vire .marca .titulo. Recarregue. O h1 que tem as duas classes no mesmo elemento deve perder esse estilo. Tire o espaço.

id e !important: ferramentas pesadas

Seletor de id usa #. #marca vence classes. Um id ainda vence um empilhamento comprido de classes. Por isso o id neste volume serve para âncora (#conteudo), não para pintar.

!important força uma declaração a ganhar. Quebra a leitura da cascata. Não use neste volume. Se o visual não aplica, o problema é seletor, ordem ou arquivo errado — não falta de !important.

#marca {
  color: maroon;
}

.nav {
  color: seagreen !important;
}

Mesmo vendo isso em códigos velhos, não copie o hábito. Classe clara e pouca briga resolvem o blog da Restinga.

O CSS está no disco. O navegador calcula a cascata na hora de desenhar a página. file:// e 127.0.0.1 mostram o mesmo cálculo nesta máquina. Publicar não muda a regra da cascata.

Prática no blog da Casa

No styles.css do exemplo, pinte a intro e o aviso de jeitos diferentes. Deixe os posts com uma borda. Não use id para cor.

.intro {
  font-size: 1.15rem;
}

.aviso {
  color: maroon;
  border-left: 4px solid maroon;
  padding-left: 1rem;
}

.post {
  border: 1px solid #d6cbb8;
  padding: 1rem;
  margin-bottom: 1rem;
}

Se um post não ganha borda, falta class="post" no article. O seletor certo não inventa a classe no HTML.

Início da referência desta etapa no navegador local

O ciclo: ler → copiar → mudar uma coisa → prever → recarregar → conferir. Troque só a cor de .aviso. Os posts devem permanecer.

Quando duas regras brigarem, pergunte: é o mesmo seletor? quem é mais específico? qual vem por último? Só então mude o CSS. Não acrescente !important para “resolver agora”.

O capítulo 9 entra em pseudoclasses. O foco do teclado e o estado do link dependem do que você viu hoje: seletor certo e cascata previsível.

Atividades

  1. Como o CSS distingue um seletor de tipo de um seletor de classe?
  2. Duas regras .aviso pedem cores diferentes. Qual vence, se não houver !important?
  3. Por que .titulo vence h1 mesmo o h1 vindo depois no arquivo?
  4. No exemplo 08-seletores-cascata, o que acontece se você escrever class=".aviso" no HTML?

Respostas comentadas

  1. Tipo usa o nome da tag (p). Classe usa o ponto e o nome (.aviso). No HTML a classe vai no atributo class, sem ponto.
  2. A que aparece por último no CSS. A especificidade é igual.
  3. Classe é mais específica que tipo. A ordem só desempata quando a especificidade empata.
  4. A classe real passaria a se chamar .aviso, com ponto no nome. O seletor .aviso não pega esse elemento. O visual do aviso some.

Referências

O arquivo completo

Referência do exemplo 08-seletores-cascata, reproduzida aqui para que você possa conferir sem sair da página.

assets/stylesheets/main.css

*,
*::before,
*::after { box-sizing: border-box; }
html, body, h1, h2, h3, p, ul { margin: 0; padding: 0; }
img { max-width: 100%; height: auto; }
body {
  font-family: "Segoe UI", Tahoma, sans-serif;
  line-height: 1.5;
  color: #1a2a2c;
  background: #f7f3ea;
}
a { color: #0d5c63; }
a:focus-visible, button:focus-visible, input:focus-visible {
  outline: 3px solid #c45c26;
  outline-offset: 3px;
}
.skip { position: absolute; left: -999px; }
.skip:focus { left: 0.5rem; top: 0.5rem; background: #fff; padding: 0.4rem 0.7rem; z-index: 2; }
.wrap { width: min(44rem, calc(100% - 2rem)); margin-inline: auto; }
header { background: #0d5c63; color: #fff; padding: 1rem 0; }
header a { color: #fff; }
.brand { font-weight: 700; text-decoration: none; }
nav ul { list-style: none; display: flex; gap: 1rem; margin-top: 0.5rem; }
nav a[aria-current="page"] { text-decoration: underline; text-underline-offset: 0.2em; }
main { padding: 1.5rem 0 3rem; }
footer { border-top: 1px solid #ddd4c4; padding: 1rem 0; font-size: 0.95rem; }
article { margin: 1.25rem 0; padding-bottom: 1rem; border-bottom: 1px solid #ddd4c4; }

.aviso { color: #c45c26; }
article p { color: #1a2a2c; }