Kaskáda a dědičnost v CSS
Kaskáda
 Tisk

Kaskáda

Na některých ukázkách v předchozích studijních článcích jste si mohli všimnout, že v jedné tabulce kaskádových stylů je pro jeden prvek definováno více pravidel. Jednalo se o pravidla, z nichž každé definovalo jinou vlastnost prvku. Například pravidlo h1, h2, p { background-color: #bfbaff } nastavilo nadpisům a odstavcům stejnou barvu pozadí. Další pravidlo p { text-align: justify } zarovnalo text odstavců do bloku. Odstavce v dokumentu se pak formátovaly podle obou těchto pravidel. Již to byl první náznak kaskády. Co by se ale stalo, kdybychom ve dvou pravidlech definovali stejnou vlastnost? Jak by se dokument formátoval?

Specifičnost selektorů

V takových případech má přednost pravidlo, které pro daný prvek uvádí přesnější (specifičtější) selektor. V CSS má každý dílčí selektor (typu, třídy, ID) určitou prioritu. Součet těchto priorit pak určí celkovou specifičnost selektoru.

Priority selektorů jsou následující:

1 = selektor typu.

10 = selektor třídy.

100 = selektor ID.


Máme-li například pravidlo se selektorem h2.mojetrida, pak specifičnost tohoto selektoru je 11. Tzn. priorita 1 selektoru typu (h2) + priorita 10 selektoru třídy (.mojetrida).

Stejným způsobem se sčítají i selektory tříd. Např. specifičnost selektoru p#mojeid je 101. Tj. součet priority 1 selektoru typu (p) a priority 100 selektoru ID (#mojeid).

Sčítají se rovněž i priority selektorů zapsaných v kontextu. Selektor h1 em bude mít tedy specifičnost 2. Priorita 1 selektoru typu (h1) + priorita 1 druhého selektoru typu (em).

Kdy se ale priority selektorů nesčítají, je při sdružování selektorů. Sdružené selektory mají totiž stejný význam, jako jejich dílčí selektory. Např. selektor h1, h2, p má naprosto stejný význam jako tři samostatné selektory (selektor h1, selektor h2, selektor p). Proto je specifičnost takového selektoru rovna 1.

I specifičnost složitějších selektorů se dá velmi snadno spočítat. Stačí si je opět rozložit na dílčí selektory a sečíst jejich priority. Např. selektor div#hlavicka img.logo bude mít specifičnost 112. Jedná se o součet priority 1 selektoru typu (div), priority 100 selektoru ID (#hlavicka), priority 1 dalšího selektoru typu (img) a priority 10 selektoru třídy (.logo).

V ukázce v XHTML kódu několik prvků em. Pravidlo h2 em { border-bottom: dashed } říká, že prvky em, které jsou uvnitř nadpisů h2 budou mít dolní rámeček čárkovaný. Druhé pravidlo em { border-bottom: dotted } říká, že všechny prvky em budou mít dolní rámeček tečkovaný. Zatímco první pravidlo má specifičnost 2 (priorita 1 selektoru h2 + priorita 1 selektoru em), specifičnost druhého pravidla je 1 (priorita 1 selektoru em). A protože má první pravidlo vyšší specifičnost, než druhé, bude pro prvky em uvnitř nadpisů h2 platit právě toto pravidlo.

Pro úplnost je ještě třeba zmínit, že existují další dvě priority, které tak trochu vybočují.

Jsou to:

0 = univerzální selektor.

1000 = definice uvedená v atributu style.


Před univerzálním selektorem mají tedy přednos všechny ostatní. Maximální prioritu má naopak definice, která je uvedená v atributu style, přímo u konkrétního prvku v XHTML kódu. Jde tedy o případ, kdy máme v hlavičce XHTML kódu vloženo propojení s externím souborem (např. <link rel="stylesheet" type="text/css" href="ukazka.css" />) a zároveň je u některého z prvků uveden atribut style (např. <h1 style="color: red" >Červený nadpis</h1>). V praxi se toho většinou využívá ve spojení s jazykem JavaScript. S pomocí tohoto jazyka je možné v závislosti na činnosti uživatele měnit definice konkrétních prvků (tzn. měnit definice v jejich atributech style). Zde se ale touto problematikou zabývat nebudeme a zůstaneme u samotných externích souborů.

Platnost pozdější definice

V případě, že mají selektory shodnou specifičnost, platí později definovaná vlastnost. Toho můžeme s výhodou využít, chceme-li mít například jednotný vzhled nadpisů, ale jeden druh nadpisů by se měl lišit.

Viz. ukázka .

Nejprve zápisem selektorů v kontextu (h1, h2, h3) definujeme styl, barvu a podtržení všech nadpisů. Následně pomocí selektoru h3 podtržení zrušíme. Všechny tři selektory v kontextu mají prioritu 1 a selektor h3 má rovněž prioritu 1. Pro podtržení nadpisu h3 tedy bude platit jeho pozdější definice text-decoration: none.

Nebýt kaskády, museli bychom pro nadpis h3 definovat styl i barvu znovu. Kdybychom se v budoucnu rozhodli změnit například barvu všech nadpisů, museli bychom to provést v obou pravidlech. Pro dvě pravidla to není výhoda nijak markantní, avšak ve složitějších tabulkách stylů již kaskádu velmi oceníme.

Pozdější definice v rámci pravidla

Platnost později definované vlastnosti můžeme využít i v rámci jednoho pravidla. Například chceme-li definovat rámeček jen třem stranám prvku. S pomocí kaskády nám k tomu stačí pouze dvě definice. V první definujeme pomocí sdružené vlastnosti border všechny vlastnosti rámečku a ve druhé pak jednu stranu rámečku zrušíme.

Můžete to vidět v ukázce .

Nebýt kaskády, museli bychom použít tři samostatné definice border-top: 3px solid red;, border-right: 3px solid red; a border-left: 3px solid red;. Kdybychom se v budoucnu rozhodli změnit některou vlastnost rámečku (šířku, styl, či barvu), museli bychom to provést ve všech třech definicích.

Kombinace s dědičností

Kaskádu je samozřejmě možné (a také vhodné) kombinovat s dědičností. Definováním vlastností rodičovským prvkům se některé (dědičné) vlastnosti přenesou i na jejich potomky (viz. studijní článek Dědičnost). Díky kaskádě můžeme navíc tyto vlastnosti změnit.

Ukážeme si to na příkladu, kdy chceme mít v celém dokumentu stejný typ písma, jen odstavce by se měly lišit.

Viz. ukázka .

Pravidlo body { font-family: sans-serif } nastaví všem potomkům prvku body (celému dokumentu) bezpatkové písmo. Následně využijeme kaskády (platnost pozdější definice) a pravidlem p { font-family: serif } definujeme odstavcům písmo patkové.