6 Assegnazione di valori di proprietà, collegamento a cascata ed eredità

Sommario

6.1 Valori specificati, calcolati ed effettivi

Una volta che un programma utente [user-agent] ha analizzato [parsed] un documento e costruito un albero del documento, deve assegnare, per ogni elemento nell'albero, un valore ad ogni proprietà che si applica al tipo di media di destinazione.

Il valore finale di una proprietà è il risultato di un calcolo suddiviso in tre fasi: il valore è determinato attraverso la specifica (il "valore specificato"), quindi risolto in un valore assoluto se necessario (il "valore calcolato"), ed infine trasformato secondo i limiti dell'ambiente locale (il "valore effettivo").

6.1.1 Valori specificati

I programmi utente [user-agents] devono per prima cosa assegnare un valore specificato ad una proprietà basato sui seguenti meccanismi (in ordine di precedenza):

  1. Se la cascata risulta in un valore, la si usi.
  2. Altrimenti, sela proprietà è ereditata, si usi il valore dell'elemento genitore, generalmente il valore calcolato.
  3. Altrimenti si usi il valore iniziale della proprietà. Il valore iniziale di ogni proprietà è indicato nella definizione della proprietà.

Poichè non ha genitore, la radice dell'albero del documento non può usare valori dall'elemento genitore; in questo caso, il valore iniziale è usato se necessario.

6.1.2 Valori calcolati

I valori specificati possono essere assoluti (ossia non sono specificati in relazione ad un altro valore, come in 'red' or'2mm') o relativi (ossia sono specificati in relazione ad un altro valore, come in 'auto', '2em', e '12%'). Per i valori assoluti, nessun calcolo è richiesto per trovare il valore calcolato.

Valori relativi, del resto, devono essere trasformati in valori calcolati: le percentuali devono essere moltiplicate da un valore di riferimento (ogni proprietà definisce quale è il valore), i valori con unità elative (em, ex, px) devono essere resi assoluti moltiplicandoli con l'appropriata dimensione del font [carattere] o del pixel, i valori 'auto' devono essere calcolati dalle formule date con ogni proprietà, alcune parole chiave ('smaller', 'bolder', 'inherit') devono essere rimpiazzate secondo le loro definizioni.

In molti casi, gli elementi ereditano i valori calcolati. Tuttavia, vi sono delle proprietà il cui valore specificato può essere ereditato (per esempio, il valore per la proprietÓ 'line-height'). Nei casi in cui gli elementi figli non ereditano il valore calcolato, questo viene descritto nella definizione della proprietà.

6.1.3 Valori effettivi

Un valore calcolato è di principio pronto per essere usato , ma un programma utente [user-agent] può non essere in grado di fare uso del valore in un dato ambiente [environment]. Per esempio, un programma utente [user-agent] può solo essere in grado di rendere [to render] i bordi con larghezze di pixel interi, e può perciò dover approssimare la larghezza calcolata. Il valore effettivo è il valore calcolato dopo l'applicazione di ogni approssimazione.

6.2 Eredità

Alcuni valori sono ereditati dai figli di un elemento nell'albero del documento. Ogni proprietà definisce se il valore è ereditato o meno.

Si supponga che vi sia un elemento H1 con un elemento di enfasi (EM) al suo interno:

<H1>The headline <EM>is</EM> important!</H1>

Se non viene assegnato alcun colore all'elemento EM, lo "is" enfatizzato erediterà il colore dell'elemento genitore, sicchè se H1 è di colore blu, l'elemento EM sarà allo stesso modo blu.

Per impostare una proprietà di stile "predefinita" per un documento, gli autori possono impostare la proprietà sulla radice dell'albero del documento. In HTML, per esempio, gli elementi HTML o BODY possono assolvere a questa funzione . Si noti che questo funzionerà anche se l'autore omette il tag BODY nel sorgente HTML, poichè il parser [analizzatore] HTML desumerà [to infer] il tag mancante.

Esempi(o):

Per esempio, poichè la proprietà 'color' è ereditata, tutti i discendenti dell'elemento BODY erediteranno il colore 'black':

BODY { color: black; }

Valori percentuali specificati non sono ereditati; i valori calcolati lo sono.

Esempi(o):

Per esempio, dato il seguente foglio di stile:

BODY { font-size: 10pt }
H1 { font-size: 120% }

e questo frammento di documento:

<BODY>
  <H1>A <EM>large</EM> heading</H1>
</BODY>

la proprietà 'font-size' per l'elemento H1 avrà il valore calcolato '12pt' (il 120% di 10pt, il valore del genitore). Poichè il valore calcolato di 'font-size' è ereditato, anche l'elemento EM avrà il valore calcolato di '12pt'. Se il programma utente [user-agent] non ha disponibile il font [carattere] da 12pt, il valore effettivo di 'font-size' sia per H1 che per EM, potrebbe essere, per esempio, '11pt'.

6.2.1 Il valore 'inherit'

Ogni proprietà può anche avere il valore specificato di 'inherit', il che vuol dire, per un dato elemento, che la proprietà prende lo stesso valore calcolato della proprietà dell'elemento genitore. Il valore ereditato, che è normalmente usato solo come un valore di ripiego, può essere rafforzato impostando 'inherit' esplicitamente.

Esempi(o):

Nel esempio di sotto, le proprietà 'color' e 'background' sono impostate sull'elemento BODY. Su tutti gli altri elementi, il valore di 'color' sarà ereditato e lo sfondo sarà trasparente. Se queste regole sono parte di un foglio di stile dell'utente, il testo nero su sfondo bianco sarà consolidato su tutto il documento.

BODY { 
  color: black !important; 
  background: white !important;
}

* { 
  color: inherit !important; 
  background: transparent;
}

6.3 La regola @import

La regola '@import' permette agli utenti di importare regole di stile da altri fogli di stile. Ogni regola @import deve precedere tutte gli insiemi di regole in un foglio di stile. La parola chiave '@import' deve essere seguita dall'URI del foglio di stile da includere. È permessa anche una stringa; verrà interpretata come se avesse intorno url(...).

Esempi(o):

Le righe seguenti sono equivalenti nel significato ed illustrano entrambe le sintassi di '@import' (una con "url()" ed una con una semplice stringa):

@import "mystyle.css";
@import url("mystyle.css");

Affinchè i programmi utente [user-agent] possano evitare di reperire risorse da tipi di media non supportati, gli autori possono specificare regole @import dipendenti dai media. Queste importazioni condizionali specificano i tipi di media, separati da virgola, dopo l'URI.

Esempi(o):

Le seguenti regole hanno lo stesso effetto del foglio di stile racchiuso in una regola @media per lo stesso media, ma in questo caso evitano al programma utente [user-agent o UA] un download [scaricamento] inutile.

@import url("fineprint.css") print;
@import url("bluish.css") projection, tv;

In assenza di tipi di media, l'importazione è incondizionale. Specificare 'all' per il medium ha lo stesso effetto.

6.4 La cascata

I fogli di stile possono avere tre differenti origini: autore [author], utente [user], e programma utente [user-agent].

I fogli di stile derivati da queste tre origini si sovrapporranno nell'ambito di applicazione [scope], e interagiranno secondo la cascata.

La cascata CSS assegna un peso [weight] ad ogni regola di stile. Quando si applicano diverse regole, quella con il peso più grande ha la precedenza.

Per impostazione predefinita [by default], le regole nel foglio di stile dell'autore hanno più peso delle regole nei fogli di stile dell'utente. La precedenza è invertita, tuttavia, per le regole "!important". Sia le regole dell'utente che dell'autore hanno più peso di quelle nel foglio di stile predefinito del programma utente.

La cascata e il peso dei fogli di stile importati dipendono dal loro ordine di importazione. Le regole specificate in un dato foglio di stile sovrascrivono le regole importate da altri fogli di stile. I fogli di stile importati possono essi stessi importare e sovrascrivere altri fogli di stile, ricorsivamente, e applicare le stesse regole di precedenza.

6.4.1 Ordine di cascata

Per trovare il valore per una combinazione elemento/proprietà, i programmi utente devono applicare il seguente ordine di classificazione [sorting]:

  1. Trovare tutte le dichiarazioni che si applicano all'elemento e alla proprietà in questione per il tipo di media d'arrivo. Le dichiarazioni si applicano se il selettore associato seleziona l'elemento in questione.
  2. La classificazione primaria delle dichiarazioni è per peso e origine: per le dichiarazioni normali, i fogli di stile dell'autore sovrascrivono i fogli di stile dell'utente che a loro volta sovrascrivono il foglio di stile predefinito. Per le dichiarazioni "!important", i fogli di stile dell'utente sovrascrivono i fogli di stile dell'autore che a loro volta sovrascrivono il foglio di stile predefinito. La dichiarazione "!important" sovrascrive le dichiarazioni normali. Un foglio di stile importato ha la stessa origine del foglio di stile che lo ha importato.
  3. La classificazione secondaria è per specificità del selettore: selettori più specifici sovrascriveranno quelli più generici. Gli pseudo-elementi e le pseudo-classi sono calcolati, rispettivamente, come normali elementi e classi.
  4. Da ultimo, la classificazione per ordine specificato: se due regole hanno lo stesso peso, origine e specificità, l'ultima ad essere specificata vince. Le regole nei fogli di stile importati si considerano precedenti a tutte le regole nel foglio di stile stesso.

Tranne per l'impostazione "!important" sulle dichiarazioni individuali, questa strategia da ai fogli di stile dell'autore un peso più alto di quelli del lettore. È perciò importante che il programma utente dia all'utente la capacità di interrompere l'influenza di un determinato foglio di stile, per esempio con un menu a discesa.

6.4.2 Regole !important

I CSS cercano di creare un equilibrio di forze fra i fogli di stile dell'autore e quelli dell'utente. Per impostazione predefinita, le regole nel foglio di stile dell'autore sovrascrivono quelle nel foglio di stile dell'utente (si veda cascata, regola 3).

Tuttavia, per equilibrio, una dichiarazione "!important" (le parole chiave "!" e "important" seguono la dichiarazione) hanno la precedenza su una dichiarazione normale. Sia i fogli di stile dell'autore che dell'utente possono contenre dichiarazioni "!important", e le regole "!important" dell'utente sovrascrivono le regole "!important" dell'autore. Questa caratteristica dei CSS aumenta l'accessibilità dei documenti, dando agli utenti con speciali esigenze (font [caratteri] grandi, combinazione di colore, ecc.) il controllo sulla presentazione.

Nota. Questo è un cambiamento semantico dai CSS1. Nei CSS1, le regole "!important" dell'autore avevano la precedenza sulle regole "!important" dell'utente.

Dichiarare una proprietà abbreviata [shorthand] (per esempio 'background') "!important" è equivalente a dichiarare tutte le sue sotto-proprietà "!important".

Esempi(o):

La prima regola nel foglio di stile dell'utente nel seguente esempio contiene una dichiarazione"!important", che sovrascrive la corrispondente dichiarazione nel foglio di stile dell'autore. Anche la seconda dichiarazione vincerà, perchè è marcata "!important". Tuttavia, la terza regola nel foglio di stile dell'utente non è "!important" e perciò perderà in favore della seconda regola nel foglio di stile dell'autore (che imposta lo stile su una proprietà abbreviata). Anche la terza regola dell'autore perderà in favore della seconda regola dell'autore,, poichè tale regola è "!important". Questo mostra come le dichiarazioni "!important" svolgano una funzione anche all'interno dei fogli di stile dell'autore.

/* From the user's style sheet */
P { text-indent: 1em ! important }
P { font-style: italic ! important }
P { font-size: 18pt }

/* From the author's style sheet */
P { text-indent: 1.5em !important }
P { font: 12pt sans-serif !important }
P { font-size: 24pt }

6.4.3 Calcolare la specificità di un selettore

La specificità di un selettore è calcolata come segue:

La concatenazione dei tre numeri a-b-c (in un sistema numerico a base estesa) da la specificità.

Esempi(o):

Alcuni esempi:

*             {}  /* a=0 b=0 c=0 -> specificity =   0 */
LI            {}  /* a=0 b=0 c=1 -> specificity =   1 */
UL LI         {}  /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI      {}  /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]{}  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red  {}  /* a=0 b=1 c=3 -> specificity =  13 */ 
LI.red.level  {}  /* a=0 b=2 c=1 -> specificity =  21 */
#x34y         {}  /* a=1 b=0 c=0 -> specificity = 100 */ 

In HTML, i valori di un attributo "style" dell'elemento sono regole di fogli di stile. Queste regole non hanno selettori, ma per lo scopo del punto 3 dell'algoritmo di cascata, si ritiene che abbiano un selettore ID (specificità: a=1, b=0, c=0). Per lo scopo del punto 4, si ritiene che siano dopo tutte le altre regole.

<HEAD>
<STYLE type="text/css">
  #x97z { color: blue }
</STYLE>
</HEAD>
<BODY>
<P ID=x97z style="color: red">
</BODY>

Nell'esempio di sopra, il colore dell'elemento P sarà rosso. Quantunque la specificità sia la stessa nelle due dichiarazioni, la dichiarazione nell'attributo "style" sovrascriverà quella nell'elemento STYLE a causa della regola 4 del collegamento a cascata.

6.4.4 Precedenza delle indicazioni presentazionali non-CSS

I programmi utente possono scegliere di rispettare indicazioni presentazionali provenienti da fonti diverse rispetto ai fogli di stile, come ad esempio l'elemento FONT o l'attributo "align" in HTML. Se questo accade, le indicazioni presentazionali non-CSS devono essere trasposte nelle corrispettive regole CSS con specificità pari a zero. Si suppone che le regole siano all'inizio del foglio di stile dell'autore e che possano essere sovrascritte da successive regole del foglio di stile.

Nota. In una fase di transizione, questa politica faciliterà la coesistenza di attributi stilistici con i fogli di stile.

Nota. Nei CSS1, le indicazioni presentazionali non-CSS avevano specificità pari a 1, non a 0. Il cambiamento è dovuto all'introduzione del selettore universale, che ha specificità 0.