Vyplatí se používat CSS preprocesory? A pokud ano, který zvolit? Pokračuji v rozboru tří nejznámějších konkurentů.
CSS preprocesor je nástroj, který vám ze zdrojového kódu zapsaného ve vlastní syntaxi vygeneruje CSS pro prohlížeč. Mezi nejznámější patří SASS, LESS a Stylus. Mají řešit praktické nedostatky samotného CSS.
V předchozí části jsme si ukázali, jak preprocesory nainstalovat. Dnes se jim podívám na zoubek.
Syntaxe
Ač jednotlivé nástroje používají odlišnou syntax, všechny rozumí klasickému CSS. To je nesmírně důležité! Můžete kopírovat existující CSS fragmenty a budou fungovat. Ačkoliv…
SASS používá dvě různé syntaxe, jedna se nazývá SASS (stejně jako
preprocesor), nepoužívá středníky ani složené závorky {}
a
místo toho odsazuje mezerami či tabulátory:
// SASS
#main
color: blue
font-size: 0.3em
Druhou syntaxí je SCSS, která vypadá jako klasické CSS a měla být i plně kompatibilní (budu ji pro SASS používat v dalších příkladech). Stejnou syntax má i LESS:
// SCSS, LESS a CSS
#main {
color: blue;
font-size: 0.3em;
}
Stylus také rozumí CSS syntaxi, nicméně upozorňuje, že nejde o 100% kompatibilitu, především proto, že hodně bazíruje na odsazování. V jeho syntaxi lze vynechat složené závorky, středníky a dokonce i dvojtečky:
// Stylus
#main
color blue
font-size 0.3em
Ale pozor! Důležité je, že tyto znaky můžeme vynechat. Pokud vám zápis připadá příliš hutný, klidně si dvojtečky doplňte. Nechcete odsazovat? Vražte tam složené závorky. Velmi podobně funguje NEON. V tomto se zásadně liší od úsporné SASS syntaxe, kde vynechání závorek a středníků je povinnost. Což ji činí z praktického hlediska nepoužitelnou a chápu, proč tvůrci o kompatibilitu s CSS usilovali, ale udělali to nešťastně zavedením další, nekompatibilní, ukecané syntaxe SCSS.
Když už se totiž rozhodnu preprocesor používat, ocením, když mi zjednoduší i syntaxi (alespoň nepovinné středníky), což bohužel umí jen Stylus. Jeho syntax je nejpružnější a nejúspornější.
V kontrastu přísnosti LESS a SASS je zajímavé, že všechny tři
preprocesory podporují // řádkové komentáře
.
Když udělám chybu
Pokud uděláte v dokumentu chibu, preprocesory vás na ni upozorní
chybovou hláškou. A v tomto směru se jednotlivé nástroje zásadně
liší. Pokud třeba zapomenu ve výše uvedeném kódu uzavírací
}
, oznámí SASS:
Syntax error: Invalid CSS after "font-size: 0.3em;": expected "}", was "" on line 4 of test.scss
Stylus:
if (err) throw err; ^ ParseError: stdin:4 1| #main { 2| color: blue; 3| font-size: 0.3em; > 4| unexpected "eos"
a LESS:
ParseError: missing closing `}` in test.less:9:17 8 9 unexpected "eos"undefined
Nutno dodat, že LESS měl šťastnější chvilku. Pokud bych zapomněl středník, skončí to u obvyklejšího
ParseError: Syntax Error on line 2 in test.less:2:1 1 #main { 2 color: blue 3 font-size: 0.3em
Výmluvné chybové hlášky jsou pro mě důležité a v tomto směru
s přehledem vede SASS. Ačkoliv se to z ukázky tak nejeví, hodně se
snaží i Stylus. Běžně však špatně spočítá číslo řádku a hlásí
chybu o pár řádků výš, než skutečně je. LESS se nejčastěji zmůže
na nicneříkající Syntax Error on line XY
.
Občas jsem narážel na chyby v samotném preprocesoru. Pokud se mi je podařilo izolovat, snažil jsem se je nahlásit (LESS, Stylus), ale ne vždy to šlo. Zde se nejvíc projevila vyspělost jednotlivých nástrojů. Zatímco nejstarší SASS se mi z rovnováhy nepodařilo vyvést nikdy, druhé dva nástroje obsahují chyb bohužel požehnaně.
Co všechno umí?
Drtivou většinou užitečných vychytávek najdeme u všech tří nástrojů, byť třeba nemusí být uvedeny v dokumentaci. V množství asi vede SASS, ale takto se to hodnotit nedá. Třeba nested properties nepotřebuji, naopak property lookup a generátor data URI ve Stylusu vypadá užitečně. Tedy do chvíle, než zjistíte, že převádí buď všechny obrázky, nebo žádný.
Nechci sepisovat výčet jednotlivých vlastností ani srovnávat jejich zápis, to najdete v dokumentaci nebo ve srovnávacím článku na NetTuts. Zaměřím se místo toho na fundamentální rozdíly a největší z nich se týkají tzv. mixinů.
Mixiny
Mixiny jsou z mého pohledu nejdůležitější vychytávkou preprocesorů, protože mění způsob, jak píšeme HTML kód. Vysvětlím. Asi nejznámější „mixin“ je tzv. clearfix, která se stará o to, aby z bloku nevytékaly plovoucí prvky. Obvykle vypadá nějak takto:
.clearfix:after {
clear: both;
content: ".";
display: block;
height: 0;
visibility: hidden;
font-size: 0;
}
(Poznámka: existují jednodušší i složitější varianty clearfixu.
Kupodivu mně vždycky fungovalo nastavit bloku overflow: auto
a
clearfix jsem nepotřeboval. Ale v tuto chvíli jde jen
o příklad.).
Clearfix pak aktivujeme v HTML:
<div id="content" class="clearfix">
<div style="float: left;">....</div>
...
</div>
Ale to neděláš dobře, Jaromíre. Clearfix by se měl aplikovat na straně
stylů, přímo pro #content
, nikoliv v HTML. Jenže komu by se
chtělo kazit si krásný stylopis kopírováním ošklivého hacku? Mnoho
kodérů raději sáhne do HTML.
S preprocesory však netřeba nic kopírovat a vystačíme si s jedinou
instrukcí. Nejprve si clearfix uložíme jako tzv. mixin a poté ho v definici
#content
zavoláme:
SASS:
// definice mixinu (zkráceno)
@mixin clearfix {
&:after { clear: both; ... }
}
#content {
@include clearfix; // vložení mixinu
}
LESS:
.clearfix() {
&:after { clear: both; ... }
}
#content {
.clearfix;
}
Stylus:
clearfix()
&:after { clear: both; ... }
#content
clearfix()
Zmizí tak nutkání zasahovat do zdrojového kódu. A to je velmi důležité.
Jak vidno, syntaxe SASS je opět nejukecanější. Za zmínku stojí, že LESS umožňuje volat jako mixin i jakoukoliv třídu nebo ID.
Parametrické mixiny
Ještě zajímavější je to ve chvíli, kdy mixinům předáme parametry:
SASS:
@mixin border-radius($arg) {
-webkit-border-radius: $arg;
-moz-border-radius: $arg;
border-radius: $arg;
}
#content {
@include border-radius(2px);
}
LESS:
.border-radius(@arg) {
-webkit-border-radius: @arg;
-moz-border-radius: @arg;
border-radius: @arg;
}
#content {
.border-radius(2px);
}
Stylus:
border-radius(arg)
-webkit-border-radius: arg
-moz-border-radius: arg
border-radius: arg
#content
border-radius(2px)
Ve Stylusu můžeme použít i zapis s dvojtečkou:
#content
border-radius: 2px
Což je velmi zajímavé! Když totiž později vendor prefix odstraníme, nebo když naopak zjistíme, že určité vlastnosti potřebujeme vendorovou variantu dodat, nemusíme změnit ani čárku v samotném stylu. Wow.
Jenže… co když mixin zavoláme s více parametry? Například uvedeme
border-radius: 2px 3px
. Překvapivě Stylus bude 3px
v tichosti ignorovat. Proč tomu tak je?
V CSS existují dva způsoby, jak uvést více argumentů, lišící se v oddělovači:
- oddělené mezerama:
border: 1px solid black
- oddělené čárkama:
rgb(10, 20, 30)
Totéž se rozlišuje i v preprocesorech. Ve Stylusu platí, že volání
mixinu border-radius: 2px 3px
je ekvivalentní k
border-radius(2px, 3px)
(a dává mi to smysl), obojí představuje
předávní dvou argumentů. Naopak border-radius(2px 3px)
bez
čárky předává argument jeden. Náš mixin očekává pouze jeden parametr a
druhý tiše bez jakéhokoliv varování zahodil. Oprava spočívá v použití
užitečného klíčového slova arguments
namísto předaného
argumentu arg
.
SASS a LESS naopak předání více argumentů, než je mixinem očekáváno,
vnímají jako fatální chybu. V případě SASS to v důsledku vede
k podivným blokům $shadow-1, …, $shadow-10 patrným
v galerii Compass, zatímco LESS se s problémem snaží vypořádat
konstrukcí when()
. Nic z toho mi nepřipadá ideální.
Komentáře
Sniper #1
Mozna jsem hnidopich, ale v sekci kdyz udelate chybu v prvni vete „Pokud uděláte v dokumentu chibu, preprocesory…“ to mekke i je zamer nebo chyba? Jinak clanek suprovej.
zetcha #2
Pokud uděláte v dokumentu chibu ← a tu jsme udělali 🙂
zetcha #3
Sniper byl rychlejší. 🙂
Trta #4
Ja naopak považuju nested properties za klíčovou vlastnost css preprocesorů, která spolu s mixins pomáhá udržet ve stylopisech pořádek. Mohl bys prosím naťuknout, z jakého důvodu ti nested p. nepřišly užitečné?
Jan Panschab #5
No jo, ale jak se vypořádat s Intellisense (našeptávání/doplňování) a syntax highlighting v IDE? Bez Intellisense si už psaní stylů nedokážu představit. Např. v Netbeans přestává Intellisense fungovat jakmile se zbortí syntaxe.
David Grudl #6
#4 Trto, nested properties != nested rules
trta #7
#6 Davide Grudle, Ahso! Jdu se posypat žhavým popelem a polít lávou :)
Jakub Vrána #8
Já už začínám tušit, jaký bude poslední díl tohoto seriálu: Napsal jsem vlastní preprocesor CSS, protože ostatní –stály za starou bačkoru– mi nevyhovovaly.
arron #9
Ono v zásadě takový NEON by se nejspíš dal do CSS celkem slušně transformovat…spolu s některými features z Nette (%variable%) by to mohlo celkem jednoduše umět to zásadní.
gagga #10
K čemu je to tedy dobré? :) Když napíšu kvalitní stylopis tak prostě nepotřebuji nic zkracovat apod. A dokonce ani nepotřebuji užívat hacky apod.
HonzaMac #11
Prosím o uveřejnění posledního dílu. Napjatě čekám co z toho bude …
Samuel #12
Ešte stojí za to kuknúť na compass, založené na sass, ale vie to trochu viac vecí, napr. sprites, generovanie url, mnoho predkódených mixinov.
ic #13
Ještě mě tak napadlo… podporuje některý z nich media queries (z CSS3)? Tedy podle pravidla Mobile First nabízí media queries možnost rozdělit si styly do několika souborů a ty se načítají jen po splnění určité podmínky (třeba šířka zobrazené plochy). Príma je že ostatní css soubory pro desktopy se ani nenačítají a tak šetří mobilní data. Nevýhoda je právě ten zápis do více souborů (často stejných věcí do více soubrů) a to, že less (ostatní neznám) v tomhle vůbec nepomůže. Je dost možné, že to někdy přijde jako nová funkce, ale dost by se mi hodila už teď.
David Grudl #14
#13 ici, podporuje to pouze SASS.
David Grudl #15
Doplnil jsem článek o závěrečné tři odstavce, aby byl problém s předáváním argumentů uzavřený.
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.