Ereditarieta' e stili a cascata
Come ho detto in precedenza, ogni pagina è strutturata come un albero genealogico, dove ogni tag rappresenta un componente della famiglia (o della dinastia, a seconda di quanto sia ramificata). Al vertice di tutto, come capostipite, si trova il tag <html>, al cui interno è contenuta la pagina intera; il tag <html> ha a propria volta due figli, ossia il tag <head> e il tag <body>. Il tag <head> ci interessa poco, perché non ci offre nulla da impaginare; il tag <body>, invece, è il contenitore di tutta la nostra pagina e possiederà un grande numero di discendenti. Il nostro lavoro di impaginazione si concentrerà quasi esclusivamente su <body> e la sua allegra stirpe.
4-1 Ereditare uno stile
È importante avere sempre una buona idea della struttura delle nostre pagine, per un motivo molto semplice: quasi tutte le proprietà che assegniamo a un elemento saranno ereditate anche dai suoi discendenti. Quando assegniamo una proprietà al tag <body>, tutti i tag contenuti in <body> (cioè tutto ciò che vediamo sullo schermo) la erediteranno. Quando assegniamo una proprietà a un tag <p>, tutti i tag contenuti in <p> la erediteranno. E così via. Allo stesso modo, quando assegniamo una proprietà a una classe di stile, tutti gli elementi contenuti in un tag, che utilizza quella classe, erediteranno la proprietà della classe.
Un uso accorto della ereditarietà può farci risparmiare tempo e fatica. Per assicurarci che tutta la pagina utilizzi un determinato stile (ad esempio, lo stesso tipo di font), basta assegnare quella proprietà al tag <body> e ogni elemento al suo interno la erediterà. Se poi decidiamo che un certo elemento dovrà presentare uno stile diverso, basterà assegnare uno stile specifico a quell’elemento.
In breve, l’ereditarietà si applica in questo modo:
- se un elemento possiede uno stile specifico, usa quello stile;
- se un elemento non possiede uno stile specifico, usa lo stile del suo genitore.
Ovviamente, la regola è ricorsiva. Per decidere come visualizzare un elemento, un dispositivo di lettura cercherà prima di tutto uno stile specifico per quell’elemento. Se lo trova, lo utilizza e tutto si conclude così. Se non lo trova, cercherà lo stile specifico per il genitore dell’elemento. Se anche il genitore non possiede uno stile specifico, cercherà lo stile del genitore del genitore. E così via, fino a che non sarà trovato uno stile da applicare. Se nessuno stile esiste, sarà applicato lo stile di default, che può variare a seconda del dispositivo di lettura.
Un esempio di questo meccanismo è il tipo di font da utilizzare, per visualizzare un testo. Se il testo possiede una proprietà font, il lettore utilizzerà quella proprietà. Se non la possiede, cercherà la proprietà font del suo genitore. Se neppure il genitore possiede un proprietà font, si cercherà la proprietà del genitore del genitore. Alla fine, se nessuna proprietà font è stata trovata, il lettore userà il tipo di font che è stato impostato come base per quel dispositivo.
Considerato questo meccanismo, una strategia razionale per impaginare il nostro libro è:
- assegniamo a un elemento <body> tutte le proprietà più generali e generiche, che tutto il nostro e-book dovrà possedere;
- per ogni elemento, specifichiamo le eventuali proprietà che dovrà possedere, se sono diverse dalle proprietà generali;
- partiamo sempre dagli elementi più grandi e scendiamo via via verso gli elementi più piccoli e specifici: definiamo prima lo stile di una pagina, poi lo stile di un paragrafo, quindi lo stile delle singole parti di un paragrafo, se dovranno essere diverse dallo stile generale.
Ovviamente, potranno esserci casi in cui questa strategia generale non sarà applicabile, o almeno non sarà applicabile per intero, ma resta comunque un buon punto di partenza, quando dovete decidere come organizzare il vostro lavoro. L’esperienza, poi, vi insegnerà eventuali sistemi per migliorarla, a seconda delle vostre abitudini e delle vostre preferenze.
4-2 Stile a cascata
Come spiegato in precedenza, lo stile discende per via ereditaria, dagli elementi più in alto (gli antenati) verso gli elementi più in basso (i discendenti). In una struttura di questo tipo, è possibile che, di tanto in tanto, si verifichino conflitti fra più stili e si debba determinare quale sia lo stile più forte, che sarà dunque applicato a un certo elemento. Situazioni di conflitto si possono tipicamente verificare in due casi:
- quando gli antenati di un elemento assegnano valori differenti a un dato attributo;
- quando due o più regole diverse sono applicate a uno stesso elemento.
Per risolvere questi conflitti, il CSS dispone di un semplice “codice della strada”, in cui sono indicate le norme di precedenza tra le regole di stile. Questo codice della strada è chiamato “cascata” o, se preferite il termine inglese, “cascade” (cambiano solo le ultime due lettere e il significato è identico).
Queste norme di precedenza sono molto semplici e, di fatto, le abbiamo già viste: le riassumerò in breve.
- una regola attribuita a un elemento ha la precedenza su qualsiasi regola possa aver ereditato dai suoi antenati;
- il più vicino antenato ha la precedenza sugli antenati più lontani.
Fin qui, sono le norme di cui abbiamo discusso, parlando della ereditarietà. Ci sono però anche altri casi da considerare, che non rientrano in queste norme. Che fare, ad esempio, quando un elemento possiede sia una regola impostata per il suo tipo di tag, sia una regola impostata per la sua classe? Ad esempio, se abbiamo un tag
<p class="nota">
e nel nostro foglio di stile abbiamo definito sia una regola per il tag <p>
p {
color: blue;
}
sia una regola per la classe “nota”
.nota {
color: red;
}
, di che colore sarà il testo delimitato da quel tag? Userà la regola del tag, assumendo quindi il colore blu, oppure la regola della classe, assumendo quindi il colore rosso?
In casi come questo, dovremo ricorrere a un poco di aritmetica, per determinare lo stile vincente. Il CSS definisce alcuni punteggi, che sono assegnati alle varie regole, a seconda di come siano applicate: per il nostro lavoro sugli e-books, ci interessano soltanto due di questi punteggi, ossia
- un selettore per tag vale 1 punto;
- un selettore per classe vale 10 punti.
Gli pseudoelementi hanno lo stesso valore dei selettori per tag, mentre le pseudoclassi hanno lo stesso valore dei selettori per classe. Nel nostro esempio, abbiamo un selettore per tag (la regola assegnata al tag <p>) e un selettore per classe (la regola assegnata alla classe “nota”). Il selettore per tag vale 1, il selettore per classe vale 10; siccome 10 è superiore a 1, vince il selettore per classe e il testo sarà colorato di rosso.
Questa norma di precedenza si applica soltanto quando le regole sono in conflitto, ossia quando le regole assegnano valori diversi a uno stesso attributo; se le regole operano su attributi diversi, non ci sono conflitti e tutte le regole saranno applicate, secondo la normale ereditarietà.
Di conseguenza, se abbiamo sempre il nostro tag <p class="nota">
e nel nostro foglio di stile abbiamo definito sia una regola per il tag <p>
p {
color: blue;
}
sia una regola per la classe “nota”
.nota {
font-size: 10px;
}
, le due regole non sono in conflitto, perché agiscono su attributi diversi: la prima sul colore, la seconda sulla dimensione dei caratteri. Dato che non c’è conflitto, le due regole possono coesistere pacificamente ed entrambe saranno applicate per intero al testo: avremo così un testo di colore blu e di 10 pixel di dimensione. Se utilizziamo selettori dei discendenti, oppure selettori dei figli, dovremo sommare i vari punteggi, per determinare quale regola abbia più valore e, dunque, la precedenza sulle altre.
Infine, resta un ultimo caso da esaminare: cosa succede, se due o più regole hanno uno stesso punteggio? In caso di pareggio, vince la regola che si trova più in basso nel foglio di stile.
Ad esempio, osserviamo un paragrafo di questo tipo:
<p class="nota">Per ulteriori informazioni in proposito, cercate pure su <a href="http://www.google.com" class="esterno">Google</a>.</p>
Nel relativo foglio di stile, poi, troviamo queste due regole:
p.nota {
color: blue;
}
a.esterno {
color: red;
}
La prima regola si applica a tutti i tag <p>, che possiedono una classe “nota”; la seconda regola si applica a tutti i tag <a>, che possiedono una classe “esterno”. Nel paragrafo in esame, entrambe le regole si dovrebbero applicare. Di che colore sarà la parola “Google”?
Entrambe le regole totalizzano uno stesso punteggio, ossia 11: 1 punto dato dal selettore per tag, più 10 punti dati dal selettore per classe. Dobbiamo dunque guardare nel foglio di stile, per scoprire quale regola sia stata inserita per ultima. Nel nostro caso, l’ultima regola è quella che prevede il colore rosso, per il testo: la parola “Google” sarà pertanto colorata di rosso.
Se nel foglio di stile invertiamo l’ordine di queste regole, ottenendo dunque
a.esterno {
color: red;
}
p.nota {
color: blue;
}
, la parola “Google” sarà colorata di blu, perché l’ultima regola prevede che il colore per il testo sia blu. Come si può capire, è fondamentale inserire le regole nel corretto ordine, se non vogliamo brutte sorprese: partiamo sempre dalle regole più generali e scendiamo via via verso le più specifiche.