Modifiche all'eredità per lo stile di selezione CSS

Stephen Chenney
Stephen Chenney

Data di pubblicazione: 8 ottobre 2024

A partire da Chrome 131, l'eredità degli elementi evidenziati CSS sta cambiando per le pseudoclassi ::selection e ::target-text. Il motivo è creare un modello più intuitivo per l'eredità e allinearsi alle pseudoclassi ::highlight, ::spelling-error e ::grammar-error aggiunte di recente. Questo post illustra la modifica, che non dovrebbe avere un impatto visibile sulla maggior parte dei siti.

Stile di selezione

Lo stile dell'aspetto del testo selezionato può trasmettere un significato agli utenti, ad esempio lo scopo dei contenuti selezionati o l'impossibilità di selezionare il testo. GitHub, ad esempio, colora il codice selezionato in modo diverso dalla struttura della directory selezionata.

CSS supporta gli stili di selezione con lo pseudo-elemento ::selection, uno di un insieme di pseudo-elementi noti come pseudo-elementi di evidenziazione. Questi pseudo-elementi controllano la visualizzazione del testo in base a varie azioni eseguite dall'utente, dal browser o dallo script. Oltre alla selezione, puoi applicare stili agli errori ortografici (::spelling-error), agli errori grammaticali (::grammar-error), ai target di testo incorporati nell'URL (::target-text) e agli elementi evidenziati generati da script (::highlight).

Come per qualsiasi raccolta di proprietà CSS, il comportamento di ereditarietà è un aspetto importante da considerare durante la progettazione di un sito. In genere, gli sviluppatori si aspettano che le proprietà CSS vengano ereditate tramite la struttura ad albero degli elementi DOM (ad es. font) o che non vengano ereditate affatto (ad es. background).

Modifiche al comportamento di selezione in Chrome 131

Considera questo frammento di documento:

p {
  color: red;
}

.blue::selection {
  color: blue;
}
<p class="blue">Some <em>emphasized</em> text that one would expect to be blue</p>

Le dichiarazioni di stile del frammento modificano il colore del testo selezionato, con una regola che corrisponde a tutti gli elementi e una che corrisponde a quelli con la classe "blue". Se questa opzione è selezionata in Chrome 130 o versioni precedenti, il risultato è il seguente:

Il testo che ti aspetteresti di vedere in blu è rosso.

Se viene selezionato in Chrome 131, il risultato diventa il seguente:

Il testo viene evidenziato in blu.

Che cosa è cambiato? Il comportamento di ereditarietà delle proprietà di selezione è stato storico implementato tramite l'ereditarietà dell'elemento di origine, dove la selezione utilizza le proprietà di un ::selection corrispondente all'elemento selezionato. Le versioni di Chrome 130 e precedenti utilizzano questo modello, in cui il testo evidenziato non ha una corrispondenza ::selection perché .blue::selection corrisponde solo agli elementi con la classe "blue", che non è presente nell'elemento <em>.

Chrome 131 attiva un nuovo comportamento in base al quale gli elementi ereditano il comportamento di selezione dall'elemento principale. Nell'esempio precedente, l'elemento <em> non ha un ::selection corrispondente, quindi eredita i colori di selezione dell'elemento <p>. Si tratta della eredità degli elementi evidenziati CSS e puoi provarla nelle versioni precedenti di Chrome attivando le funzionalità sperimentali della piattaforma web in chrome://flags.

I siti che si basano su proprietà di selezione non ereditabili potrebbero subire modifiche nell'aspetto del testo selezionato, ma le prove dei report di bug suggeriscono che esistono pochi casi d'uso per questo comportamento.

Le proprietà CSS personalizzate per la selezione continuano a funzionare

Molti siti simulano l'eredità degli elementi evidenziati CSS tramite l'uso di proprietà personalizzate CSS. Le proprietà personalizzate vengono ereditate tramite la struttura ad albero degli elementi, generando l'esito "eredita dal padre" con uno snippet di codice come questo:

:root {
   --selection-color: lightgreen;
}

::selection {
  color: var(--selection-color);
}

.blue {
  --selection-color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text that is blue</p>

Questo è il risultato quando viene selezionato sia in Chrome 130 che in 131:

La prima riga è verde, la seconda blu.

Qui ogni elemento eredita un valore per la proprietà --selection-color tramite la struttura ad albero degli elementi e questo colore viene utilizzato quando il testo è selezionato. Gli elementi con la classe .blue e i relativi discendenti sono blu quando sono selezionati, mentre gli altri elementi sono di colore verde chiaro. Molti siti utilizzano questa tecnica ed è il metodo consigliato su Stack Overflow.

Per mantenere la compatibilità, il modello di ereditarietà degli elementi evidenziati CSS specifica che ::selection (e altri pseudo-elementi di evidenziazione CSS) ereditano i valori delle proprietà personalizzate dall'elemento di origine (l'elemento a cui vengono applicati). I siti che utilizzano questo metodo non dovrebbero essere interessati dalle modifiche in Chrome. 131

Le proprietà personalizzate definite sullo pseudo-elemento ::selection stesso vengono ignorate per evitare comportamenti di ereditarietà in concorrenza. Devi definire le proprietà sull'elemento stesso e poi farvi riferimento nello pseudo elemento.

Selettori universali per ::selection disattivare l'ereditarietà dell'evidenziazione

I siti che non utilizzano le proprietà CSS personalizzate potrebbero aver utilizzato un selettore universale per impostare il colore del testo selezionato. Ad esempio, il seguente CSS:

::selection /* = *::selection (universal) */ {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

Questo è il risultato quando l'opzione è selezionata sia in Chrome 130 (e versioni precedenti) sia in Chrome 131 (e versioni successive):

La prima riga di testo è verde. Il secondo è blu, ma la parola evidenziata è verde.

L'eredità dell'evidenziazione CSS non fa ereditare il blu dal testo evidenziato perché il selettore universale corrisponde all'elemento <em> e applica il colore di evidenziazione universale, verde chiaro.

Per usufruire dei vantaggi dell'eredità dell'evidenziazione CSS, modifica il selettore universale in modo che corrisponda solo all'elemento principale, che verrà poi ereditato dai suoi discendenti:

:root::selection {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

Il risultato in Chrome 131 è il seguente:

La prima riga di testo è verde. La seconda riga è blu.

Se il tuo sito modifica i colori di selezione, ma non utilizza proprietà personalizzate, è probabile che tu abbia un selettore universale per l'elemento pseudo ::selection. La buona notizia è che il tuo sito non avrà problemi con questa modifica in Chrome, ma perderai tutti i vantaggi ergonomici dell'eredità degli indicatori.

Anche lo stile di ::target-text sta cambiando

Tutti i comportamenti e le modifiche descritti qui si applicano allo pseudo-elemento ::target-text come a ::selection. I casi d'uso per più stili di testo target su un singolo sito sono limitati e la funzionalità è piuttosto nuova, pertanto è molto improbabile che il comportamento di ::target-text cambi sul tuo sito.

Perché questa modifica?

Quando gli altri pseudo-elementi di evidenziazione erano in fase di sviluppo, il gruppo di lavoro CSS ha deciso di implementare l'ereditarietà con il modello di ereditarietà degli elementi evidenziati. Questo era già il metodo nella specifica dell'elemento pseudo::selection, ma i browser non lo hanno implementato. Gli pseudo-elementi di non selezione utilizzano l'eredità dell'evidenziazione, in cui lo pseudo-elemento viene ereditato come se fosse una proprietà. In altre parole, gli elementi ereditano gli pseudo-elementi di evidenziazione dal documento principale.

Nell'interesse della coerenza tra tutti gli pseudo-elementi di evidenziazione, il gruppo di lavoro CSS ha ribadito il supporto dell'eredità dell'evidenziazione per ::selection e i browser stanno lavorando per lanciare il nuovo comportamento, cercando al contempo di non interrompere il funzionamento dei siti esistenti.

Prova

Il seguente CodePen mostra le modifiche. Provala in Chrome 131.