Pseudo-classi

The CSS Podcast - 015: Pseudo-classes

Supponiamo che tu abbia un modulo di registrazione via email e che tu voglia che il campo del modulo email abbia un bordo rosso se contiene un indirizzo email non valido. E come potete farlo? Puoi utilizzare una pseudo-classe CSS :invalid, una delle tante pseudo-classi fornite dal browser.

Una pseudo-classe ti consente di applicare stili in base a modifiche dello stato e fattori esterni. Ciò significa che il tuo progetto può reagire all'input dell'utente, ad esempio un indirizzo email non valido. Questi argomenti vengono trattati nel modulo Selettori, che li illustrerà in modo più dettagliato.

A differenza degli pseudo-elementi, di cui puoi scoprire di più nel modulo precedente, le pseudo-classi si agganciano a stati specifici in cui un elemento potrebbe trovarsi, anziché applicare uno stile generale a parti di quell'elemento.

Stati interattivi

Le seguenti pseudo-classi vengono applicate a causa di un'interazione di un utente con la tua pagina.

:hover

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 2.

Source

Se un utente ha un dispositivo di puntamento come un mouse o un trackpad e lo posiziona sopra un elemento, puoi agganciarti a questo stato con :hover per applicare gli stili. Questo è un modo utile per suggerire che è possibile interagire con un elemento.

:active

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Questo stato viene attivato quando si interagisce attivamente con un elemento, ad esempio un clic, prima che venga rilasciato. Se viene utilizzato un dispositivo di puntamento come un mouse, questo stato si verifica quando inizia il clic e non è ancora stato rilasciato.

:focus, :focus-within e :focus-visible

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Se un elemento può ricevere lo stato attivo, ad esempio un <button>, puoi reagire a questo stato con la pseudo-classe :focus.

Puoi anche reagire se un elemento secondario del tuo elemento riceve lo stato attivo con :focus-within.

Gli elementi attivabili, come i pulsanti, mostreranno un anello di selezione quando sono attivi, anche quando vengono selezionati. In questo tipo di situazione, uno sviluppatore applicherà il seguente CSS:

button:focus {
    outline: none;
}

Questo CSS rimuove l'anello di selezione predefinito del browser quando un elemento riceve lo stato attivo, il che presenta un problema di accessibilità per gli utenti che navigano in una pagina web con una tastiera. Se non è presente uno stile di messa a fuoco, non sarà in grado di tenere traccia della posizione attuale della messa a fuoco quando utilizza il tasto Tab. Con :focus-visible puoi presentare uno stile di messa a fuoco quando un elemento riceve lo stato attivo tramite la tastiera, utilizzando anche la regola outline: none per impedirlo quando un dispositivo di puntamento interagisce con l'elemento.

button:focus {
    outline: none;
}

button:focus-visible {
    outline: 1px solid black;
}

:target

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.3.

Source

La pseudo-classe :target seleziona un elemento che ha un id corrispondente a un frammento URL. Supponiamo di avere il seguente codice HTML:

<article id="content">
    <!-- ... -->
</article>

Puoi allegare stili a questo elemento quando l'URL contiene #content.

#content:target {
    background: yellow;
}

Ciò è utile per evidenziare le aree a cui potrebbe essere stato creato un link specifico, ad esempio i contenuti principali di un sito web, utilizzando un link di salto.

Stati storici

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

La pseudo-classe :link può essere applicata a qualsiasi elemento <a> che abbia un valore href che non è stato ancora visitato.

:visited

Puoi applicare uno stile a un link già visitato dall'utente utilizzando la pseudo-classe :visited. Questo è lo stato opposto a :link, ma hai meno proprietà CSS da utilizzare per motivi di sicurezza. Puoi applicare uno stile solo a color, background-color, border-color, outline-color e al colore di fill e stroke in formato SVG.

L'ordine è importante

Se definisci uno stile :visited, può essere sostituito da una pseudoclasse di link con una specificità almeno uguale. Per questo motivo, è consigliabile utilizzare la regola LVHA per applicare lo stile ai link con pseudo-classi in un ordine specifico: :link, :visited, :hover, :active.

a:link {}
a:visited {}
a:hover {}
a:active {}

Stati del modulo

Le seguenti pseudoclassi possono selezionare gli elementi del modulo, nei vari stati in cui questi elementi potrebbero trovarsi durante l'interazione.

:disabled e :enabled

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 3.1.

Source

Se un elemento del modulo, ad esempio un <button>, è disattivato dal browser, puoi agganciarti a questo stato con la pseudo-classe :disabled. La pseudo-classe :enabled è disponibile per lo stato opposto, anche se gli elementi del modulo sono :enabled per impostazione predefinita, pertanto potresti non aver bisogno di questa pseudo-classe.

:checked e :indeterminate

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 3.1.

Source

La pseudo-classe :checked è disponibile quando un elemento del modulo di supporto, come una casella di controllo o un pulsante di opzione, è selezionato.

Lo stato :checked è uno stato binario (true o false), ma le caselle di controllo hanno uno stato intermedio quando non sono selezionate o deselezionate. Questo è noto come stato :indeterminate.

Un esempio di questo stato si verifica quando hai un controllo "Seleziona tutto" che seleziona tutte le caselle di controllo di un gruppo. Se l'utente deseleziona una di queste caselle di controllo, la casella di controllo principale non rappresenterà più "tutte" le caselle selezionate, pertanto deve essere impostata su uno stato indeterminato.

L'elemento <progress> ha anche uno stato indeterminato a cui è possibile applicare uno stile. Un caso d'uso comune è quello di conferirgli un aspetto a strisce per indicare che non è noto quanto altro sia necessario.

:placeholder-shown

Browser Support

  • Chrome: 47.
  • Edge: 79.
  • Firefox: 51.
  • Safari: 9.

Source

Se un campo del modulo ha un attributo placeholder e nessun valore, la pseudo-classe :placeholder-shown può essere utilizzata per collegare stili a questo stato. Non appena il campo contiene contenuti, indipendentemente dalla presenza o meno di un placeholder, questo stato non verrà più applicato.

Stati di convalida

Browser Support

  • Chrome: 10.
  • Edge: 12.
  • Firefox: 4.
  • Safari: 5.

Source

Puoi rispondere alla convalida dei moduli HTML con pseudo-classi come :valid, :invalid e :in-range. Le pseudo-classi :valid e :invalid sono utili per contesti come un campo email con un pattern che deve essere abbinato per essere un campo valido. Questo stato di valore valido può essere mostrato all'utente, aiutandolo a capire che può passare in sicurezza al campo successivo.

La pseudo-classe :in-range è disponibile se un input ha min e max, ad esempio un input numerico e il valore rientra in questi limiti.

Con i moduli HTML, puoi determinare che un campo è obbligatorio con l'attributo required. La pseudo-classe :required sarà disponibile per i campi obbligatori. I campi non obbligatori possono essere selezionati con la pseudo-classe :optional.

Selezionare gli elementi in base a indice, ordine e occorrenza

Esiste un gruppo di pseudo-classi che selezionano gli elementi in base alla loro posizione nel documento.

:first-child e :last-child

Browser Support

  • Chrome: 4.
  • Edge: 12.
  • Firefox: 3.
  • Safari: 3.1.

Source

Se vuoi trovare il primo o l'ultimo elemento, puoi utilizzare :first-child e :last-child. Queste pseudo-classi restituiranno il primo o l'ultimo elemento di un gruppo di elementi di pari livello.

:only-child

Browser Support

  • Chrome: 2.
  • Edge: 12.
  • Firefox: 1.5.
  • Safari: 3.1.

Source

Puoi anche selezionare elementi senza fratelli con la pseudo-classe :only-child.

:first-of-type e :last-of-type

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Source

Puoi selezionare :first-of-type e :last-of-type, che all'inizio sembrano fare la stessa cosa di :first-child e :last-child, ma considera questo codice HTML:

<div class="my-parent">
    <p>A paragraph</p>
    <div>A div</div>
    <div>Another div</div>
</div>

E questo CSS:

.my-parent div:first-child {
    color: red;
}

Nessun elemento verrà colorato di rosso perché il primo elemento secondario è un paragrafo e non un div. La pseudo-classe :first-of-type è utile in questo contesto.

.my-parent div:first-of-type {
    color: red;
}

Anche se il primo <div> è il secondo elemento secondario, è comunque il primo di tipo all'interno dell'elemento .my-parent, quindi con questa regola verrà colorato di rosso.

:nth-child e :nth-of-type

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Source

Inoltre, non sei limitato ai primi e agli ultimi figli e tipi. Le pseudo-classi :nth-child e :nth-of-type ti consentono di specificare un elemento che si trova a un determinato indice. L'indicizzazione nei selettori CSS inizia da 1.

Le pseudoclassi :nth-last-child() e :nth-last-of-type() contano dalla fine, anziché dall'inizio.

Puoi passare più di un indice anche in queste pseudo-classi. Se vuoi selezionare tutti gli elementi pari, puoi utilizzare :nth-child(even).

Puoi anche creare selettori più complessi che trovano elementi a intervalli regolari, utilizzando la microsintassi An+B.

li:nth-child(3n+3) {
    background: yellow;
}

Questo selettore seleziona ogni terzo elemento, a partire dall'elemento 3. Il n in questa espressione è l'indice, che inizia da zero e il 3 (3n) è il valore per cui moltiplicare l'indice.

Supponiamo che tu abbia 7 elementi <li>. Il primo elemento selezionato è 3 perché 3n+3 si traduce in (3 * 0) + 3. L'iterazione successiva selezionerebbe l'elemento 6 perché n è ora aumentato a 1, quindi (3 * 1) + 3). Questa espressione funziona sia per :nth-child sia per :nth-of-type.

:nth-child() e :nth-last-child() supportano anche una sintassi "of S" che consente di filtrare le corrispondenze con un selettore, in modo simile a :nth-of-type(). li:nth-of-type(even) è equivalente a :nth-child(even of li). Mentre :nth-of-type consente di filtrare solo in base al tipo di elemento (ad esempio li o p), la sintassi "di S" consente di filtrare in base a qualsiasi selettore.

Se hai una tabella, potresti voler aggiungere strisce a una riga sì e una no. Anche se puoi scegliere come target ogni altra riga contr:nth-child(even), questa opzione non funziona se filtri alcune righe. Se implementi il filtro applicando l'attributo hidden, puoi aggiungere of :not([hidden]) al selettore per prefiltrare gli elementi nascosti prima di selezionare le righe pari.

tr:nth-child(even of :not([hidden])){
  background: lightgrey;
}

Puoi sperimentare questo tipo di selettore in questo strumento di test nth-child o in questo strumento di selezione della quantità.

:only-of-type

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Source

Infine, puoi trovare l'unico elemento di un determinato tipo in un gruppo di elementi correlati con :only-of-type. Questa opzione è utile se vuoi selezionare elenchi con un solo elemento o se vuoi trovare l'unico elemento in grassetto in un paragrafo.

Trovare elementi vuoti

A volte può essere utile identificare gli elementi completamente vuoti ed esiste anche una pseudo-classe per questo.

:empty

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 3.1.

Source

Se un elemento non ha elementi secondari, si applica la pseudo-classe :empty. Tuttavia, gli elementi secondari non sono solo elementi HTML o nodi di testo: possono anche essere spazi vuoti, il che può creare confusione quando esegui il debug del seguente codice HTML e ti chiedi perché non funziona con :empty:

<div>
</div>

Il motivo è che c'è uno spazio vuoto tra l'apertura e la chiusura di <div>, quindi :empty non funzionerà.

La pseudo-classe :empty può essere utile se hai poco controllo sull'HTML e vuoi nascondere elementi vuoti, come un editor di contenuti WYSIWYG. In questo caso, un editor ha aggiunto un paragrafo vuoto.

<article class="post">
 <p>Donec ullamcorper nulla non metus auctor fringilla.</p>
 <p></p>
 <p>Curabitur blandit tempus porttitor.</p>
</article>

Con :empty, puoi trovare e nascondere questo tipo di contenuti.

.post :empty {
    display: none;
}

Trovare ed escludere più elementi

Alcune pseudo-classi ti aiutano a scrivere CSS più compatti.

:is()

Browser Support

  • Chrome: 88.
  • Edge: 88.
  • Firefox: 78.
  • Safari: 14.

Source

Se vuoi trovare tutti gli elementi secondari h2, li e img in un elemento .post, potresti pensare di scrivere un elenco di selettori come questo:

.post h2,
.post li,
.post img {
    
}

Con la pseudo-classe :is(), puoi scrivere una versione più compatta:

.post :is(h2, li, img) {
    /* ... */
}

La pseudo-classe :is non è solo più compatta di un elenco di selettori, ma è anche più tollerante. Nella maggior parte dei casi, se in un elenco di selettori è presente un errore o un selettore non supportato, l'intero elenco di selettori non funzionerà più. Se si verifica un errore nei selettori passati in una pseudo-classe :is, il selettore non valido viene ignorato, ma vengono utilizzati quelli validi.

:not()

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 3.1.

Source

Puoi anche escludere gli elementi con la pseudo-classe :not(). Ad esempio, puoi utilizzarlo per applicare uno stile a tutti i link che non hanno un attributo class.

a:not([class]) {
    color: blue;
}

Una pseudo-classe :not può anche aiutarti a migliorare l'accessibilità. Ad esempio, un <img> deve avere un alt, anche se è un valore vuoto, in modo da poter scrivere una regola CSS che aggiunga un contorno rosso spesso alle immagini non valide:

img:not([alt]) {
    outline: 10px red;
}

:has()

Cosa succede se vuoi applicare uno stile agli elementi in base al loro contenuto? Per farlo, puoi utilizzare la pseudo-classe :has(). Ad esempio, potresti voler applicare stili ai pulsanti che includono icone.

 button:has(svg) {
  /* ... */
}

Nella sua configurazione più semplice, come nell'esempio precedente, puoi considerare :has() come un selettore principale. Puoi anche utilizzare il selettore principale corrispondente combinato con altri selettori per scegliere come target altri elementi.

form:has(input:valid) label {
  font-weight: bold;
}

form:has(input:valid) label::after {
  content: "✅";
}

In questo esempio applichiamo gli stili all'elemento etichetta e allo pseudo-elemento label::after quando l'input del modulo ha una pseudo-classe valid.

La pseudo-classe :has() non può essere nidificata all'interno di un'altra :has(), ma può essere combinata con altre pseudo-classi.

:is(h1, h2, h3):has(a) {
   /* ... */
}

L'elenco dei selettori è inflessibile, quindi se uno qualsiasi dei selettori nell'elenco non è valido, tutte le regole di stile verranno ignorate.

.my-element:has(img, ::before) {
  /* any styles here will be discarded since pseudo elements can't be included in the :has() selector list */
}

Verifica la tua comprensione

Metti alla prova le tue conoscenze sulle pseudo-classi

Le pseudo-classi agiscono come se una classe fosse stata applicata dinamicamente a un elemento, mentre gli pseudo-elementi agiscono sull'elemento stesso.

Vero
Controlla l'utilizzo di un singolo o doppio : come carattere distintivo chiave nel selettore
Falso
Gli pseudo-elementi sono per le parti, le pseudo-classi sono per lo stato.

Quali delle seguenti sono pseudo-classi funzionali?

:is()
🎉
:target
Le pseudo-classi funzionali hanno () dopo, per indicare che accettano parametri.
:empty
Le pseudo-classi funzionali hanno () dopo, per indicare che accettano parametri.
:not()
🎉

Quali delle seguenti pseudo-classi sono dovute a un'interazione utente?

:hover
🎉
:press
Riprova.
:squeeze
Riprova.
:target
🎉
:focus-within
🎉

Quali delle seguenti sono pseudo-classi di stato <form>?

:enabled
🎉
:fresh
Riprova.
:indeterminate
🎉
:checked
🎉
:in-range
🎉
:loading
Riprova.
:valid
🎉