Cesta do nitra tří nejznámějších CSS preprocesorů pokračuje, i když ne tak, jak jsem původně plánoval.

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. Ukázali jsme si, jak je nainstalovat a naťukli téma syntaxe a mixinů. Všechny tři preprocesory nabízejí fundamentálně rozdílný způsob, jak programovat s mixiny. Každý je v tom jinak konzistentní a každý umí být jinak matoucí.

Pro každý preprocesor existuje galerie hotových mixinů, do kterých nahlédněte přinejmenším k posouzení jejich srozumitelnosti. Pro SASS existuje komplexní Compass, LESS má framework Twitter Bootstrap nebo drobné Elements a Stylus NIB.

…tak takhle začínal článek, který jsem rozepsal před rokem a čtvrt a nikdy nedokončil. Přišel jsem totiž k závěru, že všechny tři preprocesory jsou, alespoň zatím, nepoužitelné. Jejich nasazení by představovalo tolik ústupků, že by se vedle nich potenciální výhody dočista ztrácely. Dnes to vysvětlím.

CSS preprocesor není věc, se kterou bych začínal na zelené louce. Nejsem úplný nováček, s kaskádovými styly mám 10letou historii, kdysi mě mocně nakopl Pixy a dnes mám celkem vypilovaný systém, do kterého potřebuji preprocesor zasadit. Jak ten systém vypadá? Podle mého nejde o vůbec nic neobvyklého.

Když se podíváte pod pokličku třeba tohoto blogu, zjistíte, že se ze serveru načítá právě jeden CSS soubor a právě jeden JS, oba minimalizované. Přičemž onen soubor combined.css obsahuje styly pro všechna zařízení, tj. obrazovku, tiskárnu, mobily, retinu atd. Nezkomprimovaný vypadá nějak takto:

@import "http://fonts.googleapis.com/css?family=Open+Sans:400&subset=latin,latin-ext";

@import "libs/reset.css";
@import "libs/classes.css";

@import "libs/fshl.css" screen;
@import "fancybox/jquery.fancybox.css" screen;
@import "layout.css" screen;
@import "homepage.css" screen;

@import "libs/print.css" print;
@import "print.css" print;

Celý stylopis je tedy rozdělený do řady menších jednotek. V adresáři libs se skrývá drobný CSS framework definující základní pravidla, která používám na všech projektech (btw reset.css není prasárnička á la Eric Meyer’s reset, spíš něco takového), dále tu jsou styly použitých komponent a vůbec celého projektu. Většina importů uvádí závislost na médiu, takže se aplikují jen pro tiskárnu či obrazovku.

V samotných souborech rád používám odsazování, které mi zásadně zvyšuje čitelnost:


a {
	padding: 3px;
	margin: 0 -3px;
	text-decoration: none;
}

	a:hover, a:active, a:focus {
		color: white;
		background-color: blue;
	}



article {
	margin: 2em 0;
}

	article hr {
		visibility: visible;
		clear: none;
	}

	article footer {
		margin-top: 2em;
	}

Musím zdůraznit, že tohle všechno je normální CSS 2.0, které správně zobrazí jakýkoliv prohlížeč. Jediná podmínka je, že pravidla @import musí být uvedena na začátku souboru před čímkoliv jiným. Přičemž uvnitř inkludovaných souborů lze klidně vkládat další (to moc nedělám) a nebo uvádět media queries, pomocí kterých doladím podobu pro mobily nebo nasadím obrázky ve vyšším rozlišení pro displeje retina (prohlížeč správně kombinuje media query v souboru s médiem uvedeným u importu).

Celou strukturu by bylo možné sakumprásk nahrát na server a normálně by to fungovalo. Udělal jsem si ale jednoduchou funkci, která všechny ty klauzule @import expanduje do jediného souboru, ten ještě zkomprimuje a teprve poté pošle na server. Má to zásadní vliv na rychlost načítání stránek, obzvlášť, pokud je čtete v metru.

A do tohoto systému jsem chtěl přivést CSS preprocesor, od kterého jsem si sliboval, že samozřejmě převezme úlohu sestavení výsledného stylu, a dovolí mi lépe řešit některé ošidnosti CSS.

Jak jsem byl bláhový!

Aby preprocesor @importované soubory vůbec zpracoval, je třeba jejich příponu změnit z .css na proprietární (tj. .less, .scss, .sass nebo .styl). Jistě, je zcela správné používat proprietární přípony, jen mi o to, že preprocesor si neporadí také s CSS souborem, přičemž stačí jej pouze přejmenovat a hned to jde.

Najednou koukám, že se mi ztratily některé obrázky. Proč? Například jquery.fancybox.css obsahuje definici background-image: url('fancybox_sprite.png'), přičemž oba soubory se nachází v podadresáři fancybox. Když zkombinujeme styly z různých podadresářů do jednoho souboru, pochopitelně musíme transponovat všechny relativní cesty. To dá selský rozum. Chová se tak samozřejmě i prohlížeč, když vyhodnocuje @import, dělá to i zmíněná 15řádková los stupidos funkce v FTP deploymentu, jen preprocesory, ty to neumí a soubor jednoduše zkriplí. Vážně ☹

Hlavně jsem nepřišel na způsob, jak tuhle kulervoucí vadu obejít. Udělat si bordel ve složce a všechny obrázky nahrát do kořenového adresáře? Modifikovat cesty ve stylech? Ve stylech třetích stran? Naprogramovat prepreprocesor? Čím tyhle ústupy preprocesor vyváží?

Jenže tím zoufalství zdaleka nekončí…

CSS preprocesory si neporadily ani s media queries u pravidel @import:

@import "fancybox/jquery.fancybox.css" screen;

Je třeba screen odstranit a celý obsah vkládaného souboru obalit do @media screen { ... } (neplatí pro SASS, ten sice taky nerozumí mediu v pravidle @import, ale zvládá opis @media screen { @import "style.css" }). Krom toho, že fakt nechci modifikovat soubory natož třetích stran, protože to komplikuje budoucí aktualizace, nemusí jít o nikterak triviální úpravu. Zrovna zmíněný fancybox.css obsahuje @media queries pro retinu a otázkou je, jak se s jejich zanořením preprocesor vypořádá. Pohořely na tom všechny.

A to stále není všechno!

Klíčové je, aby preprocesor dokázal schroustat mé existující CSS (jimž jsem byl donucen změnit příponu). Žádné prasárny ve stylech nepoužívám, SASS i LESS se sekly jen na rovnítku =padding: 0 (LESS ležérně chybu ohlásil na docela jiném řádku), což je obdoba legendárního podtržítkového hacku pro IE6 ve verzi pro IE7. Kašlat na IE7, tohle jedno pravidlo jsem smazal a vše fungovalo.

Ne tak v případě Stylusu (a přiznávám, že tomuto nástroji jsem nadržoval). Ten se sesypal na mém oblíbeném odsazovaní. Prohlásil unexpected "indent" a bylo zalíčené. Stačí běžný komentář a Stylus odchází plakat do kouta.

Přátelé, abych mohl nasadit CSS preprocesor, musel bych totálně dokurvit čistou adresářovou strukturu a drasticky modifikovat své styly i styly třetích stran. Abych mohl vychutnat mixínek? Ne, děkuji, to vážně ne 🙂

A to nemluvě o zabugovanosti dvojice LESS a Stylus, dokonce Stylus ani neumí pravidlo @import přehodit na začátek souboru a generuje nevalidní CSS. Smutné. (Prosím, nepište mi, že vy preprocessor používáte a všechno vám funguje, je to stejně hloupé, jako kdyby vás doktor odmítl se zlomeninou nohy s tím, že jeho noha vůbec nebolí.)

O rok a čtvrt později

Tohle se odehrálo před rokem a čtvrt. Hodně dlouhá doba ve vývoji žhavých technologií. Chyby jsem tehdy nahlásil a dnes se podíval, co je u našich tří kamarádů nového.

  • SASS udržuje sassus quo, všechny zmíněné nedostatky i přednosti setrvávají.
  • Stylus? Těžké zklamání, naučil se sice řešit relativní cesty při uvedení parameteru -r, ale žádný bug nebyl vyřešen a autor na něj nemá čas.
  • LESS. Před rokem největší outsider mi dnes vyrobil perfektní CSS. Poradil si se vším. Wow!

LESS mi udělal obrovskou radost! Ano, nepoužil jsem žádné pokročilé funkce a jen se raduji z toho, že rozumí CSS alespoň tak, jako IE6, dokáže vygenerovat při uvedení parametru -ru sloučený soubor se správnými cestami k obrázkům, soubory není třeba přejmenovávat díky @import (less) "file.css" a mohu jej proto neskutečně snadno nasadit i do existujícího projektu a začít využívat všech výhod preprocesorů. Ty léta náročného vývoje nepřišly nazdar!

HAPPY END.