CSS: cascata, ereditarietà e specificità

CSS: cascata, ereditarietà e specificità

Cascata, ereditarietà e specificità sono tre concetti chiave che permettono ai browser di applicare correttamente gli stili specificati nei CSS. Scopo del presente articolo è quello di illustrare in dettaglio i concetti appena menzionati.

Introduzione

Una volta che un browser ha analizzato un documento e creato un albero del documento, esso assegna a ciascun elemento un valore per le proprietà che si applicano al tipo di media di destinazione (screen, print, ecc.).

Il valore finale di ogni proprietà è il risultato di un calcolo suddiviso in quattro fasi:

  1. Il valore viene determinato in base a quanto specificato (valore specificato).

  2. Il valore viene trasformato in un valore usato per l'ereditarietà (valore calcolato).

  3. Il valore viene convertito, se necessario, in un valore assoluto (valore in uso).

  4. Il valore viene trasformato tenendo presente i limiti dell'ambiente locale (valore effettivo).

Valori specificati

I browser devono per prima cosa assegnare un valore specificato a ciascuna proprietà in base alla seguente procedura (ordinata per precedenza):

  1. Se la cascata produce un valore, viene usato quello.

  2. Altrimenti, se la proprietà è ereditaria e l'elemento non è l'elemento radice dell'albero del documento, viene usato il valore calcolato dell'elemento genitore.

  3. Altrimenti, viene usato il valore iniziale della proprietà. Il valore iniziale di ciascuna proprietà è indicato nella definizione della proprietà.

Tutti i browser usano i valori specificati nel loro foglio di stile predefinito in mancanza dei valori specificati nel foglio di stile dell'autore o dell'utente. Per esempio:


ul, ol {margin-left: 2.5em;}

I browser applicheranno in questo caso i loro valori predefiniti per le restanti proprietà non specificate. In Firefox avremo:


ul, ol {margin: 1em 0; -moz-padding-start: 40px;}

Il valore del margine sinistro si andrà quindi a sommare al padding sinistro, causando una diversa visualizzazione nei vari browser. Dovremo quindi scrivere:


ul, ol {margin: 1em 0 1em 2.5em; padding: 0;}

Valori calcolati

I valori specificati vengono trasformati durante la cascata; per esempio, gli URI sono resi assoluti e l'unità em viene calcolata in pixel o in misure assolute.

Il valore calcolato degli URI che un browser non può trasformare in URI assoluti è il valore specificato.

Quando il valore specificato non è inherit, il valore calcolato di una proprietà si determina nel modo specificato nella riga Valore calcolato nella definizione della proprietà. Per esempio:

'width'
Valore: <lunghezza> | <percentuale> | auto | inherit
Iniziale: auto
Si applica a: tutti gli elementi, ma non agli elementi inline non rimpiazzati, righe di tabella e gruppi di righe
Ereditata: no
Percentuali: in riferimento alla larghezza del blocco contenitore
Valore calcolato: la percentuale o 'auto' come specificato o la lunghezza assoluta; 'auto' se la proprietà non si applica

Il valore calcolato esiste anche quando la proprietà non si applica, come definito nella riga Si applica a.

Valori in uso

Alcuni valori possono essere determinati solo quando il documento viene elaborato. Per esempio, se la larghezza di un elemento è impostata in percentuale rispetto al suo blocco contenitore, la larghezza non potrà essere determinata finchè non si sarà determinata la larghezza del blocco contenitore.

Il valore in uso è il risultato della trasformazione del valore calcolato in un valore assoluto.

Valori effettivi

Un valore in uso di solito viene usato per il layout finale, ma a volte un browser può non essere in grado di usare il valore a causa delle limitazioni imposte dal dispositivo dell'utente (schermo, colori, ecc.). Il valore effettivo è il risultato di questi aggiustamenti.

Ereditarietà

Alcuni valori vengono ereditati dai figli di un elemento. Ciascuna proprietà definisce se è ereditaria o no. Per esempio:


&lt;p&gt;Ibam &lt;em&gt;forte&lt;/em&gt; via sacra.&lt;/p&gt;

Se non viene assegnato nessun colore all'elemento em, l'elemento erediterà il colore del suo genitore. Quindi se il colore dell'elemento p è il nero, l'elemento em sarà nero.

Quando l'ereditarietà ha luogo, gli elementi ereditano i valori calcolati. Il valore calcolato per l'elemento genitore diviene il valore specificato e calcolato per i figli. Esempio:


body {font-size: 12px;}

h1 {font-size: 200%;}

In questo caso il valore calcolato per la dimensione del font dell'elemento h1 sarà del 200% superiore a quella dell'elemento body, ossia 24px.

Il valore 'inherit'

Ogni proprietà può anche avere come valore specificato inherit, che significa, per un dato elemento, assumere come valore calcolato il valore dell'elemento genitore. Esempio:


h1 em {color: inherit;}

a {background-color: inherit;}

La regola @import

La regola @import permette di importare regole di stile da altri fogli di stile.

Ogni regola @import inserita in un file .css deve precedere tutte le altre regole (tranne la regola @charset, se presente).

La parola chiave @import deve essere seguita dall'URI del foglio di stile da includere. Si può usare anche una stringa, che viene interpretata come se avesse url() attorno. Le seguenti regole sono equivalenti:


@import &quot;style.css&quot;;
@import url(&quot;style.css&quot;);

Per supportare tipi di media differenti e per assicurare che i browser non cerchino di interpretare media sconosciuti, è possibile specificare il media di destinazione nella regola @import. Se ci sono più tipi di media, i valori dopo l'URI vanno separati con virgole:


@import url(&quot;style.css&quot;) screen, handheld;

Cascata

I fogli di stile hanno tre diverse origini: autore, utente e browser.

  • Autore.

    L'autore specifica i fogli di stile per il documento secondo le convenzioni del linguaggio del documento.

  • Utente.

    L'utente può specificare delle informazioni di stile per un particolare documento.

  • Browser.

    I browser conformi devono applicare un foglio di stile predefinito.

Ordine della cascata

Per trovare il valore per una combinazione elemento/proprietà, i browser devono seguire questo ordine:

  1. Trovare tutte le dichiarazioni che si applicano all'elemento e alla proprietà in questione per il media di destinazione. Le dichiarazioni si applicano se il selettore seleziona l'elemento.

  2. Ordinare secondo l'importanza (normale o !important) e l'origine (autore, utente o browser), secondo un ordine crescente di precedenza:

    1. dichiarazioni del browser
    2. dichiarazioni normali dell'utente
    3. dichiarazioni normali dell'autore
    4. dichiarazioni !important dell'autore
    5. dichiarazioni !important dell'utente
  3. Ordinare le regole con la stessa importanza e origine per specificità del selettore: selettori più specifici sovrascriveranno quelli più generici. Gli pseudo-elementi e le pseudo-classi vengono considerati rispettivamente elementi e classi normali.

  4. Infine, ordinare secondo l'ordine specificato: se due dichiarazioni hanno lo stesso peso, origine e specificità, l'ultima specificata vince. Le dichiarazioni nei fogli di stile importati vengono prima di quelle nel foglio di stile principale.

La regola !important

La regola !important aumenta il peso di una dichiarazione rispetto ad una dichiarazione normale. Tale regola segue sempre la dichiarazione:


body {font-size: 100% !important;}

Le regole !important di un foglio di stile dell'utente vincono sempre su quelle di un foglio di stile dell'autore.

Specificità dei selettori

La specificità di un selettore si calcola come segue:

  • si conti 1 se il selettore è un attributo style, altrimenti 0 (=a). Nell'HTML, i valori dell'attributo style sono regole di stile, così avremo: a=1, b=0, c=0, d=0.

  • si conti il numero di attributi id nel selettore (=b)

  • si conti il numero di altri attributi e pseudo-classi nel selettore (=c)

  • si conti il numero di nomi di elemento e pseudo-elementi nel selettore (=d)

Concatenando i quattro numeri (a, b, c, d) in serie, in un ordine di precedenza decrescente che va da sinistra a destra e confrontando quindi i numeri da sinistra a destra, otteniamo la specificità di un selettore. Esempi:


* { } /* a=0 b=0 c=0 d=0
      specificità =  0, 0, 0, 0 */
	  
p { } /* a=0 b=0 c=0 d=1
      specificità = 0, 0, 0, 1 */
	 
#id { } /* a=0 b=1 c=0 d=0
      specificità = 0, 1, 0, 0 */
	  
style=&quot; &quot; /* a=1, b=0 c=0 d=0
      specificità = 1, 0, 0, 0 */

Si tenga presente che i valori posti più a sinistra vincono su quelli posti più a destra, a prescindere dal numero di valori. Quindi se anche l'elemento p avesse avuto quattro valori su d (per esempio con una concatenazione di selettori del discendente come body div div p { }) non sarebbe riuscito a vincere né su #id nè su style, i quali hanno i loro valori posti più a sinistra superiori ai corrispondenti valori dell'elemento p (a=1 e b=1 per i primi, contro a=0 e b=0 per il secondo). L'attributo style ha una specificità superiore agli altri perché è l'unico ad avere il valore posto più a sinistra (a=1) superiore agli altri (a=0).

Torna su