Corso di CSS / Combinatori e pseudo-classi CSS: struttura, stati e posizione
I combinatori selezionano elementi in base alle loro relazioni nella struttura HTML, mentre le pseudo-classi selezionano stati o condizioni strutturali. Un selettore figlio differisce da un selettore discendente, e :first-child si riferisce al primo elemento figlio piuttosto che al primo elemento di un tipo particolare.
Leggere le relazioni tra genitore, figlio, discendente e fratello
Nella struttura seguente, section è il genitore di h2, paragrafo A, div e paragrafo C. Il paragrafo B è un figlio di div, che è un discendente di section. A e C sono fratelli perché hanno lo stesso genitore, ma A e B non sono fratelli perché hanno genitori diversi. La struttura HTML è più importante di come appare sullo schermo.
<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
| notazione della relazione | selettore | Paragrafo selezionato | Paragrafo non selezionato |
|---|---|---|---|
| spazio: discendente | .garden p |
A, B, C | p fuori da questa sezione |
| >: figlio diretto | .garden > p |
A, C | B è annidato in un div e non è un figlio diretto |
| +: fratello immediatamente successivo | h2 + p |
A | B ha genitori diversi e c'è un div prima di C. |
| ~: fratelli successivi | h2 ~ p |
A, C | B ha un genitore diverso da h2. |
Un combinatore normalmente prende di mira l'elemento alla sua destra. h2 + p stila il p immediatamente successivo a un h2 come fratello. I nodi di testo di spazi bianchi derivanti da rientri o interruzioni di linea non interrompono questa relazione tra elementi-fratelli. Per ulteriori dettagli, vedere Selettori CSS di base: Tipo, Classe, ID e Attributi.
Confronta selettori discendenti e figli
.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
La prima regola rende verde il testo di tutti gli elementi p discendenti di .garden. Include B anche se c'è un div nel mezzo. La seconda regola aggiunge un bordo a sinistra e un padding a sinistra solo ai figli diretti A e C. Poiché color e border-left sono proprietà diverse, A e C possono avere sia il verde sia il bordo.
Un selettore discendente è adatto per lo styling comune dei paragrafi in tutta una sezione. Un selettore diretto dei figli può escludere paragrafi all'interno di card annidate. I cambiamenti nella struttura influenzano queste corrispondenze; evita di concatenare combinatori di figli non necessari che rendono il foglio di stile dipendente da una profondità rigida. Vedi MDN: Combinatori.
Confronta il fratello immediatamente successivo e tutti quelli successivi
h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }
La prima regola assegna uno sfondo giallo al paragrafo A, che è il fratello immediatamente successivo al titolo. La seconda mette in corsivo A e C perché entrambi sono elementi p fratelli successivi di h2. B ha un genitore diverso e quindi non corrisponde. Nessuno dei due combinatori seleziona fratelli precedenti.
Se inserisci <div>Additional notice</div> tra h2 e A, lo sfondo giallo scomparirà perché A non è più il fratello immediato. Tuttavia, la condizione che segua h2 all'interno dello stesso genitore rimane, quindi il corsivo permane. Vedere questa differenza ti eviterà di dover memorizzare + e ~ come “selettori simili.”
Seleziona stati e posizioni con le pseudo-classi
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 seleziona lo stato in cui il puntatore si trova sopra l’elemento. :focus-visible seleziona lo stato in cui il browser determina che è necessaria la visualizzazione del focus, ed è utile per controllare quando si sposta il focus con il tasto Tab. :focus seleziona lo stato di focus stesso, quindi il significato dei due non è completamente lo stesso. Questo esempio definisce un contorno visibile per il focus, invece di eliminare l’indicazione senza sostituirla. Puoi continuare a esercitarti su come distinguere colore e focus per stato in un link reale in Stati dei link CSS e focus visibile da tastiera.
Quando si passa il mouse sopra il link, lo sfondo diventa giallo, e quando si naviga al link tramite il tasto Tab, appare un contorno blu. In un ambiente touch, non si può garantire che l'utente sperimenti sempre l'effetto hover. Lascia le informazioni essenziali, come gli orari di apertura o i nomi dei link, ancora leggibili di default.
:first-child seleziona se è il primo elemento figlio del suo genitore. :nth-child(odd) seleziona i casi in cui l'ordine degli elementi figli è dispari, come 1, 3 o 5. La lista di piante sopra contiene solo li, quindi la menta numero 1 diventa in grassetto e crea uno sfondo per gli elementi 1 e 3. Se si usa even invece di odd, i numeri 2 e 4 saranno i target.
p:first-child significa “un elemento p che è il primo figlio del suo genitore,” piuttosto che “il primo p.” Il primo figlio di section in questo esempio è h2, quindi .garden > p:first-child non corrisponde a nessun paragrafo. nth-child conta tutti gli elementi fratelli, non solo gli elementi con lo stesso tag. Usa una condizione come nth-of-type quando ti servono posizioni all'interno di un tipo di elemento. La pagina di riferimento MDN sulle pseudo-classi spiega queste condizioni di stato e di posizione.
Esegui l'esempio 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 salvi ed esegui, A·B·C sono verdi, e solo A·C ha un bordo a sinistra. A ha uno sfondo giallo, e A·C ha il testo in corsivo. La lista delle piante ha il primo elemento in grassetto e gli elementi con numero dispari hanno uno sfondo chiaro. Controlla i link usando rispettivamente il mouse e la tastiera. Le lettere A~C davanti ai paragrafi sono lettere scritte direttamente nel testo per confrontare i risultati della selezione.
Modifica la struttura e testa ciascuna condizione
- Aggiungi un div tra h2 e A. Verifica che scompaia solo lo sfondo di A, lasciando il corsivo e i bordi. Dopo aver esercitato, elimina il div aggiunto.
- Rendi B un figlio diretto della sezione rimuovendo soltanto i tag di apertura e chiusura del div che contiene il paragrafo B. Assicurati che B abbia anche un bordo sinistro e un'inclinazione. Solo A è ancora corretto nella condizione +. Dopo la conferma, ripristina il div.
- Sostituisci
:nth-child(odd)con:nth-child(even). Controlla che lo sfondo della lista si sposti dai numeri 1 e 3 ai numeri 2 e 4 e che le lettere in grassetto per il primo elemento figlio rimangano ancora al numero 1. - Allontana il puntatore dal link, clicca all'interno della pagina e usa il tasto Tab per arrivare al link. Assicurati che il contorno di messa a fuoco sia visibile e che tu possa spostarti alla sezione contatti con Invio. Se la barra degli indirizzi del browser è in focus, torna prima alla pagina.
Si prega di controllare ogni condizione separatamente. Modificare solo il valore del colore per ampliare l'intervallo di selezione o aggiungere l'hover al problema del focus della tastiera non risolverà la causa. Negli strumenti per sviluppatori, è possibile confrontare con la possibilità di forzare l'attivazione dello stato, ma alla fine è meglio controllare i risultati visibili all'utente attraverso il movimento effettivo del tab e i movimenti del mouse.




