.button.button.button.button

Us volia explicar una cosa sobre el CSS i no sabia com titular-ho.

Adrià Fontcuberta
5 min readMay 25, 2017
“Però Adrià, ara amb Flexbox això és molt senzill”. Saps què en fem dels xivatos, al meu barri?

No, avui no parlarem de centrar verticalment. Avui parlarem d’això:

.button.button.button.button funciona

això funciona i és completament vàlid:

.button.button.button.button {
color: red;
}
<div class="button">Holi</div>

El text d’aquest div serà vermell.

I a més:

.button.button.button.button sobreescriuria els estils de .button.button.button

…que a la vegada sobreescriuria els estils de .button.button que a la vegada sobreescriuria els de .button.

El CSS ens agrada.

De quin color apareixerà el text?

.button.button.button.button {
color: red;
}
.button.button.button {
color: yellow;
}
.button.button {
color: green;
}
.button {
color: blue;
}
<div class="button">Holi</div>

Comprova-ho.

“Per què?”, et deus preguntar. Bueno, la resposta pot ser senzilla: com que la classe surt “més cops”, doncs guanya. Vale, la lògica és bona. I si fem això?

div.button {
color: blue;
}
.button.button {
color: green;
}
<div class="button">Holi</div>

Ara qui guanya?

Ho saps! Guanya el verd. El text sortirà en verd. Però… per què?

I aquí?

.button {
color: blue;
}
div {
color: green;
}
<div class="button">Holi</div>

Aquí guanya el blau.

Per què?

Bàsicament, com que podem dir a infinits llocs quin color ha de tenir el text d’un botó, el CSS ha de tenir una manera per saber quin acaba aplicant.

I el selector que guanya no és l’últim que hem escrit.

És el més específic.

El més què?

(╯°□°)╯︵ ┻━┻

El CSS bàsicament agafa tooots els selectors que modifiquen un element i els ordena per especificitat. El selector amb regles més específiques, guanya.

Vale, vale, ja ho he entès. I com es calcula l’especificitat?

Espera, que faig un títol.

Com es calcula l’especificitat?

Ara sí.

L’especificitat és el Sant Greal del CSS. I és més fàcil d’entendre del que sembla. Bàsicament el CSS agrupa el “pes” de cada selector en quatre grups:

Grup A: Compta els estils inline (style=”color:blue”)

Grup B: Compta la quantitat de selectors de ID (#Button)

Grup C: Compta la quantitat de selectors de classe, pseudoclasse o atributs (.button, :hover, [type=”submit”])

Grup D: Compta la quantitat de selectors d’elements o pseudoelements (img, ::after)

Llavors, compara els números de cada grup, i el que sigui més alt, guanya. Tenint en compte que el grup A sempre pesa més que el grup B, que sempre pesa més que el C, que sempre pesa més que el D.

Aviam, un exemple que ho entendrem tots millor. Què és més específic, div.button:hover o bé #Form .button.selected ?

Podríem fer-ho de cap. No és gaire difícil, però algú més intel·ligent que tots nosaltres s’ha currat un Specificity Calculator:

0 1 2 0 és més gran que 0 0 2 1

Veient això, queda clar quin estil sobreescriuria l’altre en cas d’haver-hi conflictes (o sigui, dos selectors que intenten modificar el mateix estil al mateix element). 0 | 1 | 2 | 0 > 0 | 0 | 2 | 1. Un exemple més complicat però prou habitual:

<div class="header">
<h2 class="title">Holi</h2>
</div>

Ens hem passat el CSS!

Oju que el grup A sempre sempre sempre tindrà més pes que el grup B, i el grup B més que el grup C, perquè concatenem les quantitats, no les sumem. O sigui:

<div class="una classe i mes classes fins que arribem a deu" id="lolnope">Holi</div>
0 | 1 | 0 | 0 > 0 | 0 | 10 | 0

He fet una demo extrema aquí: 1000 classes no superen un sol ID:
0 | 1 | 0 | 0 > 0 | 0 | 1000 | 0. Cap quantitat de classes superarà mai un ID.

Vale, però .button.button.button.button…funciona?

Funciona! El CSS es menja que escrivim la mateixa classe dues, tres o les vegades. Ho diu l’spec de CSS:

Repeated occurrances of the same simple selector are allowed and do increase specificity. (W3C Recommendation, Selectors Level 3)

.button.button.button.button // 4 classes: 0 0 4 0
.button.button.button // 3 classes: 0 0 3 0
.button.button // 2 classes: 0 0 2 0
.button // 1 classe: 0 0 1 0

I l’ordre dels selectors no importa?

Clar que importa, animal. Però només quan hi ha dues regles que empaten a màxima especificitat. En aquest cas guanya l’última:

.button.classe { color: red }  // 2 classes: 0 2 0
.button.classe { color: blue } // 2 classes: 0 2 0
div { color: yellow } // 1 element: 0 0 1
<div class="button classe">Holi</div>

El text es pintarà de color blau perquè guanya la regla que està declarada més avall de les que guanyen.

No és meravellós, el CSS?

(╯°□°)╯︵ ┻━┻

Escolta… i el mític !important no es passa tot això pel forro?

Doncs… sí. Bàsicament. El que fa !important és agafar els estils que tenen aquest flag i duplica la taula:

.classe { color: red !important } // 1 classe: 0 0 1 0Com que té important!, el resultat és: 0 0 1 0 0 0 1 0

Aquí, l’!important torna a concatenar els 4 grups, de manera que tooots els selectors que tinguin !important seran sempre, peti qui peti, més específics que els que no. Un img amb !important sobreescriurà un ID.

.button.button.button.button és una ÑAPA

Espero que tothom qui llegeixi aquest article entengui que escriure quatre vegades una classe per augmentar-ne l’especificitat és una ñapa sideral. És tant evident que no volia ni escriure aquest paràgraf, però ja estic comptant les hores perquè algú em digui “eh eh, que ho vas publicar al Medium eh! Això vol dir que ho puc fer servir”.

És un hack com una casa i no ens agrada! Igual que és un hack atacar un ID fent-t’ho com a atribut perquè no sigui tan específic:

Ñapa

És una ñapa… Però oi que mola?

--

--

Adrià Fontcuberta

Words matter – Software product development, Front-end, UX, design, lean, agile and everything in between. https://afontcu.dev