Curso de CSS / Combinadores e pseudoclasses
Combinadores selecionam elementos com base em seus relacionamentos na estrutura HTML, enquanto pseudoclasses selecionam estados ou condições estruturais. Um seletor de filho é diferente de um seletor de descendente, e :first-child refere-se ao primeiro elemento filho em vez do primeiro elemento de um tipo específico.
Leia os relacionamentos de pai, filho, descendente e irmão
Na estrutura a seguir, section é o elemento pai de h2, parágrafo A, div e parágrafo C. O parágrafo B é um filho da div, que é um descendente de section. A e C são irmãos porque têm os mesmos pais, mas A e B não são irmãos porque têm pais diferentes. A estrutura HTML é mais importante do que a aparência na tela.
<section class="garden">
<h2>Visitor Information</h2>
<p>A: Operating hours</p>
<div>
<p>B: Greenhouse Guide</p>
</div>
<p>C: What you need</p>
</section>
section.garden
├─ h2
├─ p ← A
├─ div
│ └─ p ← B
└─ p ← C
| notação de relação | seletor | Parágrafo selecionado | Parágrafo não selecionado |
|---|---|---|---|
| espaço: descendente | .garden p |
A, B, C | p fora desta seção |
| >: filho direto | .garden > p |
A, C | B está dentro de uma div e não é filho direto da seção |
| +: o irmão seguinte | h2 + p |
A | B tem pais diferentes e há uma div antes de C. |
| ~: irmão subsequente | h2 ~ p |
A, C | B tem um pai diferente de h2. |
Um combinador normalmente tem como alvo o elemento à sua direita. h2 + p estiliza o p imediatamente seguinte a um h2 como um irmão. Nós de texto em branco provenientes de indentação ou quebras de linha não interrompem essa relação de elemento-irmão. Para mais detalhes, veja Seletores CSS Básicos: Tipo, Classe, ID e Atributos.
Compare seletores de descendentes e de filhos
.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
A primeira regra deixa todos os p em garden verdes. Ela seleciona B mesmo que haja uma div no meio. A segunda regra adiciona uma borda à esquerda e espaçamento interno apenas aos filhos diretos A e C. Como color e border-left são propriedades diferentes, A e C podem ter tanto verde quanto a borda.
Um seletor de descendente é adequado para estilização de parágrafos compartilhados em toda uma seção. Um seletor de filho direto pode excluir parágrafos dentro de cartões aninhados. Mudanças na estrutura afetam essas correspondências; evite encadear combinadores de filho desnecessários que façam a folha de estilo depender de uma profundidade rígida. Veja MDN: Combinadores.
Compare irmãos imediatos e subsequentes
h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }
A primeira regra dá um fundo amarelo ao parágrafo A, que é o elemento irmão imediatamente a seguir ao título. A segunda coloca A e C em itálico, porque ambos são elementos p irmãos posteriores de h2. B tem outro pai e não corresponde. Nenhum destes combinadores seleciona irmãos anteriores.
Se você inserir <div>Additional notice</div> entre h2 e A, o fundo amarelo desaparecerá porque A não é mais o irmão imediato. No entanto, a condição de que ele segue h2 dentro do mesmo pai continua válida, então o itálico permanece. Ver essa diferença vai poupar você de ter que memorizar + e ~ como “seletores similares.”
Selecione estados e posições com pseudoclasses
a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }
:hover seleciona o estado em que o ponteiro está sobre o elemento. :focus-visible seleciona o estado no qual o navegador determina que a exibição de foco é necessária, sendo útil para verificar ao percorrer elementos com a tecla Tab. :focus seleciona o próprio estado focado, portanto, o significado dos dois não é exatamente o mesmo. Este exemplo especifica um contorno adicional sem remover o indicador de foco padrão. Você pode continuar praticando como distinguir cor e foco por estado em um link real em Estados de links e foco visível do teclado.
Quando você passa o mouse sobre o link, o fundo fica amarelo e, quando você navega até o link usando o teclado (tab), um contorno azul aparece. Em um ambiente de toque, o efeito de hover não pode ser garantido para o usuário. Deixe as informações essenciais, como horários de funcionamento ou nomes de links, ainda legíveis por padrão.
:first-child seleciona se é o primeiro elemento filho de seu pai. :nth-child(odd) seleciona casos em que a ordem dos elementos filhos é ímpar, como 1, 3 ou 5. A lista de plantas acima possui apenas li, então a hortelã número 1 fica em negrito e cria um fundo para os itens 1 e 3. Se você usar par (even) em vez de ímpar (odd), os números 2 e 4 serão os alvos.
p:first-child significa “um elemento p que é o primeiro filho de seu pai”, em vez de “o primeiro p”. O primeiro filho de section neste exemplo é h2, então .garden > p:first-child não corresponde a nenhum parágrafo. nth-child conta todos os elementos irmãos, não apenas os elementos com a mesma tag. Use uma condição como nth-of-type quando você precisar de posições dentro de um tipo de elemento. A referência da pseudo-classe MDN explica essas condições de estado e posição.
Execute o exemplo completo
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Small Garden</title>
<style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }
a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
</style>
</head>
<body>
<h1>Small Garden</h1>
<section class="garden">
<h2>Visitor Information</h2>
<p>A: We open at 9am every day.</p>
<div>
<p>B: Please observe quietly in the greenhouse.</p>
</div>
<p>C: Bring a water bottle and comfortable shoes.</p>
</section>
<ul class="plants">
<li>1: Mint</li>
<li>2: Basil</li>
<li>3: Rosemary</li>
<li>4: Time</li>
</ul>
<a href="#contact">Go to the contact section</a>
<h2 id="contact">Contact</h2>
<p>Ask at the information desk.</p>
</body>
</html>
Quando você salva e executa, A·B·C estão verdes, e apenas A·C tem uma borda à esquerda. A tem fundo amarelo, e A·C tem texto em itálico. Como h2 + p e h2 ~ p não estão limitados à seção .garden, o parágrafo após o título Contact também fica com fundo amarelo e em itálico. A lista de plantas tem o primeiro item em negrito e os itens ímpares têm um fundo claro. Verifique os links usando o mouse e teclado, respectivamente. As letras A~C na frente dos parágrafos são letras escritas diretamente no texto para comparar os resultados da seleção.
Altere a estrutura e teste cada condição
- Adicione uma div entre h2 e A. Verifique que apenas o fundo de A desaparece, mantendo o itálico e as bordas. Depois de praticar, exclua a div adicionada.
- Faça B ser um filho direto da seção, removendo apenas a tag div que envolve o parágrafo B. Certifique-se de que B também tenha uma borda esquerda e texto em itálico. Entre A, B e C, apenas A continua a corresponder à condição +. Após a confirmação, restaure a div.
- Substitua
:nth-child(odd)por:nth-child(even). Verifique se o fundo da lista se move dos números 1 e 3 para os números 2 e 4, e se as letras em negrito para o primeiro filho ainda permanecem no número 1. - Afaste o mouse, clique dentro da página e use tab para ir até o link. Certifique-se de que o contorno de foco esteja visível e de que você possa ir para a seção de contato com Enter. Se a barra de endereços do navegador estiver com foco, ele retorna à página primeiro.
Por favor, verifique cada condição separadamente. Alterar apenas o valor da cor para expandir a faixa de seleção ou adicionar hover ao problema de foco do teclado não resolverá a causa. Nas ferramentas de desenvolvedor, você pode comparar com a capacidade de forçar o estado a ser ativado, mas, no final, é melhor verificar os resultados visíveis ao usuário através do movimento real da tecla Tab e dos movimentos do mouse.




