Cascada i herència

This translation is incomplete. Please help translate this article from English

L’objectiu d’aquest article és desenvolupar la comprensió d’alguns dels conceptes més fonamentals del CSS (la cascada, l’especificitat i l’herència) que controlen com s’aplica el CSS al HTML i com es resolen els conflictes.

Si bé pot semblar que és menys rellevant i una mica més acadèmic que algunes altres parts del curs, però la seva comprensió t'estalviarà feina més endavant! T'animem a treballar aquesta secció amb cura i comprovar que entens els conceptes abans de continuar endavant.

Prerequisits: Coneixements bàsics d'informàtica, tenir el programari bàsic instal·lat, coneixements bàsics de com treballar amb fitxers i d'HTML (mira Introducció a l'HTML) i una idea de com funciona el CSS (mira Primers passos amb CSS).
Objectiu: Apendre què són la cascada i l'especificitat, i com funciona l'herència en CSS.

Regles conflictives

CSS significa Cascading Style Sheets (Fulles d'estil en cascada), i es molt important entendre la paraula cascada; la manera de comportar-se en cascada és clau per comprendre el CSS.

En algun moment, treballaràs en un projecte i trobaràs que el CSS que creus que s’hauria d’aplicar a un element no funciona. Normalment el problema és que has creat dues regles que podrien aplicar-se al mateix element. La cascada i el concepte d'especificitat, que estan estretament relacionats, són mecanismes que controlen quina regla s'aplica quan hi ha aquest conflicte. La regla que dona estil al teu element pot ser que no sigui la que esperaves, per la qual cosa has d'entendre com funcionen aquests mecanismes.

Aquí també és important el concepte d'herència, que significa que algunes propietats CSS per defecte hereten valors fixats a l'element pare, i d'altres no. Això també pot causar algun comportament que potser no esperes.

Comencem per fer una ullada ràpida als elements claus que tractem i, a continuació, examinarem com interaccionen entre si i amb el CSS. Poden semblar un conjunt de conceptes complicats d’entendre. A mesura que vagis agafant pràctica a l'hora d’escriure CSS, la forma que té de funcionar serà més evident.

La cascada

Fulls d’estil en cascada: a un nivell molt senzill això significa que l’ordre de les regles CSS és important; quan s’apliquen dues regles que tenen la mateixa especificitat, l'última que surt al codi CSS és la que s’utilitzarà.

A l’exemple següent, tenim dues regles que podrien aplicar-se a h1. h1 acaba sent de color blau: aquestes regles tenen un selector idèntic i, per tant, porten la mateixa especificitat, de manera que l’última regla al full d'estil guanya.

 

Especificitat

L’especificitat és la manera com el navegador decideix quina regla s’aplica si diverses regles tenen diferents selectors i poden aplicar-se al mateix element. Bàsicament és una mesura de com d'específica serà la selecció d'un selector:

  • Un selector d’elements és menys específic (seleccionarà tots els elements d’aquest tipus que apareixen a una pàgina) i, per tant, obtindrà una puntuació més baixa.
  • Un selector de classes és més específic: només seleccionarà els elements d'una pàgina que tinguin un valor d'atribut class específic, de manera que obtindrà una puntuació més alta.

Veiem un exemple! A continuació, tornem a tenir dues regles que podrien aplicar-se a h1. El següent h1 acaba sent de color vermell: el selector de classe dona a aquesta regla una especificitat més alta, i per tant s'aplicarà encara que la regla amb el selector d'elements aparegui més avall a la fulla d'estil.

 

Més endavant explicarem la puntuació de l'especificitat.

Herència

En aquest context també s’ha d’entendre l’herència: alguns valors de propietat CSS establerts en els elements pare són heretats pels elements fills i altres no.

Per exemple, si configures un color i un font-family a un element, tots els elements que hi ha al seu interior també es dissenyaran en funció d'aquest color i tipus de lletra, tret que els hi hagis aplicat valors de color i lletra diferents directament.

 

Algunes propietats no s'hereten, per exemple, si estableixes un width del 50% a un element, cap dels seus descendents obtenen una amplada del 50% de l'amplada de l'element pare. Si fos així, seria molt frustrant utilitzar CSS!

Nota: A les pàgines de referència de les propietats CSS de MDN, pots trobar un quadre d'informació tècnica, normalment a la part inferior de la secció d'especificacions, que enumera diversos punts de dades sobre aquesta propietat, inclòs si s'hereta o no. Mira per exemple la secció Especificacions de la propietat del color.

Comprendre el funcionament dels conceptes

Aquests tres conceptes controlen quin CSS s'aplica sobre els elements. A les seccions següents veurem com funcionen conjuntament. De vegades pot semblar una mica complicat, però començaràs a recordar-los a mesura que guanyis més experiència amb CSS, i sempre pots ho buscar si t'oblides dels detalls. Fins i tot als desenvolupadors experimentats els hi costa recordar tots els detalls.

Comprendre l’herència

Començarem per l'herència. A l'exemple següent tenim un element <ul>, amb dos nivells de llistes no ordenades enclavades al seu interior. Li hem proporcionat a l'element <ul> exterior una vora, una àrea de farciment i hem canviat el color de la lletra.

El color s’ha aplicat als fills directes i també als indirectes: els elements fills immediats (<li>) i als que hi ha a la primera llista nidificada. Després hem afegit una classe special a la segona llista nidificada i li hem aplicat un color diferent. Això s'hereta a través dels seus fills.

 

No s'hereten coses com l'amplada (com s'ha esmentat anteriorment), els marges, l'àrea de farciment i les vores. Si els fills de la nostra llista haguessin d’heretar una vora, cada llistra i element de llista obtindria una vora, i probablement no sigui un efecte que volguem.

Quines propietats s'hereten de manera predeterminada i quines no es determina, en gran part, pel sentit comú.

Control de l’herència

El CSS proporciona quatre valors especials de propietat universal per controlar l’herència. Totes les propietats CSS accepten aquests valors.

inherit
Estableix el valor de la propietat aplicat a un element seleccionat perquè sigui igual que el del seu element pare. Efectivament, això «activa l'herència».
initial
Estableix el valor de propietat aplicat a un element seleccionat perquè sigui igual que el valor establert per a aquesta propietat en aquest element al full d'estil predeterminat del navegador. Si el full d’estil predeterminat del navegador no estableix cap valor i la propietat s’hereta de manera natural, el valor de la propietat s’estableix en inherit.
unset
Restableix la propietat al seu valor natural, cosa que significa que si la propietat és heretada naturalment actua com a inherit, en cas contrari actua com a initial.

Nota: També hi ha un valor més recent, revert, que té un suport limitat per part dels navegadors.

Nota: Consulta la secció Origin of CSS declarations in Introducing the CSS Cascade per obtenir més informació sobre cadascuna d'elles i el seu funcionament.

A continuació veurem una llista d’enllaços i explorarem com funcionen els valors universals. L’exemple en directe següent permet jugar amb el CSS i veure què passa si es fan canvis. Jugar amb codi és realment la millor manera d’arribar a conèixer l'HTML i el CSS.

Per exemple:

  1. El segon element de llista té aplicada la classe my-class-1. Estableix el color de l’element <a> anclat al seu interior perquè s'hereti. Si suprimeixes la regla, com canvia el color de l'enllaç?
  2. Comprens per què el tercer i quart enllaç són del color que són? Si no és així, comprova la descripció dels valors anteriors.
  3. Quin dels enllaços canviarà de color si defineixes un nou color per a l'element <a>, per exemple a { color: red; }?

 

Restablir tots els valors de propietat

La propietat CSS abreviada all es pot utilitzar per aplicar un d’aquests valors d’herència a (gairebé) totes les propietats alhora. El seu valor pot ser qualsevol dels valors d'herència (inherit, initial, unset, or revert). És una manera còmoda de desfer els canvis fets als estils de manera que puguis tornar a un punt de partida conegut abans d'introduir canvis nous.

A l’exemple següent tenim dos cites en bloc. La primera té un estil aplicat directament sobre la cita en bloc, mentre que la segona té una classe aplicada a la cita en bloc que estableix el valor de all a unset.

 

Prova d’establir el valor all a alguns dels altres valors disponibles i observa quina és la diferència.

Comprendre la cascada

Ara entenem per què un paràgraf situat a l'estructura del HTML és del mateix color que el CSS aplicat al cos i, a partir de les lliçons introductòries, entenem com canviar el CSS aplicat en qualsevol moment del document, ja sigui assignant CSS a un element o creant una classe. Ara farem una bona ullada a com la cascada defineix quines regles CSS s'apliquen quan hi ha més d'una cosa que pot donar estil a un element.

Hi ha tres factors a considerar, que figuren en un ordre decreixent d'importància. Les anteriors anul·len les posteriors:

  1. Importància
  2. Especificitat
  3. Ordre dins el codi

Les veurem des de baix cap amunt, per veure com els navegadors determinen què s’ha d’aplicar al CSS.

Ordre dins el codi

Ja hem vist com l’ordre dins el codi és important en la cascada. Si tens més d’una regla, amb exactament el mateix pes, guanyarà la que aparegui última al CSS. Pots veure-ho com unes regles, i les que són més properes a l'element sobreescriuen les primeres fins que l'última guanya i estableix el disseny que es dona a l'element.

Especificitat

Un cop entès el fet que l’ordre dins el codi importa, en algun moment et trobaràs amb una situació en què saps que una regla apareix més endavant en el full d’estil, però s’aplica una regla conflictiva anterior. Això es deu al fet que aquesta regla anterior té una especificitat més elevada: és més específica i, per tant, el navegador la tria per donar estil a l'element.

Com hem vist abans en aquesta lliçó, un selector de classes té més pes que un selector d’elements, de manera que les propietats definides a la classe anul·len les aplicades directament a l’element.

Una cosa a destacar és que tot i que estem pensant en els selectors i les regles que s’apliquen a l'element que seleccionen, no es sobreescriu tota la regla, sinó només les propietats iguals.

Aquest comportament ajuda a evitar la repetició dins el CSS. Una pràctica habitual és definir estils genèrics per als elements bàsics, i després crear classes per a aquells que siguin diferents. Per exemple, al full d’estil següent hem definit estils genèrics per a encapçalaments de nivell 2, i després hem creat algunes classes que canvien només algunes propietats i valors. Els valors definits inicialment s'apliquen a tots els encapçalaments, i els valors més específics s'apliquen als encapçalaments on s'ha establer alguna classe.

 

Mirem ara com calcularà l’especificitat el navegador. Ja sabem que un selector d’elements té una especificitat baixa i pot ser sobreescrit per una classe. Essencialment s’atorga un valor en punts a diferents tipus de selectors i, si s’afegeixen, s’obté el pes d’aquest selector concret, que es pot avaluar després d’altres coincidències potencials.

La quantitat d'especificitat que té un seleccionador es mesura amb quatre valors (o components) diferents, que es poden pensar en milers, centenes, desenes i unitats; quatre dígits simples en quatre columnes:

  1. Milers: Suma un punt en aquesta columna si la declaració es troba dins d’un atribut style, també conegut com estils en línia. Aquestes declaracions no tenen selectors, de manera que la seva especificitat és sempre de 1000.
  2. Centenes: Suma un punt en aquesta columna per a cada selector ID que figura al selector global.
  3. Desenes: Suma un punt en aquesta columna per a cada selector de classe, selector d'atributs o pseudoclasse que es troba dins del selector general.
  4. Unitats: Suma un punt en aquesta columna per a cada selector d'elements o pseudoelement que es trobi dins del selector general.

Nota: El selector universal (*), els combinadors (+, >, ~, ' ') i la pseudoclasse de negació (:not) no tenen cap efecte sobre l'especificitat.

La taula següent mostra alguns exemples aïllats per posar-te en situació. Prova d'estudiar aquestes qüestions i assegura't d’entendre per què tenen aquesta especificitat. Encara no hem cobert detalladament els selectors, però pots trobar detalls de cada selector a la pàgina de referència dels selectors de MDN.

Selector Milers Centenes Desenes Unitats Especificitat total
h1 0 0 0 1 0001
h1 + p::first-letter 0 0 0 3 0003
li > a[href*="en-US"] > .inline-warning 0 0 2 2 0022
#identifier 0 1 0 0 0100
Cap selector, amb una regla dins de l’atribut style d'un element 1 0 0 0 1000

Abans de seguir endavant, mirem un exemple en acció.

 

Què està passant? Primer de tot, només ens interessen les set primeres regles d’aquest exemple i, com ja deus haver notat, hem inclòs els seus valors d’especificitat en un comentari abans de cadascuna.

  • Els dos primers selectors competeixen per donar estil al color de fons de l'enllaç: el segon guanya i fa que el color de fons sigui blau perquè té un selector ID addicional a la cadena: la seva especificitat és de 201 contra 101.
  • El tercer i el quart selectors competeixen per donar estil al color del text de l'enllaç: el segon guanya i fa que el text sigui blanc perquè, encara que tingui un selector d'elements menys, el selector que falta es canvia per un selector de classe, que passa de valdre'n un a valdre'n deu. Així doncs, l’especificitat guanyadora és de 113 contra 104.
  • Els selectors 5-7 competeixen per donar estil a la vora de l'enllaç quan es passa el cursor per sobre. El selector sis perd clarament contra el cinc amb una especificitat de 23 davant de 24, i té un selector menys a la cadena. El selector set, però, supera el cinc i el sis: té el mateix nombre de subselectors a la cadena que cinc, però un element ha estat canviat per un selector de classe. Així doncs, l’especificitat guanyadora és 33 davant de 23 i 24.

Nota: Aquest només ha estat un exemple aproximat per facilitar-ne la comprensió. En l'actualitat, cada tipus de selector té el seu propi nivell d'especificitat que no pot ser sobreescrit per selectors amb un nivell d'especificitat inferior. Per exemple, selectors amb la classe milers combinats entre si no podrien sobreescriure les regles d’un selector ID d'unitats.

Una forma més precisa d’avaluar l’especificitat seria puntuar els nivells d’especificitat individualment començant pel més alt i descendint quan sigui necessari. Només quan hi hagi un empat entre puntuacions de selector dins d’un nivell d’especificitat, hauràs d'avaluar el següent nivell; en cas contrari, pots prescindir dels selectors de nivell d’especificitat inferior ja que mai podran sobreescriure els nivells d’especificitat més alts.

!important

Hi ha una peça especial de CSS que podries utilitzar per substituir tots els càlculs anteriors, però has de tenir molta cura a l'hora de fer-la servir: !important. S’utilitza per fer una propietat particular i valorar la cosa més específica, per tant, superen les regles normals de la cascada.

Mira aquest exemple on hi ha dos paràgrafs, un dels quals té un selector ID.

 

Comprova-ho per veure què succeeix: prova d’eliminar algunes de les propietats per veure què passa si et costa entendre-ho:

  1. Veuràs que els valors {cssxref("color")}} i padding de la tercera regla s'han aplicat, però background-color no ho ha fet. Per què? Els tres haurien d’aplicar-se sense cap problema, perquè les regles posteriors a l’ordre font generalment anul·len les regles anteriors.
  2. Tanmateix, les regles anteriors guanyen, perquè els selectors de classe tenen una especificitat més alta que els selectors d’elements.
  3. Els dos elements tenen una class de better, però el segon té un id de winning. Com que les ID tenen una especificitat encara més elevada que les classes (només es pot tenir un element ID per pàgina, però molts elements amb la mateixa classe: els selectors ID són molt específics amb què delimiten), el color de fons vermell i la vora negra d'1 píxel s'han d'aplicar tant al segon element. El primer element té un color de fons gris i cap vora, tal i com especifica la classe.
  4. El segon element si obté un color de fons vermell, però cap vora. Per què? A causa de la declaració !important de la segona regla, incloent-la després de border: none vol dir que aquesta declaració obtindrà el valor de frontera de la regla anterior, tot i que l'ID tingui una especificitat més elevada.

Nota: L'única manera de substituir aquesta declaració !important seria incloure una altra declaració !important a una declaració amb la mateixa especificitat que es trobi més endavant a l'ordre font o una amb una especificitat més alta.

És útil saber que !important existeix perquè sàpigues què és quan el trobis al codi d'algú altre. Tanmateix, recomanem fermament que no l'utilitzis tret que no tinguis alternativa. !important canvia el funcionament habitual de la cascada, de manera que pot fer que els problemes de depuració de CSS siguin molt difícils de solucionar, especialment en un full de càlcul.

Una de les situacions en què potser l'has d'utilitzar és quan treballis en un CMS on no pots editar els mòduls CSS bàsics però vulguis substituir un estil que no es pot substituir de cap altra manera. Però realment, no ho facis servir si ho pots evitar.

L’efecte de la ubicació del CSS

Finalment, també és útil tenir en compte que la importància d’una declaració CSS depèn de quina fulla d’estil s’especifica; és possible que els usuaris estableixin fulls d’estils personalitzats per a anul·lar els estils del desenvolupador. Per exemple, l’usuari pot tenir una deficiència visual i, per tant, vulgui definir la mida de la lletra de totes les pàgines web que visiti al doble de la mida normal per llegir-ho més fàcilment.

En resum

Les declaracions conflictives s’aplicaran en l’ordre següent, on les posteriors sempre reescriuran les anteriors:

  1. Declaracions en fulls d’estil d’agent d’usuari (per exemple, els estils predeterminats del navegador, que s’utilitzen quan no s’estableix cap altre estil).
  2. Declaracions normals en fulls d’estil de l’usuari (estils personalitzats establerts per un usuari).
  3. Declaracions normals en fulls d'estil d'autor (aquests són els estils establerts per nosaltres, els desenvolupadors web).
  4. Declaracions importants en fulls d’estil d’autor.
  5. Declaracions importants als fulls d'estil de l'usuari.

Té sentit que els fulls d’estil dels desenvolupadors web reemplacin els fulls d’estil dels usuaris, de manera que el disseny es pot mantenir tal i com es pretén, però a vegades els usuaris tenen bons motius per anul·lar els estils dels desenvolupadors web, com s’ha esmentat anteriorment, això es pot aconseguir fent servir !important a les seves regles.

Aprenentatge actiu: jugar amb la cascada

En aquest aprenentatge actiu, ens agradaria que experimentessis escrivint una sola regla nova que anul·lés el color i el color de fons que hem aplicat als enllaços per defecte. Pots utilitzar un dels valors especials que vàrem analitzar a la secció Controlling inheritance per escriure una declaració en una nova regla que restablirà el color de fons a blanc, sense utilitzar un valor real de color?

Si comets un error, sempre ho pots restablir amb el botó Reiniciar. Si no ho aconsegueixes, fes una ullada a la solució aquí.

Què segueix?

Si has entès la majoria d’aquest article, ja has començat a familiaritzar-te amb la mecànica fonamental del CSS. A continuació, examinarem els selectors en detall.

Si no has entès totalment la cascada, l'especificitat i l'herència, no et preocupis. Sens dubte, aquesta és la cosa més complicada que hem cobert fins ara, i que a vegades fins i tot els desenvolupadors web professionals ho troben complicat. T'aconsellem que tornis a aquest article algunes vegades mentre avancis en el curs i que hi segueixis pensant.

Torna a aquest punt si comences a trobar problemes estranys amb estils que no s'apliquen com esperaves. Podria ser un problema d'especificitat.

En aquest mòdul

  1. La ascada i l'herència
  2. Selectors CSS
  3. El model de caixa
  4. Fons i vores
  5. El maneig de diferents direccions de text
  6. El contingut que es desborda
  7. Els valors i les unitats
  8. Dimensionar elements en CSS
  9. Imatges, media i els elements de formulari
  10. Donar estil a les taules
  11. Depurar el CSS
  12. Organitzar el teu CSS