28. Herència i cascada
Tommy Olsson. 26 de setembre de 2008. Darrera modificació: 2 d'agost de 2017 (equip docent del grau de Multimèdia de la UOC). Publicat a: importància, font, ordre, important, especificitat.
L'herència i la cascada són dos conceptes bàsics en CSS. S'han de comprendre bé per fer servir CSS. Per sort, no són gaire difícils d'entendre, tot i que alguns detalls poden ser una mica complicats de recordar.
Els dos conceptes estan relacionats, però són diferents. L'herència està relacionada amb com els elements de l'etiquetatge de l'HTML hereten propietats dels seus elements pares (els que els contenen) i els transmeten als seus fills, mentre que la cascada té a veure amb les declaracions de CSS que s'apliquen a un document i com les regles contradictòries s'anul·len o no entre elles.
En aquest apartat tractarem detalladament aquests dos conceptes. Probablement l'herència és un concepte més fàcil de copsar, de manera que començaré amb aquest i després passaré a les particularitats de la cascada.
Nota
Descarregueu-vos el codi font dels exemples d'aquest apartat; el fitxer "inheritance_cascade_code.zip" conté el CSS i HTML acabats, a més de la plantilla inicial d'HTML perquè pugueu anar treballant mentre veieu els exemples.
Descarregueu els exemples a: "inheritance_cascade_code.zip"
Els continguts d'aquest apartat són els següents:
- 28.1. Herència
- 28.1.1. Per a què serveix l'herència
- 28.1.2. Com funciona l'herència
- 28.1.3. Un exemple d'herència
- 28.1.4. Forçar l'herència
- 28.2. Cascada
- 28.2.1. Importància
- 28.2.2. Especificitat
- 28.2.3. Ordre en les fonts
- Resum
- Preguntes de repàs
28.1. Herència
L'herència en CSS és el mecanisme mitjançant el qual determinades propietats d'un element pare es transmeten als seus fills. De fet, s'assembla força a l'herència genètica. Si els progenitors tenen els ulls blaus, els fills segurament també tindran els ulls blaus.
No totes les propietats CSS són heretades perquè algunes d'elles no tindria sentit que ho fossin. Per exemple, els marges no s'hereten perquè és poc probable que un element fill necessiti els mateixos marges que el seu pare. Normalment, el sentit comú dicta quines propietats s'hereten i quines no, però per estar-ne del tot segur, cal consultar cada propietat a la taula de resum de propietats de l'especificació CSS.
28.1.1. Per a què serveix l'herència
Per què el CSS té un mecanisme d'herència? Probablement, la manera més senzilla de respondre aquesta pregunta sigui pensar què passaria si no existís l'herència. S'haurien d'especificar qüestions com ara la família de fonts, la mida de la font i el color del text individualment per a tots i cadascun dels tipus d'element.
Mitjançant l'herència, per exemple, es poden especificar les propietats de les fonts dels elements html
o body
i tota la resta d'elements els heretaran. Es poden especificar els colors de fons i de primer pla d'un element contenidor concret i tots els elements fills d'aquest contenidor heretaran automàticament el color de primer pla. El color de fons no s'hereta, però el valor inicial de background-color
(color de fons) és transparent
, la qual cosa significa que el fons del pare es veurà a través seu. L'efecte és el mateix que si s'heretés el color de fons, però penseu què passaria si s'heretessin les imatges de fons! Tots els fills tindrien la mateixa imatge de fons com a pare i, per tant, tot semblaria un trencaclosques creat per algú amb problemes d'addicció a les drogues, ja que el fons "tornaria a començar des de zero" per a cada element.
28.1.2. Com funciona l'herència
Tots els elements d'un document HTML hereten totes les propietats heretables del seu pare tret de l'element arrel (html
), que no té progenitor.
El fet que les propietats heretades tinguin algun efecte o no depèn d'altres factors, tal com veurem més endavant quan parlem de la cascada. De la mateixa manera que una mare d'ulls blaus pot tenir un fill d'ulls marrons si el pare té els ulls marrons, les propietats heretades a CSS poden anul·lar-se.
28.1.3. Un exemple d'herència
Copieu el següent document HTML en un fitxer nou de l'editor de textos que més us agradi i guardeu-lo com inherit.html.
<!DOCTYPE html > <html lang="ca"> <head> <meta charset=utf-8"> <title>Herència</title> </head> <body> <h1>Títol</h1> <p>Un paràgraf de text.</p> </body> </html>
Si obriu el document en el navegador web, veureu un document força avorrit que es mostra segons l'estil per defecte del vostre navegador.
Creeu un nou fitxer buit amb l'editor de textos, copieu-hi a dins la regla CSS que es mostra a continuació i guardeu el fitxer com
style.css
a la mateixa ubicació que el fitxer HTML.html { font: 75% Verdana,sans-serif; }
Enllaceu el full d'estil al document HTML inserint la línia següent abans del tag
</head>
.<link rel="stylesheet" type="text/css" media="screen" href="styles.css">
Guardeu el fitxer HTML modificat i recarregueu el document en el navegador. La font passarà de ser la predeterminada pel navegador (normalment Times o Times New Roman) a ser Verdana. Si no teniu Verdana instal·lada a l'ordinador, el text es mostrarà amb la font Sans Serif especificada per defecte a la configuració del navegador. A més, el text es veurà un 25% més petit que a la versió sense estil.
La regla de CSS que hem especificat s'aplica únicament a l'element html. No hem especificat cap regla per als títols o els paràgrafs, però ara tot el text es mostra en Verdana al 75% de la mida per defecte. Per què? Per l'herència.
La propietat de font és una propietat abreujada que estableix tota una sèrie de propietats relacionades amb les fonts. Només n'hem especificat dues, la mida de la font i la família de fonts, però aquesta regla equival al següent:
html { font-style: normal; font-variant: normal; font-weight: normal; font-size: 75%; line-height: normal; font-family: Verdana,sans-serif; }
Totes aquestes propietats s'hereten, de manera que l'element body les heretarà de l'element
html
i després les transmetrà als seus fills: el títol i el paràgraf.Però un moment! Hi ha quelcom que no acaba de quedar clar pel que fa a l'herència de la mida de la font, oi? La mida de la font de l'element
html
s'estableix en 75%, però 75% de què? I la mida de la font debody
no hauria de ser el 75% de la mida de la font del seu pare i les mides de les fonts del títol i del paràgraf haurien de ser el 75% de la mida de l'elementbody
?El valor que s'hereta no és el valor especificat, és a dir, el valor que escrivim al full d'estil, sinó una cosa que s'anomena el valor computat. El valor computat és, en el cas de la mida de la font, un valor absolut mesurat en píxels. Per a l'element
html
, que no té un element pare del qual heretar, un percentatge del valor de mida de font s'associa a la mida de font predeterminada del navegador. La majoria de navegadors actuals tenen una mida de font predeterminada de 16 píxels. El 75% de 16 és 12, de manera que el valor computat de la mida de la font de l'elementhtml
serà probablement 12 píxels. Aquest és el valor que heretabody
i que es transmet al títol i al paràgraf.(La mida de la font del títol és més gran perquè el navegador aplica algunes normes d'estil integrades pròpies. Vegeu el tema de la cascada tot seguit.)
Afegiu dos declaracions més a la regla del full d'estil de CSS:
html { font: 75% Verdana,sans-serif; background-color: blue; color: white; }
Guardeu el fitxer CSS i recarregueu el document al navegador.
Ara el fons és de color blau fort i tot el text és blanc. La regla s'aplica a l'element
html
: el document sencer, el fons del qual serà blau. L'elementbody
hereta el color blanc de primer pla i es transmet a tots els fills debody:
en aquest cas el títol i el paràgraf. Aquests no hereten el fons, però el fons s'establirà en el valor per defecte detransparent
, de manera que el resultat visual final serà text blanc sobre fons blau.Afegiu una altra regla nova al full d'estil i guardeu i recarregueu el document.
h1 { font-size: 300%; }
Aquesta regla estableix la mida de la font del títol. El percentatge s'aplica a la mida de font heretada (el 75% de la predeterminada pel navegador, que suposem que és 12 píxels), de manera que la mida del títol serà el 300% de 12 píxels, és a dir: 36 píxels.
28.1.4. Forçar l'herència
Mitjançant la paraula clau inherit
(heretar) pot forçar-se l'herència fins i tot per a propietats que no s'hereten normalment. Tanmateix, s'ha de fer servir amb molta cura, perquè Microsoft Internet Explorer (fins a la versió 7 inclosa) no és compatible amb aquesta paraula clau.
La regla següent fa que tots els paràgrafs heretin totes les propietats de fons dels seus pares:
p {
background: inherit;
}
Amb les propietats abreujades es pot fer servir inherit en comptes dels valors normals. S'ha de fer servir la versió abreujada per a tot o per a res. En la versió no abreujada no es poden especificar alguns valors i fer servir inherit
per a d'altres, perquè els valors poden donar-se en qualsevol ordre i no hi ha manera d'especificar quins valors volem heretar.
Forçar l'herència no és quelcom que calgui fer sovint. Pot ser útil per "desfer" una declaració d'una regla conflictiva o per no haver d'introduir les dades de determinats valors directament al codi font. Un exemple seria el típic menú de navegació:
<ul id="nav">
<li><a href="/">Inici</a></li>
<li><a href="/news/">Notícies</a></li>
<li><a href="/products/">Productes</a></li>
<li><a href="/services/">Serveis</a></li>
<li><a href="/about/">Sobre nosaltres</a></li>
</ul>
Per mostrar aquesta llista d'enllaços com a menú horitzontal, podeu fer servir el CSS següent:
#nav {
background: blue;
color: white;
margin: 0;
padding: 0;
}
#nav li {
display: inline;
margin: 0;
padding: 0 0.5em;
border-right: 1px solid;
}
#nav li a {
color: inherit;
text-decoration: none;
}
En aquest cas, el color de fons de tota la llista s'estableix en blau a la regla de #nav. Així també s'estableix el color de primer pla com a blanc i tots els elements de la llista i tots els enllaços hereten el mateix. La regla dels elements de la llista estableix un límit a la dreta, però no especifica el color del marge, la qual cosa significa que utilitzarà el color de primer pla heretat (el blanc). Per als enllaços, hem fet servir color:inherit
per forçar l'herència i anul·lar el color dels enllaços predeterminat del navegador.
Lògicament, també podria haver especificat el blanc com a color del marge i del text dels enllaços, però el millor del fet de deixar que ho faci l'herència és que, si més endavant decidim canviar els colors, només haurem de fer un canvi en aquest punt.
28.2. Cascada
CSS significa Cascading Style Sheets (fulls d'estil en cascada) i, per tant, no hauria d'estranyar-nos que la cascada sigui un concepte important. És el mecanisme que controla el resultat final quan s'apliquen diverses declaracions CSS contraposades al mateix element.
Hi ha tres conceptes principals que controlen l'ordre en el qual s'apliquen les declaracions de CSS:
Importància
Especificitat
Ordre en les fonts
Tot seguit tractaré amb detall aquests conceptes un per un.
La importància és un dels conceptes més... doncs... importants. Si dues declaracions tenen la mateixa importància, l'especificitat de les regles decidirà quina s'ha d'aplicar. Si les regles tenen la mateixa especificitat, l'ordre de les fonts controla el resultat.
28.2.1. Importància
La importància d'una declaració de CSS depèn d'on s'ha especificat. Les declaracions contraposades s'aplicaran en l'ordre següent; les noves anul·laran les més antigues.
Fulls d'estil d'agent d'usuari.
Declaracions normals en fulls d'estil d'usuari.
Declaracions normals en fulls d'estil d'autor.
Declaracions importants en fulls d'estil d'autor.
Declaracions importants en fulls d'estil d'usuari.
Un full d'estil d'agent d'usuari és el full d'estil integrat del navegador. Cada navegador té les seves pròpies regles sobre com mostrar diversos elements d'HTML si l'usuari o dissenyador de la pàgina no especifica cap estil. Per exemple, els enllaços no visitats acostumen a ser blaus i a estar subratllats.
Un full d'estil d'usuari és un full d'estil que ha especificat l'usuari. No tots els navegadors són compatibles amb els fulls d'estil d'usuari, però poden ser molt pràctics, sobretot per als usuaris amb determinats tipus de minusvalidesa. Per exemple, una persona dislèxica pot tenir un full d'estil d'usuari que especifiqui determinades fonts i colors que li facilitin la lectura.
Opera permet especificar fulls d'estil d'usuari des de Tools (eines) (o des del menú Opera en un Mac) > Preferences... (Preferències) > llengüeta Advanced (Avançat) > Content (Contingut), fent clic al botó Style Options... (Opcions d'estil...) i després assenyalant el full d'estil d'usuari del camp de text My style sheet (El meu full d'estil) dins de la llengüeta Display (Mostrar) d'aquest quadre de diàleg. També es pot especificar si es vol que el full d'estil d'usuari anul·li el full d'estil de l'autor (el dissenyador del web) a la llengüeta Presentation (Presentació)i, fins i tot, que afegeixi un botó a la interfície d'usuari amb el qual poder canviar el full d'estil de l'usuari amb la de l'autor. Per a fer-ho, sortiu totalment del menú Preferences... (Preferències...) fent clic a Acceptar i després feu clic amb el botó dret o, mentre premeu Ctrl, feu clic en algun punt de la interfície del navegador Opera, seleccioneu la vista Customize... (Personalitzar...) > llengüeta Buttons (Botons) > Browser (Navegador) i arrastreu el botó Author Mode (Mode autor) fins a un punt d'alguna de les barres d'eines.
Quan parlem de "full d'estil", normalment fem referència a un full d'estil d'autor. És el full d'estil que ha creat o enllaçat l'autor del document (o, més probablement, el dissenyador del web).
Les declaracions normals són exactament el que el seu nom indica: declaracions normals. El contrari són les declaracions importants, que són les declaracions que van seguides d'una directiva !important
.
Com es pot observar, les declaracions importants d'un full d'estil d'usuari tenen prioritat sobre totes les altres, la qual cosa és lògica. Seguint l'exemple de la persona dislèxica, podria ser que volgués veure tot el text amb Comic Sans MS en cas que li facilités la lectura. Aleshores podria tenir un full d'estil d'usuari amb la regla següent:
* {
font-family: "Comic Sans MS" !important;
}
En aquest cas, independentment d'allò que hagi especificat el dissenyador, i independentment d'allò que s'hagi establert com a família de fonts predeterminada del navegador, tot es mostrarà amb Comic Sans MS.
El mètode de presentació per defecte del navegador només s'aplicarà si les declaracions no queden anul·lades per alguna regla d'un full d'estil d'usuari o un full d'estil d'autor, ja que el full d'estil d'agent d'usuari té la precedència menor.
En realitat, la majoria de dissenyadors no cal que es preocupin gaire de la importància perquè no s'hi pot fer res. No hi ha cap manera de saber si un usuari té un full d'estil d'usuari definit que anul·la el nostre CSS. I si el tenen, segurament sigui per alguna bona raó. Tot i així, va bé saber què és la importància i com pot afectar la presentació dels nostres documents.
28.2.2. Especificitat
L'especificitat és una cosa que cal que tots els autors de CSS comprenguin i tinguin en compte. Pot considerar-se una mesura de com d'específic és el selector d'una regla. Un selector d'especificitat baixa pot donar com a resultat molts elements (com *, que dóna com a resultat tots els elements del document), mentre que un selector amb una especificitat elevada pot ser que només doni com a resultat un únic element d'una pàgina (com ara #nav
, que només dóna com a resultat l'element amb un id
de nav
).
L'especificitat d'un selector pot calcular-se fàcilment, tal com veurem molt aviat. Si dues o més declaracions entren en conflicte per un element determinat i totes les declaracions tenen la mateixa importància, la de la regla amb el selector més específic serà la que "guanyi".
L'especificitat té quatre components; per exemple a, b, c i d. El component "a" és el més distintiu i el "d" el que menys.
El component "a" és força senzill: És 1 per a una declaració en un atribut de
style
, si no, és 0.El component "b" és el nombre de selectors de
id
al selector (els que comencen amb #).El component "c" és el nombre de selectors d'atribut, inclosos els selectors de classe, i pseudoclasses.
El component "d" és el nombre de tipus d'elements i pseudoelements del selector.
Així, després de comptar una mica, podem unir aquests quatre components per aconseguir l'especificitat de qualsevol regla. Les declaracions de CSS en un atribut de
style
no tenen un selector, de manera que la seva especificitat sempre és 1,0,0,0.
Vegem uns quants exemples que ens ajudaran a aclarir com funciona aquest procés.
Selector | a | b | c | d | Especificitat |
---|---|---|---|---|---|
h1 |
0 | 0 | 0 | 1 | 0,0,0,1 |
.foo |
0 | 0 | 1 | 0 | 0,0,1,0 |
#bar |
0 | 1 | 0 | 0 | 0,1,0,0 |
html>head+body ul#nav *.home a:link |
0 | 1 | 2 | 5 | 0,1,2,5 |
Passem ara a comentar l'últim exemple amb més detall. S'obté a=0
perquè és un selector, no una declaració d'un atribut style. Hi ha un selector ID (#nav
), de manera que b=1
. Hi ha un selector d'atributs (.home
) i una pseudoclasse (:link
), per tant, c=2
. Hi ha cinc tipus d'element (html
, head
, body
, ul
i a
), de manera que d=5
. Per tant, l'especificitat final és 0,1,2,5.
Cal mencionar que els combinadors (com >, + i l'espai en blanc) no afecten l'especificitat d'un selector. El selector universal (*) tampoc té informació sobre especificitat.
També cal tenir en compte que hi ha una gran diferència d'especificitat entre un selector id
i un selector d'atributs que per casualitat faci referència a un atribut
id
. Encara que donin com a resultat el mateix element, tenen especificitats molt diferents. L'especificitat de #nav
és 0,1,0,0 i l'especificitat de [id="nav"
]és només 0,0,1,0.
Fixem-nos com funciona això en la pràctica.
Comenceu afegint un altre paràgraf al document HTML.
<body> <h1>Títol</h1> <p>Un paràgraf de text.</p> <p>Un segon paràgraf de text.</p> </body>
Afegiu una regla al full d'estil per fer que el text dels paràgrafs sigui d'un color diferent.
p { color: cyan; }
Guardeu els dos fitxers i recarregueu el document al vostre navegador. S'haurien de veure dos paràgrafs de color cian.
Establiu un
id
al primer paràgraf per a que pugueu trobar-lo fàcilment amb un selector CSS.<body> <h1>Títol</h1> <p id="special" >Un paràgraf de text.</p> <p>Un segon paràgraf de text.</p> </body>
Afegiu una regla per al paràgraf especial al full d'estil.
#special { background-color: red; color: yellow; }
Guardeu els dos fitxers i recarregueu el document al navegador per veure'n el resultat, que és bastant viu.
Vegem les declaracions que s'apliquen als dos paràgrafs.
La primera regla que he afegit estableix color:cyan
per a tots els paràgrafs. La segona regla estableix un color de fons vermell i estableix color:yellow
per a l'únic element que té id
de special
. El primer paràgraf encaixa amb aquestes dues regles: és un paràgraf i té la id
de special
.
El fons vermell no és cap problema perquè només s'ha especificat per a #special
. No obstant això, ambdues regles inclouen una declaració de la propietat de color
, la qual cosa significa que hi ha un conflicte. Ambdues regles tenen la mateixa importància, es tracta de declaracions normals al full d'estil de l'autor, de manera que cal fixar-se en l'especificitat dels dos selectors.
El selector de la primera regla és p
, que té una especificitat de 0,0,0,1 segons les regles anteriorment mencionades, ja que inclou un únic tipus d'element. El selector de la segona regla és #special
, que té una especificitat de 0,1,0,0 perquè està format per un selector de id
. 0,1,0,0 i és molt més específic que 0,0,0,1, de manera que la declaració color:yellow
guanya i s'obté el text groc sobre fons vermell.
28.2.3. Ordre en les fonts
Si dues declaracions afecten el mateix element, tenen la mateixa importància i la mateixa especificitat, la senyal distintiva final és l'ordre en les fonts. La declaració que es veu més endavant als fulls d'estil "guanyarà" a les anteriors.
Si teniu un únic full d'estil extern, les declaracions al final del fitxer anul·laran les que succeeixin abans al fitxer en cas de conflicte. Les declaracions contraposades també poden succeir en diferents fulls d'estil. En aquest cas, l'ordre en què s'enllacen, s'inclouen o s'importen els fulls d'estil determina quina declaració s'aplica, de manera que si es tenen dos fulls d'estil enllaçats en el head
d'un document, l'enllaçat a l'últim anul·larà l'enllaçat al primer. Vegem un exemple pràctic de com funciona això.
Afegiu una regla nova al full d'estil, just al final del fitxer, com per exemple:
p { background-color: yellow; color: black; }
Guardeu i recarregueu la pàgina web. Llavors tindreu dues regles que donen com a resultat tots els paràgrafs. Tenen la mateixa importància i la mateixa especificitat (ja que el selector és el mateix), per tant el mecanisme final per distingir-les serà l'ordre de les fonts.
L'última regla especifica color:black
i que anul·larà color:cyan
de la regla anterior.
Fixeu-vos com aquesta regla nova no afecta en absolut el primer paràgraf. Malgrat que la regla nova apareix en últim lloc, el seu selector té una especificitat més baixa que el de #special
. Això demostra clarament com l'especificitat té prioritat sobre l'ordre de les fonts.
Resum
Herència i cascada són conceptes bàsics que qualsevol dissenyador web ha de comprendre.
L'herència permet declarar propietats en elements de nivell alt i que aquestes propietats es transmetin a tots els elements descendents. Només algunes propietats s'hereten per defecte, però l'herència pot forçar-se mitjançant la paraula clau inherit
.
La cascada soluciona els conflictes quan diverses declaracions afecten un element determinat. Les declaracions importants anul·len les que no ho són tant. Entre declaracions d'igual importància, l'especificitat de la regla controla quina s'aplica. I, si tota la resta és igual, l'ordre de les fonts suposa la distinció definitiva.
Preguntes de repàs
Preguntes que hauríeu de poder respondre:
Es pot heretar la propietat
width
? Penseu-hi abans de contestar (tindria sentit?) i després mireu la resposta correcta a l'especificació CSS.Si afegim
!important
a la declaraciócolor:black
de l'última regla del full d'estil d'exemple, afectarà el color del text del primer paràgraf "especial"?Quin selector és més específic, "
#special
" o "html>head+body>h1+p
"?Quina aparença hauria de tenir un full d'estil d'usuari per a que el nostre document de prova aparegui amb Comic Sans MS negra sobre fons blanc, independentment del full d'estil de l'autor?