Vývoj efektivity zápisu CSS
CSS má za sebou dlouhou historii. Tušíte, co bylo před příchodem CSS na scénu webového vývoje a co přispívá k těžkopádnému škálování a udržování stylopisů?
V roce 1994 přišel Håkon Wium Lie na to, že je potřeba vytvořit jazyk, který umožní vizuálně upravovat dokumenty na webu. Hlavní myšlenka byla postavena na tom, že je potřeba oddělit obsah od prezentace. A tak se stalo, že se Håkon spolu s dalšími autory podílel na vytvoření první verze CSS, kterou postupem času implementovaly všechny prohlížeče. Po HTML se z CSS stal druhý standardizovaný jazyk pro W3 (World Wide Web). Ale nepředbíhejme. Nejprve se podívejme na to, jak to celé začalo.
Jak je vidět na snímku níže, po vložení stejného HTML se na dvou různých prohlížečích (Netscape a Mosaic) zobrazoval obsah rozdílně. Vývojáři prohlížeče Mosaic se totiž rozhodli přidat před seznam (dnes známý jako unordered list) odsazení seshora. Mysleli si, že to tak bude vypadat lépe. Jenže všichni to vnímali jako chybu a získávali potřebu mít kontrolu nad tím, jak se jejich obsah na webu zobrazí.
V polovině 90. let, kdy se začaly objevovat první webové stránky, bylo odlišení od výchozího nastavení zobrazení v prohlížečích opravdovým oříškem. V době, kdy se kaskádové styly teprve testovaly, byla možnost upravovat podobu zobrazení jedině pomocí HTML atributů. První webové prohlížeče jako ViolaWWW však neumožňovaly upravit vizuální podobu takřka vůbec.
Co bylo před tím, než přišlo CSS?
Postupem času začali autoři webových stránek tvořit první pokusy o to, čemu dnes říkáme webdesign. Častým příkladem webu z 90. let byla stránka Space Jam.
Na tomto webu je dobře vidět, jak se v této éře přistupovalo k barevnému odlišení textů a odkazů a jak se pracovalo s layoutem.
Veškeré barvy byly definovány v těle stránky, kde tvůrci pomocí HTML atributů nastavili základní pravidla pro zobrazení. Konkrétně atributy bgcolor
, text
, link
, vlink
a alink
. Takto definované atributy pak odlišovaly barvy textů, odkazů a pozadí.
<body
bgcolor="#000000"
text="#ff0000"
link="#ff4c4c"
vlink="#ff4c4c"
alink="#ff4c4c"
>
Dalším pěkným příkladem na tomto webu je layout . Ten se ve své době upravoval jen pomocí tabulek a struktura layoutu vznikala zanořováním tabulek do sebe. Tato technika se pak několik dalších let používala pro tvorbu všech layoutů webových dokumentů. Nejprve kruhový layout (příklad webu Space Jam) a následně Holy Grail Layout, který byl trendem ve webdesignu spoustu let.
Tabulková technika se dodnes doporučuje pro tvorbu newsletterů a PDF generovaných pomocí HTML, protože mnoho e-mailových klientů se rozhodlo své systémy neměnit.
Code newsletters like it’s still 1999.
Na tomto příkladu je vidět, jak přišli autoři k výsledku kruhového layoutu, který byl v té době populární. Tím se chtěli společnosti odlišit od konkurence, a proto vznikaly první pokusy o vizuální změny výchozího nastavení.
Umístění obrázků do kruhového layoutu je pak řešeno opět pomocí atributů tabulek — konkrétně pak align
a valign
a taky pomocí HTML tagů <br>
.
<table width=500 border=0>
<tr>
<td colspan=5 align=right valign=top></td>
</tr>
<tr>
<td colspan=2 align=right valign=middle>
<br>
<br>
<br>
<center>
<a href="cmp/pressbox/pressboxframes.html">
<img
src="img/p-pressbox.gif"
height=56
width=131
alt="Press Box Shuttle"
border=0
>
</a>
</center>
</td>
<!-- … -->
</tr>
<!-- … -->
</table>
Tímto způsobem se několik let (v případě progresivních vývojářů, kteří experimentovali s CSS, jen prvních pár let) tvořil webdesign.
Nástup CSS
Kaskádové styly byly v té době revoluční. Eric Meyer — který se spojil s ostatními vývojáři — začal v roce 1998 popisovat, jak je možné implementovat a používat styly. Postupem času se tak CSS dostalo na první webové stránky a začalo se plně využívat pro designování webů. Třeba tímto (pro mnohé z nás mírně odstrašujícím) způsobem:
<STYLE type=”text/css”>
BODY {
font-family: serif;
background-color: silver;
}
H1 {
font: x-large Verdana, sans-serif;
color: olive;
border-bottom: thin black solid;
}
.sidebar UL LI {
list-style-type: none;
margin-left: 0;
margin-right: 0.5em;
}
.sidebar UL LI A {
color: #ffcccc;
}
.body {
background: white;
}
IMG.icon {
border: outset gray 3px;
padding: 0;
}
</STYLE>
Následně pak přicházely další deklarace, vlastnosti nebo hodnoty, a CSS se tak stalo dalším nepostradatelným jazykem pro vývoj webů.
Na začátku to byla velká revoluce. Už nebylo potřeba pro změnu barvy nadpisu přepisovat hodnoty atributů na všech stránkách, ale stačila jedna drobná změna v kaskádových stylech a změny se projevily všude na webu.
Vývojáři začali CSS používat, ale nikdo se nezabýval potřebou styly nějak strukturálně organizovat a udržovat. Psaní CSS bez jakékoli organizace nebo myšlenky pro udržitelnost už nebylo dostačující. Neexistovaly žádné postupy, jak udržovat kaskádové styly a jak se vyrovnat s mnohdy nekonzistentním designem velkých webů (což trvá v některých případech dodnes). A tak začaly vznikat komplikace…
Two CSS properties walk into a bar.
A barstool in a completely different bar falls over.
Problémy s CSS
Jaké komplikace můžou vznikat při psaní CSS? Hlavně pro začátečníky může být psaní stylů oříškem. Na jednu stranu jsou kaskádové styly díky své přímočarosti velmi jednoduché na pochopení, na druhou stranu je dost komplikované styly udržovat, upravovat a strukturovat. Problémů se může objevit mnoho.
Hluboké zanořování selektorů a vysoká specificita
Pojďme si tuto problematiku představit na příkladu. Vývojář se rozhodne v existujícím projektu přidat unordered list, ze kterého chce vytvořit seznam s modrou barvou odkazů a velikostí písma 20 px. Pro výběr použije selektor .seznam
.
HTML vloží na web — hluboko do struktury HTML, kam patří a kde se má zobrazit:
<ul class="seznam">
<li><a href="prvni.html">Odkaz 1</a></li>
<li><a href="druhy.html">Odkaz 2</a></li>
<li><a href="treti.html">Odkaz 3</a></li>
</ul>
… a CSS zapíše následujícím způsobem:
.seznam li a {
font-size: 20px;
color: blue;
}
Oops? Barva odkazů je červená, písmo je velikosti 16 px a navíc tučně. Podívá se do DevTools a zjistí, že je selektor už přetížen jiným selektorem, který brání ve vykreslení správného výsledku:
body #content .page ul li a {
font-size: 16px;
color: red;
font-weight: bold;
}
Jakou má teď vývojář možnost? Nezbývá nic jiného, než zvýšit specificitu nově vytvořeného selektoru, upravit přetěžující selektor a nebo použít !important
. Možností je samozřejmě víc, ale principiálně jde stále o boj se specificitou.
Praxe je v drtivé většině taková, že se do úprav již hotového selektoru málokdo pustí a !important
víme, proč nepoužívat. Proto nezbývá jiná možnost než zvýšit specificitu přidáním třídy seznam
(spolu se zbytkem selektoru) k našemu unordered listu.
body #content .page ul.seznam li a {
font-size: 20px;
color: blue;
}
Vzniká tak nový element, který se nedá nijak dál použít a je odsouzen k tomu, aby zůstal jen tam, kde je. Pokud bude potřeba použití jinde, nezbývá než přidat další kus kódu. Specificita se zkrátka vyplácí držet zkrátka už od prvního řádku kódu.
Výpočet specificity
V CSS se šablony stylů vybírají podle důležitosti a selektory mají podle typu definice různé hodnoty.
Po posouzení důležitosti pravidla mu kaskáda přisuzuje specificitu; pokud se na stejný prvek vztahují dva selektory CSS, vyhrává ten s vyšší specificitou.
Jako vývojáři občas děláme chybu a pokoušíme se cílit na prvek HTML více než jednou. Obvykle také zvyšujeme hodnotu specificity přidáním nebo úpravou selektoru. Krátkodobě to funguje skvěle, ale obvykle se to dříve nebo později vymkne kontrole. A to způsobuje problémy právě se specificitou. Podívejme se ještě na následující příklad, kde je vidět, jak se zvyšuje hodnota specificita selektorů.
Můžete zkusit vybrat prvek navigace v DevTools, abyste viděli, jak jsou ostatní selektory ignorovány.
Závorkové peklo alias Nesting Hell
Vývojářům, kteří psali CSS, chyběla spousta funkcí (podmínky, cykly, ...), které nabízí jiné programovací jazyky. Proto se od roku 2005 objevily na scéně preprocesory jako Sass či LESS, které přispěly k efektivnějšímu kódování. Ruku v ruce však přinášely řadu neduhů, se kterými se museli vývojáři vypořádat – jedním z nich je tzv. Nesting Hell.
Preprocesory (a od prosince 2023 částečně i nativní CSS) umožňují vnořování selektorů, pomocí kterých je možné zapsat několik jeho úrovní na pár řádků a odpadá nutnost zapisovat víceúrovňová pravidla znovu dokola. Často se však nedbá na to, co nám preprocesory přeloží do výsledného CSS a díky funkcím jako @extend vzniká velké množství kódu navíc, které zhoršují rychlost načítání.
Rozluštění takového kódu a jeho následná úprava tak byla v některých případech takřka nemožná. Následující kód vypadá hrozivě, není to však vůbec nic výjimečného a při refaktorování CSS se s něčím takovým setkáme docela často.
.Checkbox--toggle {
padding: $chekcbox-toggle-diameter / 10 0;
.Checkbox {
&-input {
&:checked {
& + .Checkbox-label {
@extend .Checkbox-toggle — active;
}
}
&:not(:checked) {
&:focus {
& + .Checkbox-label {
&::before {
background-color: $checkbox-toggle-active-handle-bg;
}
}
}
& + .Checkbox-label {
background-color: rgba($checkbox-toggle-bg, 0.46);
}
&[disabled], &[readonly] {
& + .Checkbox-label {
@extend .Checkbox-toggle — disabled;
}
}
}
&-label {
@extend .Checkbox-toggle;
}
}
Jak asi bude vypadat výsledný zkompilovaný selektor? Netroufl jsem si zveřejnit výsledek tohoto selektoru, ale z následujícího obrázku si můžete vytvořit představu, jak takové výstupy vypadají.
Takovému zanořování selektorů bychom se měli vyvarovat. Dobrým zvykem je používat zanoření selektorů maximálně do druhé, s výjimkou do třetí úrovně. Kód zůstává dobře čitelným a nezpůsobí nám nikdy nekončící bolesti hlavy.
Zápis je dobře čitelný a vývojář hned pochopí, co se děje, jak může zápis dál rozšiřovat a pracovat s ním. Dobře tuto problematiku popsal Martin Michálek na svém webu Vzhůru dolů.
Kaskáda — pořadí zápisu pravidel a struktura souborů
CSS je zkratka pro Cascading Style Sheets, a proto hraje kaskáda důležitou roli při práci se styly. Musíme dávat pozor na pořadí, ve kterém selektory zapisujeme a to díky mechanismu kaskády. Kaskáda je algoritmus, podle kterého prohlížeč rozhoduje o tom, které styly použije. Rozhoduje, jak jsou pravidla aplikována, v jakém pořadí a co se stane, když dojde ke konfliktu dvou nebo více pravidel.
Kaskáda je jednou z nejvýkonnějších částí CSS, ale může být také velmi frustrující. Je jedním z důvodů, proč jsme všichni v pokušení přidávat !important
do našich stylů. Osobně si myslím, že je to jeden z nejsložitějších algoritmů na pochopení, přesto je základem pro psaní CSS.
Když mluvíme o kaskádě, máme na mysli kombinaci pravidel, které jsou vzájemně propojeny a je důležité chápat jejich návaznost. V zásadě se jedná o tato čtyři pravidla:
- Pořadí a pozice jednotlivých pravidel - Pokud existují konfliktní hodnoty pro vlastnost v šabloně stylů, které odpovídají selektorům stejné specificity (i původu se stejnou prioritou), použije se poslední deklarace v pořadí stylů.
- Specificita pravidel (selektorů) - Algoritmus určuje, který CSS selektor bude použit na základě skóre specifičnosti. Při porovnávání specificity selektorů převažuje deklarace s vyšší specificitou.
- Důležitost pravidel (selektorů) - Některá pravidla CSS mají vyšší váhu než jiná, zejména ta, která používají typ pravidla
!important
. - Původ - Kaskáda zvažuje, odkud CSS pochází. Může se jednat o interní šablony stylů prohlížeče (user-agent), styly zavedené rozšířeními prohlížeče nebo operačním systémem či autorské styly webu.
Podívejte se pozorně na předchozí příklad:
Z předchozího příkladu můžeme vzít následující body:
- Pokud mají selektory dvou deklarací stejnou váhu (specificitu), pak prohlížeč použije tu, která je v kódu definovaná později.
- Na pořadí CSS deklarací záleží.
- Nezáleží na pořadí, v jakém jsou uvedeny třídy v HTML.
!important
přepíše všechny selektory.
Tato extrémní závislost mezi strukturou HTML způsobuje, že kód je obzvláště křehký: i když je čistý, prostá chyba jej může zcela zničit. To je také důvod, proč komunita začala navrhovat best practices, jak se těmto problémům vyhnout. Ale o tom až někdy později…
Shrnutí
CSS má za sebou dlouhý vývoj a díky neustálému vylepšování (na kterém pracují ti nejzkušenější v oboru) se daří rozvíjet jeho funkcionality a možnosti. Drží si tak stabilní místo vedle svých kolegů pro vývoj webových dokumentů a aplikací.
Související odkazy
- Modular CSS: Best practices to improve your coding workflow (Noble Pixels)
- Combining the Powers of SEM and BIO for Improving CSS (Ryan Yu, CSS Tricks, 2018)
- No seriously: Don’t use @extend (Tiffany B. Brown, March 2017)
- Extending In Sass Without Creating A Mess (David Khourshid, Smashing Magazine, 2015)
- Specificity (MDN, 2023)
- The cascade (web.dev, 2021)
Článek původně vyšel na Medium.com. Na návrh autora byl přenesen v upravené podobě na Frontend Garden, kde jej s radostí vítáme. 🍀
Další články od autora:
Sdílejte
Líbí se vám článek? Podpořte jej sdílením!
Komentujte
Chcete k článku něco doplnit? Našli jste chybu? Napište e-mail.