Sass Guidelines

Umíněný průvodce pro psaní rozumného, udržovatelného a škálovatelného Sass.

You are viewing the Czech translation by Honza Bittner of the original Sass Guidelines from Hugo Giraudel.

This version is exclusively maintained by contributors without the review of the main author, therefore might not be completely up-to-date, especially since it is currently in version 1.1 while the English version is in version 1.3.

Otevřít nastavení

O autorovi

Jmenuji se Hugo Giraudel, jsem front-end vývojář z Francie a žiji v Berlíně. Sass píšu přes dva roky a jsem autor Sass projektů jako SassDoc a Sass-Compatibility. Také jsem napsal knihu o CSS (ve francoužštině) s názvem CSS3 Pratique du Design Web.

Napsal jsem také několik Sass knihoven, nejčastěji pro mé vlastní účely: SassyJSON, SassyLists, SassySort, SassyCast, SassyMatrix, SassyBitwise, SassyIteratorsGenerators, SassyLogger, SassyStrings a SassyGradients.

Přispivání

Sass Guidelines je můj volnočasový projekt. Snad ani není potřeba dodávat, že udržovat všechno aktuální, zdokumentované a relevantní dá docela dost práce. Samozřejmě už jen toho, že je pro vás tento manuál přínosem, si velice cením!

Pokud byste rádi chtěli přispět, budu rád za jakýkoliv tweet, či jinou metodu šíření, ale i třeba za upozornění na chybu otevřením issue nebo pull-requestu na GitHub repositáři.

V neposlední řadě, než začneme: pokud se vám tento dokument líbil, nebo pro vás byl užitečný, zvažte, prosím, jeho podporu!

O Sassu

Takto je Sass popisován v jeho dokumentaci:

Sass je CSS rozšíření, které dodává sílu a eleganci základnímu jazyku.

Hlavním cílem Sassu je opravit nedostatky v CSS. CSS, jak všichni víme, není nejlepší jazyk světa [nutná citace]. I když je velmi jednoduchý na naučení, mžiknutím oka se může stát chaotický, zejména pokud jde o velké projekty.

A to je přesně ten moment, kdy se hodí mít po ruce Sass, jako meta-jazyk, který vylepšuje CSS syntaxi za pomoci různých funkcí a šikovných nástrojů, a to vše konzervativně k jazyku CSS.

Nejde ale o to, proměnit CSS do plnohodnotného programovacího jazyka, jelikož Sass chce jenom pomoci tam, kde CSS selhává. A právě proto není začít se Sassem o nic těžšího, než-li se začít učit CSS: jednoduše to přidává několik funkcí navíc.

Jak již bylo řečeno, existuje mnoho způsobů využití těchto funkcí. Některé jsou dobré, některé špatné a některé poměrně neobvyklé. Tenhle manuál si klade za cíl nastínit vám konzistentní zdokumentovaný přístup pro psaní Sassu.

Další četba

Ruby Sass nebo LibSass

První commit Sassu se datuje na konec roku 2006, tedy skoro před 8 lety. Netřeba snad ani dodávat, že od té doby uplynula dlouhá doba. Při počátečním vývoji v Ruby se tu a tam objevil nějaký ten port. Nejúspěšnější z nich, LibSass (napsaný v C/C++) je nyní blízko k plné kompatibilitě s původní Ruby verzí.

V roce 2014 se Ruby Sass a LibSass týmy se rozhodly počkat a sjednotit obě verze před dalším postupem. Od té doby LibSass aktivně uvolňuje verze kompatibilní s jeho starším bratrem. Poslední zbývající nesrovnalosti jsem osobně zaznamenal ve svém projektu Sass-Compatibility. Pokud víte o nějakém rozdílu mezi verzemi, který v seznamu není uvedený, budu vám vděčný za otevření příslušné issue.

Vraťme se zpět k volbě kompilátoru. Ono to vlastně záleží na vašem projektu. Pokud je založen na Ruby on Rails, je lepší použít Ruby Sass, který se na takovýto případ perfektně hodí. Také mějte na paměti, že Ruby Sass bude vždy referenční implementací a bude vždy udávat směr funkcí LibSassu. Na projektech, které Ruby nevyužívají, bude použití LibSassu pravděpodobně lepší nápad, jelikož je pravděpodobně už je wrapper pro daný jazyk vytvořen. Takže pokud chcete použít například Node.js, node-sass je jasná volba.

Další četba

Sass nebo SCSS

Ohledně sémantiky jména Sass je hodně nejasností, a to z dobrého důvodu: Sass označuje jak preprocessor, tak i jeho vlastní syntaxi. To není moc příhodné, co?

No, Sass zpočátku popsal syntaxi, jejímž charakteristickým rysem bylo založení na odsazení. Brzy poté se vývojáři Sass rozhodli uzavřít propast mezi Sassem a CSS poskytnutím CSS-friendly syntaxe nazývané SCSS podle Sassy CSS. Jejím motem je: pokud to je validní CSS, je to validní SCSS.

Od té doby je Sass (myšleno preprocesor) poskytován ve dvou rozdílných syntaxích: Sass (bez kapitálek, prosím), také známou jako odsazovaná syntaxe, a SCSS. Kterou z nich budete používat je v podstatě jen a jen na vás, jelikož obě jsou striktně ekvivalentní co se funkcí týče. Je to jen otázka osobního vkusu.

Na mezery citlivá syntaxe Sass spoléhá na odsazení, zbavení se závorek, středníků a dalších interpunkčních symbolů, což vede ke štíhlejší a kratší syntaxi. Oproti tomu SCSS je jednoduší na naučení, jelikož je to spíše něco málo navíc oproti CSS.

Já osobně preferuji SCSS nad Sass, protože je blíže k CSS a je přátelštější k většině vývojářů. Proto je také SCSS výchozí syntaxí v tomto manuálu. Můžete přepnout na Sass odsazenou syntaxi v .

Další četba

Další preprocesory

Sass je preprocesor jako každý jiný. Jeho největší soupeř je LESS. Preprocesor založený na Node.js a který se stal poměrně populárním díky proslulému CSS frameworku Bootstrap, který jej využívá. Je tu také Stylus, což je tak trochu hloupá neomezená verze LESS, kde můžete dělat v podstatě co jen chcete, protože skoro dělá z CSS programovací jazyk.

Proč zvolit Sass nad LESS nebo jiným preprocesorem? je dnes stále hojně pokládaná otázka. Ne tak dávno jsme doporučovali Sass pro projekty založené na Ruby, protože to byl první vytvořený v Ruby a dobře se používal s Ruby on Rails. Nyní, když LibSass skoro dohnal originální Sass to již není až tak relevantní rada.

To co zbožňuji na Sassu je jeho konzervativní přístup k CSS. Sass je navrhnut na základě silných zásad: mnoho z designového přístupu přichází čistě z víry klíčového týmu, že a) přidávání fuknce navíc má komplexní cenu, která musí být odůvodněna užitečností a b) by mělo být jasné co daný blok stylů dělá pouze při pohledu z tohoto bloku. Sass také klade mnohem větší důraz na detaily než ostatní preprocesory. Pokud je mi známo, klíčoví designéři se hluboce starají o podporu každého koutového případu CSS kompatibility a starají se o to, aby bylo každé obecné chování konzistentní.

Jinými slovy, Sass není preprocesor zaměřen na hloupoučké rádoby programátory, jako mě, přidáním mimořádné funkce na vrcholu jazyka, který není určen na podporu logických případů použití. Je to software zaměřený na řešení aktuálních problémů a pomoci poskytnout užitečné funkce pro CSS kde CSS zaostává.

Preprocesory stranou, měli bychom také zmínit postprocesory, které obdržely v několika posledních měsících významné boom. A to především díky PostCSS a cssnext. Postprocesory jsou do značné míry rovnocenné k preprocesorům až na to, že neposkytují nic jiného než CSS syntaxi zítřka.

Můžete je brát jako polyfill pro nepodporované CSS funkce. Například kdybyste psali proměnné tak, jak je popsáno v CSS specifikaci, poté zkompilovali své styly pouze postprocessorem, abyste našli každou proměnnou a ta byla nahrazena její hodnotou, jako by to udělal Sass.

Nápad za postprocesory je ten, že jednou budou prohlížeče podporovat nové funkce (například CSS proměnné), postprocesory je nezkompilují, nechají je být a nechají prohlížeče ať se starají.

Zatímco poskytování zítřejší syntaxe už dnes je opravdu ušlechtilý nápad, musím říci, že pořád preferuji používání Sassu pro většinu věcí. Každopádně jsou tu některé případy, kde věřím, že je použití postprocesorů více vhodné, než-li Sass a tak podobně, například CSS prefixování, ale k tomu se vrátíme.

Další četba

Úvod

Proč mít příručku

Příručka není jenom bezvýznamný dokument na bezduché přečtení, nebo představení ideálního stavu pro váš kód. Je to klíčový dokument projektu, který popisuje, jak a proč psát kód. Pro malé projekty se může zdát spíše jako zbytečnost, ale opravdu dost pomáhá udržovat codebase čistou a jednoduše upravitelnou.

Netřeba ani říkat, že čím více vývojářů je zapojeno v projektu, tím více je manuál pro psaní kódu dost potřebný. Stejně tak čím větší je projekt, tím více je manuál potřeba.

Důležitost dobře uvádí Harry Roberts v jeho CSS Guidelines:

Příručka pro psaní kódu (poznámka, nikoli ve vizuálním stylu) je hodnotným nástrojem pro týmy, které:

  • budou budovat a udržovat produkty přiměřenou dobu;
  • mít vývojáře různých schopností a specializací;
  • mít několik vývojářů pracujících na produktu v jakýkoli daný čas;
  • přijímat pravidelně nové zaměstnance;
  • mít několik codebases, do kterých vývojáři mohou zasahovat zřídkakdy.

Podmínky odpovědnosti

Zaprvé: toto není CSS příručka. Tento dokument nebude probírat jmenné konvence pro CSS třídy, modulárních vzorů a otázku problematiky ID v CSS. Tato příručka se zabývá pouze otázkami spojenými se Sass.

Tato příručka je také mojí vlastní a proto je velmi tvrdohlavá. Berte to jako sbírku metodik a rad, které jsem vykoumal v průběhu let. Díky tomu vás mohu také nasměřovat na užitečnou hrstku zdrojů, takže se určitě dívejte na další četbu.

Samozřejmě to není jediná možnost jak dělat věci a hodně může záležet na vašem projektu. Klidně si vyberte a upravte si vše podle vašich potřeb. Jak říkám, záleží na vkusu.

Klíčové principy

Na závěr toho všeho, pokud tu je jediná věc, kterou bych vám rád předal z celé této příručky, je to právě to, že Sass by měl zůstat jednoduchý jak jen to je možné.

Díky mým pošetilým experimentům jako bitový operátor, iterátory a generátory a JSON parser v Sasu, jsme si všichni vědomi, co se dá s takovýmto preprocesorem dělat.

Zatímco je CSS jednoduchý jazyk, Sass, kterým se má psát CSS, by neměl být o nic moc složitější než obyčejné CSS.Hlavní roli zde hraje princip KISS (Keep It Simple Stupid), který může mít v některých případech dokonce přednost před principem DRY (Don’t Repeat Yourself).

Někdy se je lepší trochu opakovat tak, aby se kód dobře upravoval, spíše než vybudovat těžký, nemotorný a zbytečně složitý systém, který se nebude dát udržovat, kvůli jeho komplexnosti.

Stejně tak, a znovu budu citovat Harryho Robertse, pragmatismus přebíjí dokonalost. V nějakém momentu se pravděpodobně nachytáte, když budete dělat něco, co se příčí pravidlům. Pokud to dává smysl a pokud to zní dobře, dělejte to. Kodex je jen prostředkem, nikoli cílem.

Další četba

Syntaxe & formátování

Pokud byste se mě zeptali, co je první věc, kterou by každá příručka měla obsahovat, bylo by to jak má kód vypadat.

Když se několik vývojářů zapojí do psaní CSS ve stejném projektu, je jen otázkou času, než si jeden z nich začne dělat věci po svém. Manuály pro kód, které podporují konzistenci nejen že tomuto zabraňují, ale také pomáhají pokud jde o čtení a aktualizaci kódu.

Tady je zhruba to, co chceme (beze studu inspirováno CSS Guidelines):

  • dvě (2) mezery odsazení, žádné tabulátory;
  • ideálně, 80 znaků na řádek;
  • správně psané víceřádkové CSS pravidla;
  • smysluplné použití mezer.
// Yep
.foo {
  display: block;
  overflow: hidden;
  padding: 0 1em;
}

// Nope
.foo {
    display: block; overflow: hidden;

    padding: 0 1em;
}
// Since Sass indented-syntax forces those coding standards
// There is no wrong way of proceeding
.foo
  display: block
  overflow: hidden
  padding: 0 1em

V této části nebudeme řešit organizaci souboru. Je to předmětem jiné sekce.

Textové řetězce

Věřte nebo ne, řetězce hrají docela důležitou roli jak v CSS, tak i Sass ekosystémech. Většina CSS hodnod jsou buď délky nebo řetězce (většinou bez uvozovek), takže je docela zásadní držet se nějakého manuálu, pro vypořádávání se s řetězci v Sass.

Kódování

Aby se zabránilo možným problémům s kódováním znaků, je vysoce doporučeno nastavit kódování UTF-8 v hlavním souboru se styly použitím @charset direktivy. Ujistěte se, že je kódování nastaveno hned na prvním místě ve stylech a není před ním žádný znak.

@charset 'utf-8';
@charset 'utf-8'

Uvozovky

CSS nevyžaduje, aby byly řetězce obaleny uvozovkami, a to ani pokud obsahují mezery. Vezměte si například font-family názvy: CSS parseru nezáleží, jestli je zabalíte do uvozovek.

A právě proto ani Sass nevyžaduje, aby byly řetězce zabaleny uvozovkami. A ještě lépe (a naštěstí, což určitě poznáte), řetězec s uvozovkami je striktně rovnocený k dvojčeti bez uvozovek (tedy například 'abc' je striktně rovnocenný s abc).

Jak již bylo řečeno, jazyky, které nevyžadují, aby byly řetězce obaleny uvozovkami jsou jasnou menšinou a proto by měly být řetězce v Sassu vždy zabaleny v jednoduchých uvozovkách (') (jednoduché uvozovky bývají snadnější na napsaní než-li dvojité na qwerty klávesnicích). Kromě souladu s ostatními jazyky, včetně CSS bratrance JavaScriptu, je několik důvodů pro tuto volbu:

  • jména barev jsou považovány za barvy, pokud jsou bez uvozovek, což může vést k vážným problémům;
  • většina zvýrazňovačů syntaxe bude řetězce bez uvozovek považovat za chybu;
  • napomáhá obecné čitelnosti;
  • není žádný důvod proč řetězce neobalovat uvozovkami.
// Yep
$direction: 'left';

// Nope
$direction: left;
// Yep
$direction: 'left'

// Nope
$direction: left

Textové řetězce jako CSS hodnoty

Specifické CSS hodnoty jako initial nebo sans-serif vyžadují, aby nebyly v uvozovkách. Deklarace jako font-family: 'sans-serif' tiše selže, protože CSS očekává identifikátor, ne řetězec s uvozovkami. Z toho důvodu nepoužíváme uvozovky na tyto hodnoty.

// Yep
$font-type: sans-serif;

// Nope
$font-type: 'sans-serif';

// Okay I guess
$font-type: unquote('sans-serif');
// Yep
$font-type: sans-serif

// Nope
$font-type: 'sans-serif'

// Okay I guess
$font-type: unquote('sans-serif')

Proto můžeme rozlišovat mezi řetězci, které mají být použiti jako CSS hodnoty (CSS identifikátory) jako v předchozím případě a řetězci, které se drží Sass datového typu, jako například klíče mapy.

Nepoužíváme uvozovky v prvním případně, ale v druhém případě využíváme jednoduchých uvozovek.

Textové řetězce obsahující uvozovky

Pokud řetězec obsahuje jednu nebo více jednoduchých uvozovek, může se řetězec namísto toho zabalit dvojitými uvozovkami ("), aby se zabránilo úniku znaků z řetězce.

// Okay
@warn 'You can\'t do that.';

// Okay
@warn "You can't do that.";
// Okay
@warn 'You can\'t do that.'

// Okay
@warn "You can't do that."

URL

URL by měly být také zabaleny v uvozovkách ze stejných důvodů jako je výše:

// Yep
.foo {
  background-image: url('/images/kittens.jpg');
}

// Nope
.foo {
  background-image: url(/images/kittens.jpg);
}
// Yep
.foo
  background-image: url('/images/kittens.jpg')

// Nope
.foo
  background-image: url(/images/kittens.jpg)
Další četba

Čísla

V Sassu je číslo datový typ, včetně všeho od bezjednotkových čísel po délky, trvání, frekvence, úhly a tak dále. To umožňuje spustit výpočty na těchto opatřeních.

Nuly

Čísla by měla zobrazovat nulu před tečkou pro hodnoty menší než jedna. Nikdy nezobrazujte koncové nuly.

// Yep
.foo {
  padding: 2em;
  opacity: 0.5;
}

// Nope
.foo {
  padding: 2.0em;
  opacity: .5;
}
// Yep
.foo
  padding: 2em
  opacity: 0.5

// Nope
.foo
  padding: 2.0em
  opacity: .5

Jednotky

Pokud se zaměříme na jednotky, 0 by nikdy neměla mít definovanou jednotku.

// Yep
$length: 0;

// Nope
$length: 0em;
// Yep
$length: 0

// Nope
$length: 0em

Nejčastější chybou, která mě napadne v souvislosti s čísly v Sassu, je ta, že jednotky jsou jen nějaké textové řetězce, které mohou být bezpečně dosazeny k číslu. I když to je pravda, určitě to není jak jednotky fungují. Představte si jednotky jako algebraické symboly. Například v reálném světě, násobení 5 centimetrů 5 centimetry vám dá 25 centimetrů čtverečních. Stejná logika platí i pro Sass.

Pro přidání jednotky k číslu musíte číslo vynásobit 1 jednotkou.

$value: 42;

// Yep
$length: $value * 1px;

// Nope
$length: $value + px;
$value: 42

// Yep
$length: $value * 1px

// Nope
$length: $value + px

Všimněte si, že 0 členů té jednotky také funguje, ale já bych vám raději doporučoval zmíněnou metodu, jelikož přidáním 0 jednotky může být tak trochu matoucí. Avšak pokud se budete snažit převést číslo do jiné kompatibilní jednotky, přidání 0 na to nebude stačit.

$value: 42 + 0px;
// -> 42px

$value: 1in + 0px;
// -> 1in

$value: 0px + 1in;
// -> 96px
$value: 42 + 0px
// -> 42px

$value: 1in + 0px
// -> 1in

$value: 0px + 1in
// -> 96px

Nakonec to všechny závisí na tom, čeho se snažíte dosáhnout. Jenom mějte na paměti, že přidáním jednotky v řetězci není dobrou cestou jak to dělat.

Pro odstranění jednotky z hodnoty ji musíte vydělit jednou jednotkou svého druhu.

$length: 42px;

// Yep
$value: $length / 1px;

// Nope
$value: str-slice($length + unquote(''), 1, 2);
$length: 42px

// Yep
$value: $length / 1px

// Nope
$value: str-slice($length + unquote(''), 1, 2)

Připojením jednotky v řetězci k číslu vznikne řetězec, který zamezí jakýmkoli dalším operacím na hodnotě. Krajení numerické části čísla jednotkou také vyústí v řetězec. A to není to, co chcete.

Výpočty

Numerické výpočty na nejvyšší úrovni by měly být vždy zabaleny v závorkách. Nejen, že tento požadavek výrazně zlěpší čitelnost, ale také zabrání některým krajním případům tím, že nutí Sass vyhodnotit obsah závorek.

// Yep
.foo {
  width: (100% / 3);
}

// Nope
.foo {
  width: 100% / 3;
}
// Yep
.foo
  width: (100% / 3)

// Nope
.foo
  width: 100% / 3

Magická čísla

“Magická čísla” je old school programovací termín pro nepojmenované matematické konstanty. V podstatě to je jen náhodné číslo, které prostě funguje™ a zatím není vázáno na žádné logické vysvětlení.

Netřeba snad ani dodávat, že magická čísla jsou mor a mělo by se jim vyhýbat za jakoukoli cenu. Pokud nemůžete najít rozumné vysvětlení, proč číslo funguje, přidejte rozsáhlý komentář vysvětlující jak jste se tam dostali a proč si myslíte, že to funguje. Přiznáním se, že nevíte proč něco funguje je stále více užitečné pro dalšího vývojáře, než aby sám musel přijít na to co se děje on nuly.

/**
 * 1. Magic number. This value is the lowest I could find to align the top of
 * `.foo` with its parent. Ideally, we should fix it properly.
 */
.foo {
  top: 0.327em; /* 1 */
}
/**
 * 1. Magic number. This value is the lowest I could find to align the top of
 * `.foo` with its parent. Ideally, we should fix it properly.
 */
.foo
  top: 0.327em /* 1 */
Další četba

Barvy

Barvy zaujímají v CSS jazyce důležité místo. Jako obvykle, Sass je nakonec cenným spojencem když přijde na řadu manipulace s barvami, především proto, jelikož obsahuje mocné funkce.

Formáty barev

Aby byly barvy tak jednoduché, jak jen mohou být, moje rada je respektovat následující pořadí formátů barev:

  1. CSS klíčová slova pro barvy;
  2. HSL notace;
  3. RGB notace;
  4. Hexadecimální notace. Přednostně malá písmena a zkrácené kde je jen možné.

Pro začátek, klíčová slova často mluví sami za sebe. HSL reprezentace je nejen ta nejjednodušší pro lidský mozek na pochopení [citation needed], ale také ulehčuje autorům stylu vyladit barvu úpravou odstínu, sytosti a světlosti individuálně. RGB má stále tu výhodu, že hned vidíte, jestli má barva více modré, zelené, nebo červené, ale to neznamená, že je vytvoření barvy ze tří částí jednoduché. Poslední, hexadecimální, je pro lidskou mysl skoro nečitelný.

// Yep
.foo {
  color: hsl(0, 100%, 50%);
}

// Also yep
.foo {
  color: rgb(255, 0, 0);
}

// Meh
.foo {
  color: #f00;
}

// Nope
.foo {
  color: #FF0000;
}

// Nope
.foo {
  color: red;
}
.foo
  color: hsl(0, 100%, 50%)

// Also yep
.foo
  color: rgb(255, 0, 0)

// Nope
.foo
  color: #f00

// Nope
.foo
  color: #FF0000

// Nope
.foo
  color: red

Při používání HSL nebo RGB notace vždy přidejte jednu mezeru po čárce (,), ale nepřidávejte žádnou mezeru mezi závorkami ((, )) a obsahem.

// Yep
.foo {
  color: rgba(0, 0, 0, 0.1);
  background: hsl(300, 100%, 100%);
}

// Nope
.foo {
  color: rgba(0,0,0,0.1);
  background: hsl( 300, 100%, 100% );
}
// Yep
.foo
  color: rgba(0, 0, 0, 0.1)
  background: hsl(300, 100%, 100%)

// Nope
.foo
  color: rgba(0,0,0,0.1)
  background: hsl( 300, 100%, 100% )

Barvy a proměnné

Pokud barvu používáte více než jednou, uložte jí do proměnné se smysluplným názvem reprezentující barvu.

$sass-pink: hsl(330, 50%, 60%);
$sass-pink: hsl(330, 50%, 60%)

Odteď budete moci používat tuto proměnnou kdekoliv chcete. Pokud je však vaše proměnná velmi svázaná s tématem, radil bych, abyste ji nepoužívali tak, jak je. Namísto toho ji uložte v jiné proměnné se jménem vysvětlující, jak by se měla používat.

$main-theme-color: $sass-pink;
$main-theme-color: $sass-pink

Tímto zabráníte problémům vyplývajících ze změny tématu jako $sass-pink: blue.

Zesvětlení a ztmavení barev

Obě, lighten a darken funkce manipulují ze světlostí barvy v HSL formátu přidáním nebo odebráním světlosti. V podstatě nejsou ničím jiným než jen alias pro $lightness parametr adjust-color funkce.

Věc se má tak, že tyto funkce často neprovádí očekávaný výsledek. Na druhou stranu mix funkce je pěkná cesta, jak zesvětlit nebo ztmavit barvu namícháním s white nebo black.

Výhoda ve využívání mix spíše než jednu z těch dvou funkcí shora je, že postupně půjde do černé (nebo bílé), jak budete snižovat poměr barvy, zatímco darken a lighten rychle sfouknou barvu do černé nebo bílé.

Ilustrace rozdílu mezi lighten/darken a mix od KatieK
Ilustrace rozdílu mezi lighten/darken a mix od KatieK

Pokud nechcete pokaždé psát mix funkci, můžete vytvořit dvě jednoduché funkce tint a shade (které jsou také částí Compass) aby dělaly tu stejnou věc:

/// Slightly lighten a color
/// @access public
/// @param {Color} $color - color to tint
/// @param {Number} $percentage - percentage of `$color` in returned color
/// @return {Color}
@function tint($color, $percentage) {
  @return mix(white, $color, $percentage);
}

/// Slightly darken a color
/// @access public
/// @param {Color} $color - color to shade
/// @param {Number} $percentage - percentage of `$color` in returned color
/// @return {Color}
@function shade($color, $percentage) {
  @return mix(black, $color, $percentage);
}
/// Slightly lighten a color
/// @access public
/// @param {Color} $color - color to tint
/// @param {Number} $percentage - percentage of `$color` in returned color
/// @return {Color}
@function tint($color, $percentage)
  @return mix($color, white, $percentage)

/// Slightly darken a color
/// @access public
/// @param {Color} $color - color to shade
/// @param {Number} $percentage - percentage of `$color` in returned color
/// @return {Color}
@function shade($color, $percentage)
  @return mix($color, black, $percentage)

Funkce scale-color je navržena tak, že škáluje vlastnosti více plynule tím, že vezme v úvahu, jak vysoké nebo nízké již jsou. To by mělo poskytnou výsledky, které jsou hezké jako mix, ale s jasnější konvencí pro volání. Měřítko přesně totéž.

Další četba

Seznamy

Seznamy jsou Sass verzí polí. Seznam má strukturu jednorozměrného pole (na rozdíl od mapy), které jsou navrženy tak, aby mohly obsahovat hodnoty jakéhokoli typu (včetně listů, což vede k vnořeným seznamům).

Seznamy by měly být tvořeny podle následujícího manuálu:

  • buď je jednořádkový nebo víceřádkový;
  • pokud je příliš dlouhý, aby se vešel na 80 znaků, musí být víceřádkový;
  • pokud není používaný pro účely CSS, vždy se položky rozdělují čárkami;
  • vždy musí být zabalený v závorkách;
  • koncová čárka se přidává pokud je víceřádkový, pokud je jednořádkový, tak ne.
// Yep
$font-stack: ('Helvetica', 'Arial', sans-serif);

// Yep
$font-stack: (
  'Helvetica',
  'Arial',
  sans-serif,
);

// Nope
$font-stack: 'Helvetica' 'Arial' sans-serif;

// Nope
$font-stack: 'Helvetica', 'Arial', sans-serif;

// Nope
$font-stack: ('Helvetica', 'Arial', sans-serif,);
// Yep
$font-stack: ('Helvetica', 'Arial', sans-serif)

// Nope (not supported)
$font-stack: (
  'Helvetica',
  'Arial',
  sans-serif,
)

// Nope
$font-stack: 'Helvetica' 'Arial' sans-serif

// Nope
$font-stack: 'Helvetica', 'Arial', sans-serif

// Nope
$font-stack: ('Helvetica', 'Arial', sans-serif,)

Pokud přidáváte nové položky do seznamu, vždy používejte dodávané API. Nepokoušejte se přidávat položky manuálně.

$shadows: (0 42px 13.37px hotpink);

// Yep
$shadows: append($shadows, $shadow, comma);

// Nope
$shadows: $shadows, $shadow;
$shadows: (0 42px 13.37px hotpink)

// Yep
$shadows: append($shadows, $shadow, comma)

// Nope
$shadows: $shadows, $shadow
Další četba

Mapy

Již od Sassu 3.3 mohou autoři definovat mapy — což je Sass termín pro asociativní pole, hashe, nebo dokonce JavaScript objekty. Mapa je datová struktura, která mapuje klíče (což mohou být jakékoli datové typy, včetně map, což bych ale nedoporučoval) k hodnotám jakéhokoli datového typu.

Mapy by se měly psát tak, jako je popsáno níže:

  • mezera za dvojtečkou (:);
  • otevírací závorka (() na stejném řádku jako dvojtečka (:);
  • pokud je klíč textový řetězec, pak by měl být v uvozovkách (což je 99% případů);
  • každý pár klíč/hodnota na svém vlastním řádku;
  • čárka (,) na konci každého páru klíč/hodnota;
  • koncová čárka (,) by měla být i na konci poslední položky, pro snadnější přidávání, odstraňování, nebo změnu pořadí položek;
  • uzavírací závorka ()) na novém řádku;
  • žádná mezera nebo nový řádek mezi uzavírací závorkou ()) a středníkem (;).

Ilustrace:

// Yep
$breakpoints: (
  'small': 767px,
  'medium': 992px,
  'large': 1200px,
);

// Nope
$breakpoints: ( small: 767px, medium: 992px, large: 1200px );
// Yep
$breakpoints: ('small': 767px, 'medium': 992px, 'large': 1200px,)

// Nope
$breakpoints: ( 'small': 767px, 'medium': 992px, 'large': 1200px )

// Nope
$breakpoints: (small: 767px, medium: 992px, large: 1200px,)

// Nope (since it is not supported)
$breakpoints: (
  'small': 767px,
  'medium': 992px,
  'large': 1200px,
)

Debugování Sass map

Pokud se někdy ocitnete ztraceni, nebo budete přemýšlet, co za šílenou magii se právě v Sass mapě děje, pak se nebojte, protože je tu stále možnost záchrany.

@mixin debug-map($map) {
  @at-root {
    @debug-map {
      __toString__: inspect($map);
      __length__: length($map);
      __depth__: if(function-exists('map-depth'), map-depth($map), null);
      __keys__: map-keys($map);
      __properties__ {
        @each $key, $value in $map {
          #{'(' + type-of($value) + ') ' + $key}: inspect($value);
        }
      }
    }
  }
}
=debug-map($map)
  @at-root
    @debug-map
      __toString__: inspect($map)
      __length__: length($map)
      __depth__: if(function-exists('map-depth'), map-depth($map), null)
      __keys__: map-keys($map)
      __properties__
        @each $key, $value in $map
          #{'(' + type-of($value) + ') ' + $key}: inspect($value)

Pokud jste zvědavi, do jaké hloubky vaše mapa sahá, přidejte následující funkci. Mixin ji zobrazí automaticky.

/// Compute the maximum depth of a map
/// @param {Map} $map
/// @return {Number} max depth of `$map`
@function map-depth($map) {
  $level: 1;

  @each $key, $value in $map {
    @if type-of($value) == 'map' {
      $level: max(map-depth($value) + 1, $level);
    }
  }

  @return $level;
}
/// Compute the maximum depth of a map
/// @param {Map} $map
/// @return {Number} max depth of `$map`
@function map-depth($map)
  $level: 1

  @each $key, $value in $map
    @if type-of($value) == 'map'
      $level: max(map-depth($value) + 1, $level)

  @return $level;
Další četba

CSS pravidla

V tuto chvíli zde uvedu, co většina asi ví, jak by měly být CSS pravidla psány (nebo alespoň jak je nejvíce uvedeno v manuálech, včetně CSS Guidelines):

  • související selektory na stejném řádku; nesouvisející na nových řádcích;
  • otevírací závorka ({) oddělena jednou mezerou od posledního selektoru;
  • každá deklarace na svém vlastním řádku;
  • mezera za středníkem (:);
  • uzavírací středník (;) na konci každé deklarace;
  • uzavírací závorka (}) na svém vlastním novém řádku;
  • nový řádek po uzavírací závorce }.

Ilustrace:

// Yep
.foo, .foo-bar,
.baz {
  display: block;
  overflow: hidden;
  margin: 0 auto;
}

// Nope
.foo,
.foo-bar, .baz {
    display: block;
    overflow: hidden;
    margin: 0 auto }
// Yep
.foo, .foo-bar,
.baz
  display: block
  overflow: hidden
  margin: 0 auto

// Nope
.foo,
.foo-bar, .baz
    display: block
    overflow: hidden
    margin: 0 auto

Přidáním těchto pokynů k CSS budeme dávat pozor na toto:

  • deklarovat lokální proměnné před jakoukoli deklarací, potom oddělit of deklarace novým řádkem;
  • volání mixinů bez @content před jakoukoli deklarací;
  • vnořené selektory vždy po novém řádku;
  • volání mixinů s @content po vnořených selektorech;
  • žádný řádek před zavírací závorkou (}).

Ilustrace:

.foo, .foo-bar,
.baz {
  $length: 42em;

  @include ellipsis;
  @include size($length);
  display: block;
  overflow: hidden;
  margin: 0 auto;

  &:hover {
    color: red;
  }

  @include respond-to('small') {
    overflow: visible;
  }
}
.foo, .foo-bar,
.baz
  $length: 42em

  +ellipsis
  +size($length)
  display: block
  overflow: hidden
  margin: 0 auto

  &:hover
    color: red

  +respond-to('small')
    overflow: visible
Další četba

Řazení deklarace

Nenapadá mě snad žádné jiné téma, kde jsou názory tak rozdělené jako právě v řazení CSS deklarací. Konkrétně se dělí na dvě frakce:

  • držet se abecedního pořadí;
  • řadit deklarace dle typu (pozice, zobrazení, barvy, písmo, a další…).

V obou případech najdete výhody i nevýhody. Na jednu stranu je abecení pořadí univerzální (alespoň pro jazyky, které používají latinku), takže nemůže nastat situace, kdy se budete muset rozhodnout, jestli toto bude před tím, nebo ne. Každopádně vidět bottom a top od sebe je tak trochu divné. Proč by měly animace být před typem zobrazení? S abecedním pořadí existuje dost zvláštností.

.foo {
  background: black;
  bottom: 0;
  color: white;
  font-weight: bold;
  font-size: 1.5em;
  height: 100px;
  overflow: hidden;
  position: absolute;
  right: 0;
  width: 100px;
}
.foo
  background: black
  bottom: 0
  color: white
  font-weight: bold
  font-size: 1.5em
  height: 100px
  overflow: hidden
  position: absolute
  right: 0
  width: 100px

Na druhou stranu, řazení vlastností podle typu dává perfektní smysl. Každá deklarace okolo písma je u sebe, top a bottom jsou znovu u sebe a číst pravidla je jako číst krátký příběh. Ale dokud nezačnete používat nějaké konvence jako Idiomatic CSS, je tu spoustu možností jak danou věc udělat. Kde by se měla řadit white-space? Do písma, nebo zobrazení? Kam přesně patří overflow? Jaké je pořadí vlastností v dané skupině (mělo by to být abecedně, jaká to ironie)?

.foo {
  height: 100px;
  width: 100px;
  overflow: hidden;
  position: absolute;
  bottom: 0;
  right: 0;
  background: black;
  color: white;
  font-weight: bold;
  font-size: 1.5em;
}
.foo
  height: 100px
  width: 100px
  overflow: hidden
  position: absolute
  bottom: 0
  right: 0
  background: black
  color: white
  font-weight: bold
  font-size: 1.5em

Je tu také další zajímavý způsob řazení nazývaný Concentric CSS, což vypadá, že je také populární. Concentric CSS pro určení pořadí v podstatě spoléhá na box-model.

.foo {
  width: 100px;
  height: 100px;
  position: absolute;
  right: 0;
  bottom: 0;
  background: black;
  overflow: hidden;
  color: white;
  font-weight: bold;
  font-size: 1.5em;
}
.foo
  width: 100px
  height: 100px
  position: absolute
  right: 0
  bottom: 0
  background: black
  overflow: hidden
  color: white
  font-weight: bold
  font-size: 1.5em

Musím říci, že se sám nemohu rozhodnout. Nedávný průzkum na CSS-Tricks zjistil, že přes 45% vývojářů řadí své deklarace podle typu a oproti tomu 14% abecedně. Ale je tu také 39%, kteří vše řadí náhodně, včetně mě.

Graf ukazuje, jak vývojáři řadí své CSS deklarace
Graf ukazuje, jak vývojáři řadí své CSS deklarace

Právě proto nebudu do příručky dávat doporučení na výběr. Vyberte si tu, kterou preferujete vy, jen buďte ve všech stylech konzistentní (tedy žádná náhodná možnost).

Nedávná studie ukazuje, že používání CSS Comb (což používá řazení podle typu) pro řazení CSS deklarací končí s zkrácením průměrné velikosti pod Gzip kompresí o 2,7%, v porovnání 1,3% když je řazení podle abecedy.

Další četba

Noření selektorů

Jedna konkrétní funkce Sass, která je až příliš zneužívána spoustou vývojářů je noření selektorů. Noření selektorů nabízí způsob, jak se autoři stylů mohou vypořádat s dlouhými selektory vnořováním menších v dalších.

Obecné pravidlo

Například následující vnořování v Sass:

.foo {
  .bar {
    &:hover {
      color: red;
    }
  }
}
.foo
  .bar
    &:hover
      color: red

… vygeneruje toto CSS:

.foo .bar:hover {
  color: red;
}

Ve stejném duchu, od Sass 3.3, je možné použít referenci na aktuální selektor (&) ke generování rozšířených selektorů. Například:

.foo {
  &-bar {
    color: red;
  }
}
.foo
  &-bar
    color: red

… vygeneruje toto CSS:

.foo-bar {
  color: red;
}
.foo-bar
  color: red

Tento způsob se často používá spolu s BEM jmennou konvencí pro generování .block__element a .block--modifier selektorů založených na originálním selektoru (tedy v tomto případě .block).

Ačkoliv je to možná neoficiální, generování nových selektorů z reference aktuálního selektoru (&) dělá tyto selektory nedosažitelné v codebase, protože samy o sobě neexistují.

Problém s vnořenými selektory je ten, že je v konečném důsledku dělá hůře čitelné. Každý si pak musí v hlavně domyslet výsledný selektor z úrovně odsazení, což není vždy až tak jasné, jak se může zdát.

Toto tvrzení se stává skutečnější čím dál tím více, čím je aktuální selektor (&) četnější. Od nějakého bodu je také čím dál tím větší riziko, že nikdo nepochopí, co se děje, že to za to ani nestojí.

Abyste se takovýmto situacím vyhnuli, vyhýbejte se vnořeným selektorům jak jen to jde. Každopádně pro toto pravidlo je samozřejmě pár výjimek.

Výjimky

Pro začátek, je dovoleno a dokonce doporučeno nořit pseudo třídy a pseudo elementy do původního selektoru.

.foo {
  color: red;

  &:hover {
    color: green;
  }

  &::before {
    content: 'pseudo-element';
  }
}
.foo
  color: red

  &:hover
    color: green

  &::before
    content: 'pseudo-element'

Používání noření pro pseudo třídy a pseudo selektory nejenom že dává smysl (protože se vypořádává s úzce souvisejícími selektory), ale také pomáhá udržet všechno o komponentě na jednom místě.

Také když používáte třídy, které určují pravdivost, jako například .is-active, je naprosto v pořádku vnořit ji do selektoru komponenty, abyste zachovali věci v pořádku.

.foo {
  // …

  &.is-active {
    font-weight: bold;
  }
}
.foo
  // …

  &.is-active
    font-weight: bold

V neposlední řadě, když stylujete element protože musí být obsažen v nějakém specifickém elementu, je často fajn použít noření k udržení všeho o komponentě na stejném místě.

.foo {
  // …

  .no-opacity & {
    display: none;
  }
}
.foo
  // …

  .no-opacity &
    display: none

Když pracujete s nezkušenými vývojáři, selektor jako .no-opacity & může vypadat tak trochu divně. Abyste zabránili jakýmkoli rozpakům, můžete udělat velmi krátký mixin, který přemění tuto divnou syntaxi na výslovné API.

/// Helper mixin to provide simple API to selector nesting
/// @param {String} $selector - Selector
@mixin when-inside($selector) {
  #{$selector} & {
    @content;
  }
}
/// Helper mixin to provide simple API to selector nesting
/// @param {String} $selector - Selector
=when-inside($selector) {
  #{$selector} &
    @content
}

Přepsáním předešlého příkladu by to vypadalo asi takto:

.foo {
  // …

  @include when-inside('.no-opacity') {
    display: none;
  }
}
.foo
  // …

  +when-inside('.no-opacity')
    display: none

Jako asi se vším, specifika jsou poněkud nedůležitá, důležitá je konzistence. Pokud noření plně důvěřujete, klidně noření používejte. Jenom se ujistěte, že to nikomu z vašeho týmu nevadí.

Další četba

Jmenné konvence

V této sekci se nebudeme zabývat nejlepšími jmennými CSS konvencemi pro udržovatelnost a rozsah. Nejen že je to jen a jen na vás, ale je to také mimo oblast Sass manuálu. Navrhuji však ty, které jsou doporučeny v CSS Guidelines.

Je tu však pár věcí, které můžete v Sassu pojmenovat a je důležité je pojmenovat dobře, takže celý codebase bude vypadat konzistentní a bude snadno čitelný:

  • proměnné;
  • funkce;
  • mixiny.

Sass placeholdery jsou z tohoto seznamu úmyslně vynechány, jelikož mohou být považovány za běžné CSS selektory a proto na ně platí stejné vzory pro název jako pro třídy.

Pokud jde o proměnné, funce a mixiny, držme se něčeho velmi ve stylu CSS: malé písmo oddělené pomlčkami a především smysluplného.

$vertical-rhythm-baseline: 1.5rem;

@mixin size($width, $height: $width) {
  // …
}

@function opposite-direction($direction) {
  // …
}
$vertical-rhythm-baseline: 1.5rem

=size($width, $height: $width)
  // …

@function opposite-direction($direction)
  // 
Další četba

Konstanty

Pokud jste náhodou vývojáři frameworku, nebo píšete knihovnu, pravděpodobně se potýkáte s proměnnými, které nejsou zamýšleny tak, aby se daly upravovat: konstanty. Bohužel (nebo naštěstí?) Sass neumožňuje žádnou cestu pro takovouto věc, takže si musíme vystačit s jmennými konvencemi.

Tak jako pro mnoho jazyků, doporučuji proměnné, pokud jsou konstantami, psát velkým písmem. Nejen že je to velmi stará konvence, ale také snadno poznáte, že je daná proměnná právě konstantou, jelikož je v kontrastu s proměnnými psanými malým písmem a oddělenými pomlčkami.

// Yep
$CSS_POSITIONS: (top, right, bottom, left, center);

// Nope
$css-positions: (top, right, bottom, left, center);
// Yep
$CSS_POSITIONS: (top, right, bottom, left, center)

// Nope
$css-positions: (top, right, bottom, left, center)
Další četba

Namespace

Pokud máte v úmyslu svůj Sass kód rozšířit, v případě knihovny, frameworku, grid systému nebo čehokoli, pravděpodobně zvažujete použít namespace na všechny vaše proměnné, funkce, mixiny a placeholdery, takže nebude moci dojít ke konfliktu s kódem někoho jiného.

Například, pokud pracujete na projektu Sassy Unicorn, se kterým budou moci pracovat vývojáři z celého světa (kdo by ne, že ano?), můžete zvážit použít su- jako namespace. Je to dost specifické aby se zabránilo jakémukoli kolidování názvu a krátké dost na to, aby to nebolelo psát.

$su-configuration: (  );

@function su-rainbow($unicorn) {
  // …
}
$su-configuration: (  )

@function su-rainbow($unicorn)
  // 

Poznámka: automatické namespacy budou definitivně designový cíl pro připravovaný @import od Sassu 4.0. Čím je blíže k uskutečnění, tím je méně a méně užitečné dělat namespace ručně. Případně ručně namespacované knihovny mohou být složitější na použití.

Další četba

Komentování

CSS je ošemetný jazyk plný hacků a podivností. Díky tomu by měl být hodně komentován, zvláště pokud vy nebo někdo jiný zamýšlíte číst a upravovat kód za 6 měsíců nebo rok. Nenechte se, nebo někoho jiného, dostat do pozice Já-jsem-tohle-pane-bože-nenapsal.

I přesto, že se CSS může zdát jednoduché, je mnoho situací, kdy může komentář hodně vysvětlit. Mohou vysvětlit takové věci jako:

  • struktura a/nebo smysl souboru;
  • cíl pravidla;
  • smysl za magickým číslem;
  • důvod pro CSS deklaraci;
  • pořádek CSS deklarací;
  • myšlenkový proces za způsobem dělání věcí.

A pravděpodobně jsem ještě zapomněl mnoho dalších důvodů. Komentování zabere málo času, když se dělá plynule při psaní kódu, takže jej dělejte ve správný čas. Vracet se zpátky okomentovat kus kódu není nejen zcela nereálné, ale je to zároveň příšerně otravné.

Psaní komentářů

Nejlepší je, když každé CSS pravidlo předchází předchází komentář ve stylu jazyka C, který vysvětluje smysl CSS bloku. Tento komentář může také obsahuje očíslované vysvětlení pro specifické části pravidel. Například:

/**
 * Helper class to truncate and add ellipsis to a string too long for it to fit
 * on a single line.
 * 1. Prevent content from wrapping, forcing it on a single line.
 * 2. Add ellipsis at the end of the line.
 */
.ellipsis {
  white-space: nowrap; /* 1 */
  text-overflow: ellipsis; /* 2 */
  overflow: hidden;
}
/**
 * Helper class to truncate and add ellipsis to a string too long for it to fit
 * on a single line.
 * 1. Prevent content from wrapping, forcing it on a single line.
 * 2. Add ellipsis at the end of the line.
 */
.ellipsis
  white-space: nowrap /* 1 */
  text-overflow: ellipsis /* 2 */
  overflow: hidden

V podstatě všechno co není zřejmé na první pohled, by mělo být okomentováno. Není tu nic takového jako přiliš mnoho dokumentace. Pamatujte, že nemůžete komentovat zas tak mnoho, takže nažhavte klávesy a pište komentáře pro všechno, co za to stojí.

Pokud komentujete Sass specifickou sekci, použijte Sass řádkové komentáře namísto blokových komentářů ve stylu jazyka C. To zapříčiní, že se komentář nezobrazí ve výstupu, dokonce i v expanded módu během vývoje.

// Add current module to the list of imported modules.
// `!global` flag is required so it actually updates the global variable.
$imported-modules: append($imported-modules, $module) !global;
// Add current module to the list of imported modules.
// `!global` flag is required so it actually updates the global variable.
$imported-modules: append($imported-modules, $module) !global
Další četba

Dokumentace

Každá proměnná, funkce, mixin a placeholder, která je zamýšlena býti znovupoužitelná v codebase by měla být dokumentována jako část globálního API využívající SassDoc.

/// Vertical rhythm baseline used all over the code base.
/// @type Length
$vertical-rhythm-baseline: 1.5rem;
/// Vertical rhythm baseline used all over the code base.
/// @type Length
$vertical-rhythm-baseline: 1.5rem

Jsou vyžadovány tři lomítka (/).

SassDoc má dvě hlavní role:

  • vynutit standardizované komentáře využívající systému založeném na anotacích pro všechno, co je součástí veřejného nebo privátního API;
  • být schopný generovat HTML verze API dokumentace za použití některého ze SassDoc koncového bodu (CLI tool, Grunt, Gulp, Broccoli, Node…).
Dokumentace generována ze SassDoc
Dokumentace generována ze SassDoc

Zde je příklad rozsáhle dokumentovaného mixinu se SassDoc:

/// Mixin helping defining both `width` and `height` simultaneously.
///
/// @author Hugo Giraudel
///
/// @access public
///
/// @param {Length} $width - Element’s `width`
/// @param {Length} $height [$width] - Element’s `height`
///
/// @example scss - Usage
///   .foo {
///     @include size(10em);
///   }
///
///   .bar {
///     @include size(100%, 10em);
///   }
///
/// @example css - CSS output
///   .foo {
///     width: 10em;
///     height: 10em;
///   }
///
///   .bar {
///     width: 100%;
///     height: 10em;
///   }
@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}
/// Mixin helping defining both `width` and `height` simultaneously.
///
/// @author Hugo Giraudel
///
/// @access public
///
/// @param {Length} $width - Element’s `width`
/// @param {Length} $height ($width) - Element’s `height`
///
/// @example scss - Usage
///   .foo
///     +size(10em)
///
///   .bar
///     +size(100%, 10em)
///
/// @example css - CSS output
///   .foo {
///     width: 10em;
///     height: 10em;
///   }
///
///   .bar {
///     width: 100%;
///     height: 10em;
///   }
=size($width, $height: $width)
  width: $width
  height: $height
Další četba

Architektura

Navrhnout architekturu CSS projektu je pravděpodobně jedna z nejvíce těžkých věcí, kterou budete muset v životě projektu udělat. Udržovat návrh konzistentní a smysluplný je ještě těžší.

Naštěstí, jedna z hlavních výhod používání CSS preprocesoru je schopnost rozdělit codebase do několika souborů bez dopadu na výkon (jako dělá CSS direktiva @import). Díky přetížení Sass @import direktiv je naprosto bezpečné (a vlastně i doporučované) používat tak mnoho souborů, kolik je ve vývoji nezbytné a všechno pro produkci kompilovat do jednoho stylu.

Nad vším tímhle snad ani nemohu dostatečně zdůraznit potřebu složek, a to dokonce i u malých projektů. Doma také nedáváte každý list papíru do jedné a té samé krabice. Používáte složky. Jednu pro dům/byt, jednu pro banku, jednu pro účty, a tak dále. Není tedy žádný důvod dělat to jinak při strukturování CSS projektu. Rozdělte codebase do smysluplně rozdělených složek tak, ať je později jednoduché najít věci, když se do kódu vrátíte později.

Je tu hodně populárních architektur pro CSS projekty: OOCSS, Atomic Design, Bootstrap-like, Foundation-like… Všechny mají své přednosti, klady a zápory.

Já sám používám přístup shodou okolností docela podobný k SMACSS od Jonathan Snook, který se zaměřuje na udržování věcí jednoduchých a jasných.

Naučil jsem se, že architektura je většinou velmi specifická pro daný projekt. Neváhejte jí tedy kompletně zrušit, nebo upravit navrhované řešení tak, aby jste se vypořádali se systémem, který sedí vašim potřebám.

Další četba

Komponenty

Je tu podstatný rozdíl mezi děláním to funkční a děláním to dobře. Znovu, CSS je tak trochu nepořádný jazyk [nutná citace]. Čím méně CSS máme, tím lépe. Nechceme se zabývat s megybyty CSS kódu. Chcete-li zachovat styly krátké a efektivní—a to pro vás nebude žádné překvápko—je většinou dobrý nápad přemýšlet o rozhraní jako o kolekci komponent.

Komponenty mohou být cokoliv, tak dlouho dokud:

  • dělají pouze jednu věc;
  • jsou v projektu znovu použitelné;
  • jsou nezávislé.

Například vyhledávací formulář by měl být považován za komponentu. Měl by být znovu použitelný, na různých místech, na různých stránkách, v rozdílných situacích. Neměl by záviset na pozici v DOM (patička, postranní panel, hlavní obsah…).

Většina z jakéhokoliv rozhraní se dá představit jako malé komponenty a hodně doporučuji, abyste se drželi tohoto paradigmatu. Tím se nejen že zkrátí množství potřebného CSS pro celý projekt, ale také to bude jednodušší spravovat spíše než-li chaotický nepořádek, kde je všechno vyvedeno z míry.

Vzor 7-1

Zpátky k architektuře, můžeme? Obvykle pracuji s tím, čemu říkám vzor 7-1: 7 složek, 1 soubor. V podstatě máte všechny své partials nacpané do 7 různých složek a jeden soubor na kořenové úrovni (obvykle pojmenován main.scss) je všechny importuje do CSS stylu.

  • base/
  • components/
  • layout/
  • pages/
  • themes/
  • utils/
  • vendors/

A samozřejmě:

  • main.scss
Tapeta od Julien He
Tapeta od Julien He

Ideálně můžeme přijít s něčím jako je toto:

sass/
|
|– abstracts/
|   |– _variables.scss    # Sass Variables
|   |– _functions.scss    # Sass Functions
|   |– _mixins.scss       # Sass Mixins
|   |– _placeholders.scss # Sass Placeholders
|
|– base/
|   |– _reset.scss        # Reset/normalize
|   |– _typography.scss   # Typography rules
|   …                     # Etc.
|
|– components/
|   |– _buttons.scss      # Buttons
|   |– _carousel.scss     # Carousel
|   |– _cover.scss        # Cover
|   |– _dropdown.scss     # Dropdown
|   …                     # Etc.
|
|– layout/
|   |– _navigation.scss   # Navigation
|   |– _grid.scss         # Grid system
|   |– _header.scss       # Header
|   |– _footer.scss       # Footer
|   |– _sidebar.scss      # Sidebar
|   |– _forms.scss        # Forms
|   …                     # Etc.
|
|– pages/
|   |– _home.scss         # Home specific styles
|   |– _contact.scss      # Contact specific styles
|   …                     # Etc.
|
|– themes/
|   |– _theme.scss        # Default theme
|   |– _admin.scss        # Admin theme
|   …                     # Etc.
|
|– vendors/
|   |– _bootstrap.scss    # Bootstrap
|   |– _jquery-ui.scss    # jQuery UI
|   …                     # Etc.
|
`– main.scss              # Main Sass file

Soubory následují stejné jmenné konvence jako je popsáno výše: jsou oddelene-pomlckou.

Složka base

Složka base/ obsahuje to, co bychom mohli nazvat ‘často používaný kód’ projektu. Můžete tam najít soubor pro resetování, nějaké pravidla pro typografii a pravděpodobně styl (který nazývám _base.scss), který definuje nějaké standardní styly pro obyčejně používané HTML elementy.

  • _base.scss
  • _reset.scss
  • _typography.scss

Složka layout

Složka layout/ obsahuje vše, co se podílí na rozvržení stránky nebo aplikace. Tato složka může obsahovat styly pro hlavní části stránky (hlavička, patička, navigace, postranní panel…), grid systém nebo dokonce CSS styly pro všechny formuláře.

  • _grid.scss
  • _header.scss
  • _footer.scss
  • _sidebar.scss
  • _forms.scss
  • _navigation.scss

Složka layout/ může být také nazývána partials/, záleží především na tom, co preferujete.

Složka components

Pro menší komponenty tu je složka components/. Zatímco layout/ je makro (definuje globální wireframe), components/ je více zaměřený na widgety. Obsahuje všechny druhy specifických modulů jako slider, loader, widget a v podstatě cokoliv v tomto směru. V components/ je obvykle hodně souborů, protože celá stránka/aplikace by měla být převážně složena z malých modulů.

  • _media.scss
  • _carousel.scss
  • _thumbnails.scss

Složka components/ může být také nazývána modules/, záleží především na tom, co preferujete.

Složka pages

Pokud máte styly specifické pro jednotlivé stránky, je nejlepší je umístit do složky pages/, do souboru pojmenovaného po stránce. Není neobvyklé mít například velmi specifické styly pro úvodní stránku, proto je pak potřeba soubor _home.scss ve složce pages/.

  • _home.scss
  • _contact.scss

Tyto soubory mohou být nazvány jako jen chcete, závisí na vašem projektu, ale je nutné, abyste se vyhnuli jejich sloučení s ostatními ve výsledném stylu. Je to vážně jen na vás.

Složka themes

Na velkých stránkách a aplikacích není neobvyklé mít rozdílné témata. Jsou tu jistě různé způsoby, jak se přáve s tématy vyrovnat, ale já osobně je mám rád všechny ve složce themes/.

  • _theme.scss
  • _admin.scss

Toto je velmi specifické pro daný projekt a je proto pravděpodobné, že ji v mnoha projektech mít nebudete.

Složka utils

Složka utils/ shromažďuje všechny Sass nástroje a helpery použité napříč projektem. Měla by tu být každý globální proměnná, funkce, mixin a placeholder.

Pravidlem této složky je to, že by se neměl vypsat ani jeden řádek stylů po kompilaci. Nejedná se o nic jiného než o Sass helpery.

  • _variables.scss
  • _mixins.scss
  • _functions.scss
  • _placeholders.scss (často pojmenované jako _helpers.scss)

Složka utils/ může být také nazývána helpers/, sass-helpers/ nebo sass-utils/, záleží co preferujete vy osobně.

Složka vendors

V neposlední řadě mnoho projektů bude mít složku vendors/ obsahující všechny CSS soubory od externích knihoven a frameworků - Normalize, Bootstrap, jQueryUI, FancyCarouselSliderjQueryPowered, a tak dále. Odložení všech těchto věcí stranou do jedné složky je dobrý způsob, jak říci „Hej, tohle není ode mne, není to můj kód, není to má zodpovědnost“.

  • _normalize.scss
  • _bootstrap.scss
  • _jquery-ui.scss
  • _select2.scss

Pokud musíte přepsat sekci nějakého vendoru, doporučuji mít 8. složku nazvanou vendors-extensions/, ve které můžete mít soubory pojmenované přesně podle těch vendorů, které přepisují.

Například vendors-extensions/_bootstrap.scss je soubor obsahující všechny CSS pravidla, které předeklarovávají nějaké Bootstrap defaultní CSS. A to proto, aby se zabránilo editaci vendor souborů samo o sobě, což obecně není dobrý nápad.

Hlavní soubor

Hlavní soubor (obvykle označován main.scss) by měl být jediný Sass soubor z celého codebase, který nezačíná na podtržítko. Tento soubor by neměl obsahovat nic více než @import a komentáře.

Soubory by měly být importovány podle složky, ve které se nachází a jeden po druhém v následujícím pořadí:

  1. vendors/
  2. utils/
  3. base/
  4. layout/
  5. components/
  6. pages/
  7. themes/

V zájmu zachování čitelnosti by měl hlavní soubor respektovat tyto pokyny:

  • jeden soubor na @import;
  • jeden @import na řádek;
  • žádný nový řádek mezi dvěma importy ze stejné složky;
  • nový řádek po posledním importu ze složky;
  • vynechat přípony souborů a podtržítko na začátku.
@import 'abstracts/variables';
@import 'abstracts/functions';
@import 'abstracts/mixins';
@import 'abstracts/placeholders';

@import 'vendors/bootstrap';
@import 'vendors/jquery-ui';

@import 'base/reset';
@import 'base/typography';

@import 'layout/navigation';
@import 'layout/grid';
@import 'layout/header';
@import 'layout/footer';
@import 'layout/sidebar';
@import 'layout/forms';

@import 'components/buttons';
@import 'components/carousel';
@import 'components/cover';
@import 'components/dropdown';

@import 'pages/home';
@import 'pages/contact';

@import 'themes/theme';
@import 'themes/admin';
@import vendors/bootstrap
@import vendors/jquery-ui

@import utils/variables
@import utils/functions
@import utils/mixins
@import utils/placeholders

@import base/reset
@import base/typography

@import layout/navigation
@import layout/grid
@import layout/header
@import layout/footer
@import layout/sidebar
@import layout/forms

@import components/buttons
@import components/carousel
@import components/cover
@import components/dropdown

@import pages/home
@import pages/contact

@import themes/theme
@import themes/admin

Je tu ještě další způsob importování partials, který také považuji za validní. Na jednu stranu to dělá soubor více čitelným, ale na stranu druhou dělá úpravy trochu více bolestné. Každopádně, nechám vás rozhodnout se, který způsob je nejlepší - moc na tom nezáleží. Pro tento způsob by měl hlavní soubor dodržovat tyto pokyny:

  • jeden @import na složku;
  • konec řádku po @import;
  • každý soubor na svém vlastním řádku;
  • nový řádek po posledním importu ze složky;
  • vynechat přípony souborů a podtžítko na začátku.
@import
  'abstracts/variables',
  'abstracts/functions',
  'abstracts/mixins',
  'abstracts/placeholders';

@import
  'vendors/bootstrap',
  'vendors/jquery-ui';

@import
  'base/reset',
  'base/typography';

@import
  'layout/navigation',
  'layout/grid',
  'layout/header',
  'layout/footer',
  'layout/sidebar',
  'layout/forms';

@import
  'components/buttons',
  'components/carousel',
  'components/cover',
  'components/dropdown';

@import
  'pages/home',
  'pages/contact';

@import
  'themes/theme',
  'themes/admin';
@import
  vendors/bootstrap,
  vendors/jquery-ui

@import
  utils/variables,
  utils/functions,
  utils/mixins,
  utils/placeholders

@import
  base/reset,
  base/typography

@import
  layout/navigation,
  layout/grid,
  layout/header,
  layout/footer,
  layout/sidebar,
  layout/forms

@import
  components/buttons,
  components/carousel,
  components/cover,
  components/dropdown

@import
  pages/home,
  pages/contact

@import
  themes/theme,
  themes/admin

Abyste nemuseli importovat každý soubor ručně, můžete využít Ruby Sass rozšíření zvané sass-globbing, díky kterému můžete používat globální vzory v Sass @import jako např. @import "components/*".

Jak bylo řečeno, toto řešení bych nedoporučoval, jelikož importujete soubory podle abecedního pořadí, což obvykle není to co chcete, zvláště pokud se musíte vypořádat s pořadím souborů v závislosti na jazyku.

Ostudný soubor

Zajímavý koncept, který zpopularizoval Harry Roberts, Dave Rupert a Chris Coyier, který se skládá z uvedení všech CSS deklarací, hacků a věcí, na které nejsme pyšní do ostudného souboru. Tento soubor, který je dramaticky pojmenován _shame.scss, by měl být importován po ostatních souborech na konci stylu.

/**
 * Nav specificity fix.
 *
 * Someone used an ID in the header code (`#header a {}`) which trumps the
 * nav selectors (`.site-nav a {}`). Use !important to override it until I
 * have time to refactor the header stuff.
 */
.site-nav a {
    color: #BADA55 !important;
}
/**
 * Nav specificity fix.
 *
 * Someone used an ID in the header code (`#header a {}`) which trumps the
 * nav selectors (`.site-nav a {}`). Use !important to override it until I
 * have time to refactor the header stuff.
 */
.site-nav a
    color: #BADA55 !important
Další četba

Responzivní Web Design a breakpointy

Nemyslím si, že je Responzivní Web Design stále nutné představovat, když je to nyní snad všude. Každopádně se můžete ptát proč je sekce o RWD v Sass manuálu? Ve skutečnosti existuje pár věcí, které mohou být udělány tak, aby se s breakpointy pracovalo jednodušeji, takže myslím, že by nebyl špatný nápad je tady uvést.

Naming breakpoints

Myslím si, že mohu bez problému říci, že media queries by neměla být vázána na specifické zařízení. Například pokoušet se mířit přímo na iPady nebo Blackberry telefony je určitě špatný nápad. Media queries by se měla starat o různé velikosti obrazovky, dokud se design nerozboří a nenastoupí další media query.

Ze stejného důvodu by breakpointy neměly být pojmenovány podle zařízení ale podle něčeho obecnějšího. Hlavně proto, že některé telefony jsou nyní větší než tablety, některé tablety větší než malé počítače atd.

// Yep
$breakpoints: (
  'medium': (min-width: 800px),
  'large': (min-width: 1000px),
  'huge': (min-width: 1200px),
);

// Nope
$breakpoints: (
  'tablet': (min-width: 800px),
  'computer': (min-width: 1000px),
  'tv': (min-width: 1200px),
);
// Yep
$breakpoints: ('medium': (min-width: 800px), 'large': (min-width: 1000px), 'huge': (min-width: 1200px))

// Nope
$breakpoints: ('tablet': (min-width: 800px), 'computer': (min-width: 1000px), 'tv': (min-width: 1200px))

V tomto bodě naprosto stačí, pokud použijeme jakoukoli jmennou konvenci, která dává smysl a není spjata s konkrétními zařízeními.

$breakpoints: (
  'seed': (min-width: 800px),
  'sprout': (min-width: 1000px),
  'plant': (min-width: 1200px),
);
$breakpoints: ('seed': (min-width: 800px), 'sprout': (min-width: 1000px), 'plant': (min-width: 1200px))

Předešlý příklad používá vnořené mapy pro definování breakpointů, každopádně opravdu záleží jen na vás, jaký druh správy použijete. Můžete se rozhodnout pro textové řetězce, spíše než-li pro vnitřní mapy, kvůli větší pružnosti (tedy '(min-width: 800px)').

Další četba

Správce breakpointů

Jakmile pojmenujete své breakpointy tak, jak chcete, budete potřebovat najít způsob, jak je používat v media queries. Je mnoho způsobů jak tak učinit, ale musím říci, že nejvíce fandím breakpointové mapě, kterou čtu pomocí getter funkce. Tento způsob je zároveň jednoduchý a efektivní.

/// Responsive breakpoint manager
/// @access public
/// @param {String} $breakpoint - Breakpoint
/// @requires $breakpoints
@mixin respond-to($breakpoint) {
  $raw-query: map-get($breakpoints, $breakpoint);

  @if $raw-query {
    $query: if(
      type-of($raw-query) == 'string',
      unquote($raw-query),
      inspect($raw-query)
    );

    @media #{$query} {
      @content;
    }
  } @else {
    @error 'No value found for `#{$breakpoint}`. '
         + 'Please make sure it is defined in `$breakpoints` map.';
  }
}
/// Responsive breakpoint manager
/// @access public
/// @param {String} $breakpoint - Breakpoint
/// @requires $breakpoints
=respond-to($breakpoint)
  $raw-query: map-get($breakpoints, $breakpoint)

  @if $raw-query
    $query: if(type-of($raw-query) == 'string', unquote($raw-query), inspect($raw-query))

    @media #{$query}
      @content

  @else
    @error 'No value found for `#{$breakpoint}`. '
         + 'Please make sure it is defined in `$breakpoints` map.'

Je zřejmé, že je to poměrně zjednodušující řešení pro správu breakpointů. Pokud potřebujete něco tolerantnějšího, doporučuji vám, abyste znovu nevynalézali kolo a použili něco co bylo ověřeno jako efektivní, právě jako Sass-MQ, Breakpoint nebo include-media.

Další četba

Použití Media Queries

Ne tak dávno probíhala poměrně vzrušující debata o tom, kde by se měla media queries psát: patří do selektorů (jak to umožňuje Sass) nebo by se měly psát striktně mimo ně? Musím uznat, že jsem vášnivým zastáncem systému media-queries-v-selektorech a myslím si, že to funguje skvěle s ideou komponent.

.foo {
  color: red;

  @include respond-to('medium') {
    color: blue;
  }
}
.foo
  color: red

  +respond-to('medium')
    color: blue

Což vede k následujícímu CSS výstupu:

.foo {
  color: red;
}

@media (min-width: 800px) {
  .foo {
    color: blue;
  }
}

Mohli jste slyšet, že tato konvence vede k duplikování media queries v CSS výstupu. A je to rozhodně pravda. I když byl udělán test a finální verdikt je, že na tom nezáleží jakmile Gzip (nebo něco podobného) dokončí svou věc:

… probírali jsme, zda existují problémy s výkonem v porovnání kombinování vs rozházení Media Queries a dospěli jsme k závěru, že v nejhorším případě sice ano, ale v nejlepším případě v podstatě vůbec ne.
Sam Richards, ohledně Breakpoint

Pokud máte obavu ohledně duplicitních media queries, pořád můžete použít nástroj, který je spojí k sobě, jako například tento gem, každopádně vás musím varovat, že pokud přesunete CSS někam jinam, může to mít negativní účinky. Nikdy nevíte, jestli je pořadí důležité.

Další četba

Proměnné

Proměnné jsou esencí každého programovacího jazyka. Díky nim můžeme znovu použít hodnoty místo jejich kopírování znovu a znovu. Ale hlavně se díky nim dá jednoduše aktualizovat hodnota. Už žádné další find and replace nebo ruční procházení.

Každopádně CSS není nic jiného než velký koš obsahující všechny naše vejce. Oproti většině jazyků, v CSS nenajdete žádné pravé scopy.

Moje rada proto je taková, abyste proměnné vytvářeli jen když to dává smysl. Neberte to na lehkou váhu, protože to vám v ničem nepomůže. Nová proměnná by se měla vytvářet pouze pokud se splňují následující kritéria:

  • hodnota se opakuje minimálně dvakrát;
  • hodnota by se mohla alespoň jednou aktualizovat;
  • všechny shody výskytu hodnoty jsou vázané s proměnnou (tedy nejsou to náhody).

V podstatě deklarovat proměnnou, která se nikdy nebude aktualizovat nebo je použita pouze na jednom místě, nemá žádný význam.

Scopování

Scopování proměnné v Sassu se během let změnilo. Donedávna byla deklarace proměnné spolu se styly a dalšími skopy lokální již v základu. Každopádně když tu byla již ta samá globální proměnná se stejným názvem, lokální přirovnání mohlo změnit globální proměnnou. Od verze 3.4 Sass řeší koncept scopů správně a vytváří namísto toho novou lokální proměnnou.

V dokumentaci se hovoří o stínování globální proměnné. Pokud deklarujete proměnnou, která již existuje, v globálním scopu v vnitřním prostoru (selektor, funkce, mixin…), lokální proměnná stíňuje tu globální. V podstatě ji přepíše jen pro daný scope.

Následující útržka kódu vysvětluje koncept stíňování proměnné.

// Initialize a global variable at root level.
$variable: 'initial value';

// Create a mixin that overrides that global variable.
@mixin global-variable-overriding {
  $variable: 'mixin value' !global;
}

.local-scope::before {
  // Create a local variable that shadows the global one.
  $variable: 'local value';

  // Include the mixin: it overrides the global variable.
  @include global-variable-overriding;

  // Print the variable’s value.
  // It is the **local** one, since it shadows the global one.
  content: $variable;
}

// Print the variable in another selector that does no shadowing.
// It is the **global** one, as expected.
.other-local-scope::before {
  content: $variable;
}
// Initialize a global variable at root level.
$variable: 'initial value'

// Create a mixin that overrides that global variable.
@mixin global-variable-overriding
  $variable: 'mixin value' !global

.local-scope::before
  // Create a local variable that shadows the global one.
  $variable: 'local value'

  // Include the mixin: it overrides the global variable.
  +global-variable-overriding

  // Print the variable’s value.
  // It is the **local** one, since it shadows the global one.
  content: $variable

// Print the variable in another selector that does no shadowing.
// It is the **global** one, as expected.
.other-local-scope::before
  content: $variable

značka !default

Pokud vytváříte knihovnu, framework, grid systém nebo jakoukoli jinou část Sassu, která se bude zveřenovat a používat externími vývojáři, všechny konfigurační proměnné by měly být označeny značkou !default, takže budou moci být přepsány.

$baseline: 1em !default;
$baseline: 1em !default

Díky tomu může vývojář definovat vlastní $baseline proměnnou před importováním vaší knihovny a neuvidí svou proměnnou přepsanou.

// Developer’s own variable
$baseline: 2em;

// Your library declaring `$baseline`
@import 'your-library';

// $baseline == 2em;
// Developer’s own variable
$baseline: 2em

// Your library declaring `$baseline`
@import your-library

// $baseline == 2em

značka !global

Značka !global by se měla používat pro přepisování globálních proměnných z lokálního scopu. Pokud definujete proměnnou v kořenové úrovni, značka !global by se však měla vynechat.

// Yep
$baseline: 2em;

// Nope
$baseline: 2em !global;
// Yep
$baseline: 2em

// Nope
$baseline: 2em !global

Více proměnných nebo mapy

Používání map spíše než více proměnných má několik výhod. Největší výhoda je možnost provést smyčku nad mapou, což s rozdílnými proměnnými nelze.

Další plus pro používání map je možnost vytvořit malou getter funkci pro přátelštější API. Zvažte například následující Sass kód:

/// Z-indexes map, gathering all Z layers of the application
/// @access private
/// @type Map
/// @prop {String} key - Layer’s name
/// @prop {Number} value - Z value mapped to the key
$z-indexes: (
  'modal': 5000,
  'dropdown': 4000,
  'default': 1,
  'below': -1,
);

/// Get a z-index value from a layer name
/// @access public
/// @param {String} $layer - Layer’s name
/// @return {Number}
/// @require $z-indexes
@function z($layer) {
  @return map-get($z-indexes, $layer);
}
/// Z-indexes map, gathering all Z layers of the application
/// @access private
/// @type Map
/// @prop {String} key - Layer’s name
/// @prop {Number} value - Z value mapped to the key
$z-indexes: ('modal': 5000, 'dropdown': 4000, 'default': 1, 'below': -1,)

/// Get a z-index value from a layer name
/// @access public
/// @param {String} $layer - Layer’s name
/// @return {Number}
/// @require $z-indexes
@function z($layer)
  @return map-get($z-indexes, $layer)

Extend

Direktiva @extend je právě jedna z funkcí Sassu, co jej udělalo tak populárním již několik let zpátky. Jen připomenu, že to umožňuje říci Sassu, aby nastyloval element A tak, aby to odpovídalo selektoru B. Netřeba asi dodávat, že tato funkce může ztratit svou hodnotu, pokud píšete modulární CSS.

Každopádně mám pocit, že vás musím před touto funkcí varovat. Stejně tak, jak je to chytré, tak je @extend stále ošemetný koncept, který by mohl udělat více škody, než-li užitku, zvláště když se špatně použije. Věc se má tak, že když extendujete selektor, nemůžete zodpovědět následující otázky bez toho, aniž byste měli nějakou hlubokou znalost celé codebase:

  • kde se můj aktuální selektor připojí?
  • mohu způsobovat nežádoucí efekty?
  • jak velké CSS vyjde z tohoto jednoho extendu?

Všichni víte, že výsledek se může pohybovat od ‘nic to nedělá’ až po katastrofální vedlejší účinky. A právě proto je moje první rada vyhnout se nadobro @extend direktivě. Může to znít brutálně, ale na konci dne to může ušetřit nějaké ty bolesti hlavy a potíže.

Jak již bylo řečeno, znáte rčení:

Nikdy neříkej nikdy.
— Zřejmě ne Beyonce.

Samozřejmě existují případy, kde by extendování selektorů mohlo být k užitku, přesto ale vždy mějte na paměti tyto pravidla, abyste se nedostali do potíží:

  • Použijte extend z modulu, ne napříč různými moduly.
  • Použijte extend na samostatné placeholdery, nikoli na skutečné selektory.
  • Ujistěte se, že placeholder, který extendujete, je ve stylech přítomný co možná nejméně.

Pokud se rozhodnete použít extend, dovolte mi připomenout, že si to moc dobře nerozumí s @media bloky. Jak asi víte, Sass není schopen extendnout vnější selektor z media query. Pokud tak učiníte, kompilátor se jednoduše zhroutí a řekne vám, že takovéto věci nemůžete dělat. Nic moc, zejména proto, že media queries téměř všichni známe.

%button {
  display: inline-block;
  // … button styles

  // Relationship: a %button that is a child of a %modal
  %modal > & {
    display: block;
  }
}

.button {
  @extend %button;
}

// Yep
.modal {
  @extend %modal;
}

// Nope
.modal {
  @extend %modal;

  > .button {
    @extend %button;
  }
}
%button
  display: inline-block
  // … button styles

  // Relationship: a %button that is a child of a %modal
  %modal > &
    display: block

.button
  @extend %button

// Yep
.modal
  @extend %modal

// Nope
.modal
  @extend %modal

  > .button
    @extend %button

Nemůžete použít @extend z vnějšího selektoru v rámci @media.
Můžete použít pouze @extend selektory v rámci stejné direktivy.

Často se říká, že @extend pomáhá s velikostí souboru, jelikož kombinuje selektory a neduplikuje vlastnosti. To je sice pravda, nicméně jakmile použijete Gzip, který provede svou kompresi, rozdíl je zanedbatelný.

Jak bylo řečeno, pokud nemůžete použít Gzip (nebo nic ekvivalentního), pak používání @extend přístupu nemusí být až tak špatné, dokud však víte, co děláte.

Abych to shrnul, nedoporučoval bych používat @extend direktivu, mimo nějaké specifické okolnosti, ale nezajdu až tak daleko, abych ji úplně zakázal.

Další četba

Mixiny

Mixiny jsou jednou z nejvíce používaných funkcí celého Sassu. Jsou klíčem pro znovupoužitelnost a DRY komponenty. A to z dobrých důvodů: mixiny dovolují autorům definovat styly, které mohou být použity napříč styly bez potřeby využívat nesémantické třídy jako .float-left.

Mohou obsahovat všechny CSS pravidla a v podstatě cokoliv, co je dovoleno používat kdekoli jinde v Sassu. Dokonce mohou přijímat argumenty, přesně jako funkce. Netřeba říkat, že možností je nekonečno.

Ale mám pocit, že vás musím varovat před zneužitím moci mixinů. Opět platí, že klíčové slovo je jednoduchost. Mohli byste se zlákat vytvořit extrémně mocné mixiny s velkým množstvím logiky. Tomu se říká přeinženýrování a trpí tím většina vývojářů. Nepřeceňujte svůj kód a držte jej především jednoduchý. Pokud skončíte s mixinem, který má více než 20 řádků, nebo tak nějak, pak by měl být rozdělen na menší části nebo zcela přepracován.

Základy

Jak již bylo řečeno, mixiny jsou extrémně užitečné a měli byste nějaké používat. Pokud je nějaká skupina vlastností, které se z nějakého důvodu zobrazují spolu (a není to tedy náhoda), můžete si je dát do mixinu. Například micro-clearfix hack od Nicolase Gallaghera si zaslouží být vložen do mixinu.

/// Helper to clear inner floats
/// @author Nicolas Gallagher
/// @link http://nicolasgallagher.com/micro-clearfix-hack/ Micro Clearfix
@mixin clearfix {
  &::after {
    content: '';
    display: table;
    clear: both;
  }
}
/// Helper to clear inner floats
/// @author Nicolas Gallagher
/// @link http://nicolasgallagher.com/micro-clearfix-hack/ Micro Clearfix
@mixin clearfix
  &::after
    content: ''
    display: table
    clear: both

Dalším příkladem může být mixin pro nastavení velikosti elementu, který bude definovat with a height ve stejném okamžiku. Nejenom, že by bylo psát kód jednodušší, ale také by se lépe četl.

/// Helper to size an element
/// @author Hugo Giraudel
/// @param {Length} $width
/// @param {Length} $height
@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}
/// Helper to size an element
/// @author Hugo Giraudel
/// @param {Length} $width
/// @param {Length} $height
=size($width, $height: $width)
  width: $width
  height: $height
Další četba

Seznam argumentů

Pokud se máte v mixinu utkat s neznámým počtem argumentů, vždy použijte spíše arglist než-li seznam. O arglist můžete přemýšlet jako o 8. skrytém nezdokumentovaném data typu ze Sassu, který se implicitně používá při průchodu libovolného počtu argumentů mixinu nebo funkce, kde se využívá ....

@mixin shadows($shadows...) {
  // type-of($shadows) == 'arglist'
  // …
}
=shadows($shadows...)
  // type-of($shadows) == 'arglist'
  // 

Nyní, při vytváření mixinu, který akceptuje několik argumentů (tím myslím 3 a více), přemýšlejte dvakrát před jejich spojením do seznamu nebo mapy, jelikož si myslíte, že je bude jednodušší zpracovat, než s jeden po druhém.

Sass je vlastně pěkně chytrý, co se deklarace mixinů a funkcí týče. Tak moc, že vlastně můžete předat seznam nebo mapu jako arglist funckci/mixinu, a ten si to naparsuje jako sérii argumentů.

@mixin dummy($a, $b, $c) {
  // …
}

// Yep
@include dummy(true, 42, 'kittens');

// Yep but nope
$params: (true, 42, 'kittens');
$value: dummy(nth($params, 1), nth($params, 2), nth($params, 3));

// Yep
$params: (true, 42, 'kittens');
@include dummy($params...);

// Yep
$params: (
  'c': 'kittens',
  'a': true,
  'b': 42,
);
@include dummy($params...);
=dummy($a, $b, $c)
  // …

// Yep
+dummy(true, 42, 'kittens')

// Yep but nope
$params: (true, 42, 'kittens')
$value: dummy(nth($params, 1), nth($params, 2), nth($params, 3))

// Yep
$params: (true, 42, 'kittens')
+dummy($params...)

// Yep
$params: ('c': 'kittens', 'a': true, 'b': 42,)
+dummy($params...)
Další četba

Mixiny a vendor prefixy

Mohlo by být lákavé, udělat si vlastní mixin, který vám bude přidávat vendor prefixy pro nepodporovatelné, nebo částečně podporované, CSS vlastnosti. Ale to není to, co chceme. Za prvé, pokud můžete použít Autoprefixer, použijte Autoprefixer. Díky němu nebudete muset v Sassu psát přebyteční kód a ten bude vždy aktuální a vždy udělá lepší práci, než-li vaše prefixující věci.

Bohužel vždy není možné Autoprefixer použít. Pokud používáte Bourbon nebo Compass, asi již pravděpodobně víte, že oba mají kolekci mixinů, které se o vendor prefixy starají. Použijte je.

Pokud nemůžete použít Autoprefixer ani Bourbon nebo Compass, pak a jen tehdy můžete použít svůj vlastní mixin, který se s prefixováním CSS vlastností popere. Ale, prosím vás, nedělejte pro každou vlastnost svůj vlastní mixin, který ručně vypíše každý vendor.

// Nope
@mixin transform($value) {
  -webkit-transform: $value;
  -moz-transform: $value;
  transform: $value;
}
// Nope
=transform($value)
  -webkit-transform: $value
  -moz-transform: $value
  transform: $value

Udělejte to chytře.

/// Mixin helper to output vendor prefixes
/// @access public
/// @author HugoGiraudel
/// @param {String} $property - Unprefixed CSS property
/// @param {*} $value - Raw CSS value
/// @param {List} $prefixes - List of prefixes to output
@mixin prefix($property, $value, $prefixes: ()) {
  @each $prefix in $prefixes {
    -#{$prefix}-#{$property}: $value;
  }

  #{$property}: $value;
}
/// Mixin helper to output vendor prefixes
/// @access public
/// @author HugoGiraudel
/// @param {String} $property - Unprefixed CSS property
/// @param {*} $value - Raw CSS value
/// @param {List} $prefixes - List of prefixes to output
=prefix($property, $value, $prefixes: ())
  @each $prefix in $prefixes
    -#{$prefix}-#{$property}: $value

  #{$property}: $value

Použití takového mixinu pak bude velmi jednoduché:

.foo {
  @include prefix(transform, rotate(90deg), ('webkit', 'ms'));
}
.foo
  +prefix(transform, rotate(90deg), ('webkit', 'ms'))

Prosím, vemte na vědomí, že je to velmi špatné řešení. Například se to nemůže vypořádat se složitými polyfily, jako ty, co jsou potřeba pro Flexbox. V tomto případně by bylo použití Autoprefixeru daleko lepší řešení.

Další četba

Podmíněné příkazy

Pravděpodobně již víte, že Sass poskytuje podmíněné příkazy pomocí @if a @else direktiv. V běžných stylech nejsou podmíněné příkazy potřeba, ledaže máte střední až velmi komplexní řešení. Ve skutečnosti existují hlavně pro knihovny a frameworky.

Každopádně, pokud se někdy ocitnete v situaci, kdy je budete využívat, respektujte, prosím, následující zásady:

  • Žádné závorky, pokud nejsou nezbytné;
  • Vždy mějte prázdný řádek před @if;
  • Vždy ukončete řádek po otevírací závorce ({);
  • @else příkaz mějte na stejném řádku, jako předchozí uzavírací závorka (}).
  • Vždy mějte nový prázdný řádek za poslední uzavírací závorkou (}), pokud není na dalším řádku uzavírací závorka (}).
// Yep
@if $support-legacy {
  // …
} @else {
  // …
}

// Nope
@if ($support-legacy == true) {
  // …
}
@else {
  // …
}
// Yep
@if $support-legacy
  // …
@else
  // …

// Nope
@if ($support-legacy == true)
  // …
@else
  // 

Pokud testujete nepravdivé hodnoty, vždy použijte klíčové slovo not spíše než testování oproti false nebo null.

// Yep
@if not index($list, $item) {
  // …
}

// Nope
@if index($list, $item) == null {
  // …
}
// Yep
@if not index($list, $item)
  // …

// Nope
@if index($list, $item) == null
  // 

Vždy dávejte část s proměnnou na levou stranu příkazu a (ne)očekávaný výsledek na stranu pravou. Obrácené podmíněné příkazy jsou často obtížně čitelné, zvláště pro nezkušené vývojáře.

// Yep
@if $value == 42 {
  // …
}

// Nope
@if 42 == $value {
  // …
}
// Yep
@if $value == 42
  // …

// Nope
@if 42 == $value
  // 

Při použití podmíněného příkazu v rámci funkce pro vrácení rozdílného výsledku na základě nějaké podmínky se vždy ujistěte, že funkce obsahuje @return také mimo jakýkoliv podmíněný blok.

// Yep
@function dummy($condition) {
  @if $condition {
    @return true;
  }

  @return false;
}

// Nope
@function dummy($condition) {
  @if $condition {
    @return true;
  } @else {
    @return false;
  }
}
// Yep
@function dummy($condition)
  @if $condition
    @return true

  @return false;

// Nope
@function dummy($condition)
  @if $condition
    @return true
  @else
    @return false

Cykly

Protože Sass umožňuje komplexní datové struktury jako seznamy a mapy, není až takové překvapení, že také umožňuje tyto struktury procházet.

Každopádně, přítomnost cyklů obvykle implikuje středně složitou logiku, která do Sassu pravděpodobně nepatří. A tedy proto se před tím, než-li cyklus použijete, ujistěte, že dává smysl a opravdu řeší problém.

Each

Cyklus @each je definitivně nejpoužívanější z Sass cyklů. Poskytuje čisté API pro procházení seznamu nebo mapy.

@each $theme in $themes {
  .section-#{$theme} {
    background-color: map-get($colors, $theme);
  }
}
@each $theme in $themes
  .section-#{$theme}
    background-color: map-get($colors, $theme)

Pokud procházíte mapu, vždy používejte $key a $value jako jména proměnných, abyste zachovali konzistentnost.

@each $key, $value in $map {
  .section-#{$key} {
    background-color: $value;
  }
}
@each $key, $value in $map
  .section-#{$key}
    background-color: $value

Také se ujistěte, že dodržujete tyto pokyny, pro zachování čitelnosti:

  • Nový řádek vždy před @each;
  • Nový řádek vždy po ukončující závorce (}), tedy pokud další řádek není ukončující závorka (}).

For

Cyklus @for může být užitečný, pokud kombinujete CSS pseudo třídu :nth-*. Kromě tohoto případu preferujte spíše cyklus @each, pokud musíte něco procházet.

@for $i from 1 through 10 {
  .foo:nth-of-type(#{$i}) {
    border-color: hsl($i * 36, 50%, 50%);
  }
}
@for $i from 1 through 10
  .foo:nth-of-type(#{$i})
    border-color: hsl($i * 36, 50%, 50%)

Vždy používejte $i jako jméno proměnné, abyste se drželi obecné konvence, tedy pokud nemáte jiný dobrý důvod proč tak neučinit. Nikdy nepoužívejte klíčové slovo to, vždy používejte through. Mnoho vývojářů ani neví, že Sass má tuto možnost a používání může vést k záměně.

Také respektujte tyto pokyny pro zachování čitelnosti:

  • Nový řádek vždy před @for;
  • Nový řádek vždy po ukončující závorce (}), tedy pokud další řádek není ukončující závorka (}).

While

Cyklus @while nemá v Sassu absolutně žádné reálné použití, zvláště když tu není žádná možnost, jak breaknout cyklus zevnitř. Nepoužívejte ho.

Varování a chyby

Pokud bych měl vybrat jednu funkci, která je často Sass vývojáři přehlížena, je to nepochybně možnost dynamického výstupu chyb a varování. Sass obsahuje tři vlastní direktivy pro výpis obsahu ve standardním výstupu systému (CLI, kompilování applikace…), což může být pro někoho překvapením.

  • @debug;
  • @warn;
  • @error.

Pojďme dát @debug stranou, protože je jasně určená pro ladění SassScriptu, což nás teď nezajímá. Zbyly nám tedy @warn a @error, které jsou shodné až na to, že jedna zastavuje kompilátor, zatímco druhá ne. Schválně hádejte, která je která.

V Sass projektu je nespočet využití pro varování a chyby. V podstatě každý mixin nebo funkce očekávající specifický typ argumentu může vyhazovat chyby, pokud se něco pokazí, nebo zobrazit varování, pokud je pro chybu předpoklad.

Další četba

Varování

Vezměte si tuto funkci z Sass-MQ, která se pokouší převést px hodnotu na em hodnotu, například:

@function mq-px2em($px, $base-font-size: $mq-base-font-size) {
  @if unitless($px) {
    @warn 'Assuming #{$px} to be in pixels, attempting to convert it into pixels.';
    @return mq-px2em($px + 0px);
  } @else if unit($px) == em {
    @return $px;
  }

  @return ($px / $base-font-size) * 1em;
}
@function mq-px2em($px, $base-font-size: $mq-base-font-size)
  @if unitless($px)
    @warn 'Assuming #{$px} to be in pixels, attempting to convert it into pixels.'
    @return mq-px2em($px + 0px)
  @else if unit($px) == em
    @return $px

  @return ($px / $base-font-size) * 1em

Pokud je hodnota bezjednotková, funkce předpokládá, že je hodnota vyjádřena pixely. Na tomto místě může být předpoklad riskantní, a proto by měl být uživatel varován, že software provedl něco, co by mohlo být považováno za neočekávané.

Chyby

Chyby, oproti varováním, zabraňují kompilátoru běžet dále. V podstatě zastaví kompilaci a zobrazí zprávu ve výstupním proudu, stejně jako trasování zásobníku, což je užitečné pro debugování. Kvůli tomu by chyby měly vyhodit výjimku, pokud není žádná možnost jak program udržet v chodu. Pokud je to možné, snažte se s problémem pracovat a namísto toho zobrazit varování.

Například pojďme říci, že vytváříte getter funkci pro přístup k hodnotám ze specifické mapy. Můžete vyhodit error, pokud v mapě není požadovaný klíč.

/// Z-indexes map, gathering all Z layers of the application
/// @access private
/// @type Map
/// @prop {String} key - Layer’s name
/// @prop {Number} value - Z value mapped to the key
$z-indexes: (
  'modal': 5000,
  'dropdown': 4000,
  'default': 1,
  'below': -1,
);

/// Get a z-index value from a layer name
/// @access public
/// @param {String} $layer - Layer's name
/// @return {Number}
/// @require $z-indexes
@function z($layer) {
  @if not map-has-key($z-indexes, $layer) {
    @error 'There is no layer named `#{$layer}` in $z-indexes. '
         + 'Layer should be one of #{map-keys($z-indexes)}.';
  }

  @return map-get($z-indexes, $layer);
}
/// Z-indexes map, gathering all Z layers of the application
/// @access private
/// @type Map
/// @prop {String} key - Layer's name
/// @prop {Number} value - Z value mapped to the key
$z-indexes: ('modal': 5000, 'dropdown': 4000, 'default': 1, 'below': -1,)

/// Get a z-index value from a layer name
/// @access public
/// @param {String} $layer - Layer's name
/// @return {Number}
/// @require $z-indexes
@function z($layer)
  @if not map-has-key($z-indexes, $layer)
    @error 'There is no layer named `#{$layer}` in $z-indexes. '
         + 'Layer should be one of #{map-keys($z-indexes)}.'

  @return map-get($z-indexes, $layer)

Nástroje

Co je opravdu hezké na CSS preprocesoru tak populárním jako Sass je to, že přichází s celým ekosystémem frameworků, pluginů, knihoven a nástrojů. Po 8 letech existence se dostáváme blíže a blíže k bodu, kde všechno co může být napsané v Sassu, je napsané v Sassu.

Každopádně mojí radou je udržet počet závislostí na opravdové minimum. Spravování závislostí je tak trochu peklo, kterého nechcete být součástí. A navíc ani žádné externí závislosti nepotřebujete.

Compass

Compass je hlavní Sass framework široko daleko. Vyvíjen Chrisem Eppsteinem, jedním ze dvou hlavních designérů Sassu, a pokud chcete znát můj názor, nemyslím si, že by měl v nejbližší době dramaticky ztratit popularitu.

Já osobně Compass už nepoužívám a hlavním důvodem je právě to, že zpomaluje Sass, a to dost. Ruby Sass je docela pomalé samo o sobě a přidáním více Ruby a více Sassu tomu opravdu moc nepomáhá.

Věc se má tak, že používáme jen velmi málo z celého frameworku. Compass je obrovský. A mixiny na podporu různých prohlížečů jsou jen špičkou ledovce. Matematické funkce, helpery pro obrázky, sprity… Je toho tak moc, co se s tímto skvělým kusem softwaru dá udělat.

Bohužel, všechno je to jen cukříček a není tam žádná zabijácká funkce. Vyjímkou by mohla být udělena pro sprite builder, který je opravdu skvělý, ale Grunticon a Grumpicon dělají stejnou práci a mají výhodu, že mohou být připojeny v procesu sestavení.

Každopádně, používat Compass vám nezakazuji, i když bych jej ani nedoporučil, zvláště jelikož není kompatibilní s LibSass (i když v tomto směru bylo vyvinuto značné úsilí). Pokud máte pocit, že byste jej raději použili, proč ne, ale nemyslím si, že toho v konečném důsledku hodně získáte.

Ruby Sass v současné době prochází několika optimalizacemi, které jsou specificky zamířené na těžkou logiku s mnoha funkcemi a mixinami. Mělo by to dramaticky zlepšit výkon k takovému stavu, že by použití Compassu a dalších frameworků nemuselo Sass zpomalovat.

Další četba

Grid systém

Nepoužívat grid systém v dnešní době, kdy je všude Responzivní Web Design, prostě není možnost. Chcete-li, aby návrhy vypadaly konzistentně a pevně ve všech velikostech, použijte nějaký grid pro rozložení elementů. Abyste se vyhnuli nutnosti kódovat tento grid tak, aby fungoval, znovu a znovu dokola, a někteří chytráci dokonce udělali ty své znovupoužitelné.

Nechte mě to ujasnit: nejsem velký fanoušek grid systémů. Samozřejmě vidím jejich potenciál, ale myslím si, že většina z nich jsou totální přestřely a jsou spíše používány na kreslení červených sloupců na bílé pozadí hloupých prezentací designérů. Kdy naposledy jste si říkali děkuji-Bohu,-že-mám-tento-nástroj-pro-budování-2-5-3.1-π-gridu? No právě, nikdy, protože ve většině případů jste chtěli jen normální 12-sloupcový grid, prostě nic úchvatného.

Pokud ve svém projektu používáte CSS framework jako Bootstrap nebo Foundation, pak jsou šance, že již obsahují grid systém opravdu vysoké. V tomto případě bych vám doporučil, abyste jej využili, abyste se zbavili další závislosti.

Pokud nejste vázáni na konkrétní grid systém, budete rádi, že tu jsou dva prvotřídní Sass grid enginy: Susy a Singularity. Oba dělají trochu více, než budete kdy potřebovat, takže si můžete vybrat ten, který preferujete více a buďte si jisti, že všechny vaše krajní případy — dokonce i ty nejzáludnější — budou pokryty. Pokud se ptáte mě, Susy má o něco lepší komunitu, ale to je jen můj názor.

Nebo můžete jít do něčeho trochu více formálního, jako csswizardry-grids. Ať už si vyberete jak si vyberete, volba nebude mít na váš styl kódování téměř žádný dopad, takže je to jen na vás.

Další četba

SCSS-lint

Lintování kódu je velmi důležité. Obvykle dodržování pravidel z příručky pomáhá redukovat množství kódu, které snižuje kvalitu, ale nikdo není dokonalí a vždy jsou věci, které se dají vylepšit. Dá se říci, že lintování kódu je stejně tak důležité, jako komentování.

SCSS-lint je nástroj, který vám pomáhá udržovat SCSS soubory čisté a čitelné. Je plně přizpůsobitelný a jednoduchý na začlenění do vlastních nástrojů.

SCSS-lint doporučení jsou naštěstí velmi podobné k těm, které jsou popsány v tomto dokumentu. Chcete-li konfigurovat SCSS-link podle Sass Guidelines, doporučuji vám toto nastavení:

linters:

  BangFormat:
    enabled: true
    space_before_bang: true
    space_after_bang: false

  BemDepth:
    enabled: true
    max_elements: 1

  BorderZero:
    enabled: true
    convention: zero

  ChainedClasses:
    enabled: false

  ColorKeyword:
    enabled: true

  ColorVariable:
    enabled: false

  Comment:
    enabled: false

  DebugStatement:
    enabled: true

  DeclarationOrder:
    enabled: true

  DisableLinterReason:
    enabled: true

  DuplicateProperty:
    enabled: false

  ElsePlacement:
    enabled: true
    style: same_line

  EmptyLineBetweenBlocks:
    enabled: true
    ignore_single_line_blocks: true

  EmptyRule:
    enabled: true

  ExtendDirective:
    enabled: false

  FinalNewline:
    enabled: true
    present: true

  HexLength:
    enabled: true
    style: short

  HexNotation:
    enabled: true
    style: lowercase

  HexValidation:
    enabled: true

  IdSelector:
    enabled: true

  ImportantRule:
    enabled: false

  ImportPath:
    enabled: true
    leading_underscore: false
    filename_extension: false

  Indentation:
    enabled: true
    allow_non_nested_indentation: true
    character: space
    width: 2

  LeadingZero:
    enabled: true
    style: include_zero

  MergeableSelector:
    enabled: false
    force_nesting: false

  NameFormat:
    enabled: true
    convention: hyphenated_lowercase
    allow_leading_underscore: true

  NestingDepth:
    enabled: true
    max_depth: 1

  PlaceholderInExtend:
    enabled: true

  PrivateNamingConvention:
    enabled: true
    prefix: _

  PropertyCount:
    enabled: false

  PropertySortOrder:
    enabled: false

  PropertySpelling:
    enabled: true
    extra_properties: []

  PropertyUnits:
    enabled: false

  PseudoElement:
    enabled: true

  QualifyingElement:
    enabled: true
    allow_element_with_attribute: false
    allow_element_with_class: false
    allow_element_with_id: false

  SelectorDepth:
    enabled: true
    max_depth: 3

  SelectorFormat:
    enabled: true
    convention: hyphenated_lowercase
    class_convention: '^(?:u|is|has)\-[a-z][a-zA-Z0-9]*$|^(?!u|is|has)[a-zA-Z][a-zA-Z0-9]*(?:\-[a-z][a-zA-Z0-9]*)?(?:\-\-[a-z][a-zA-Z0-9]*)?$'

  Shorthand:
    enabled: true

  SingleLinePerProperty:
    enabled: true
    allow_single_line_rule_sets: false

  SingleLinePerSelector:
    enabled: true

  SpaceAfterComma:
    enabled: true

  SpaceAfterPropertyColon:
    enabled: true
    style: one_space

  SpaceAfterPropertyName:
    enabled: true

  SpaceAfterVariableColon:
    enabled: true
    style: at_least_one_space

  SpaceAfterVariableName:
    enabled: true

  SpaceAroundOperator:
    enabled: true
    style: one_space

  SpaceBeforeBrace:
    enabled: true
    style: space
    allow_single_line_padding: true

  SpaceBetweenParens:
    enabled: true
    spaces: 0

  StringQuotes:
    enabled: true
    style: single_quotes

  TrailingSemicolon:
    enabled: true

  TrailingZero:
    enabled: true

  TransitionAll:
    enabled: false

  UnnecessaryMantissa:
    enabled: true

  UnnecessaryParentReference:
    enabled: true

  UrlFormat:
    enabled: false

  UrlQuotes:
    enabled: true

  VariableForProperty:
    enabled: false

  VendorPrefixes:
    enabled: true
    identifier_list: base
    include: []
    exclude: []

  ZeroUnit:
    enabled: true

Pokud chcete SCSS lint začlenit do vašeho Grunt build procesu, budete rádi vědět, že pro to existuje Grunt plugin, který se nazývá grunt-scss-lint.

Stejně tak pokud hledáte elegantní aplikace, které pracují s SCSS-lintem a tak podobně, lidé z Thoughtbot (Bourbon, Neat…) pracují na Hound.

Další četba

TL;DR

Abych to shrnul, chceme:

  • Dvě (2) mezery pro odsazení, ne taby;
  • 80 znaků široké řádky;
  • Správně psané víceřádkové CSS;
  • Smysluplné užití whitespaců;
  • Řetězce a URL v jednoduchý uvozovkách;
  • Žádné koncové mezery, povinná 0 před desetinnou čárkou;
  • Nezobrazujte zbytečné 0, zobrazujte úvodní 0;
  • Výpočty zabalen v závorkách;
  • Žádné magické čísla;
  • Barvy vyjádřené v klíčových slovech > HSL > RGB > hexadecimálně;
  • Listy oddělené čárkami;
  • Nepoužívat koncové čárky v seznamech (jelikož jsou jednořádkové);
  • Koncová čárka v mapách;
  • Nenořte selektory vyjma pseudo tříd a pseudo elementů;
  • Čárkou-oddelené pojmenování;
  • Rozsáhlé komentáře;
  • Komentáře poháněné SassDoc API;
  • Omezené použití @extend;
  • Jednoduché mixiny;
  • Tak málo cyklů jak je možno, žádné @while;
  • Snížený počet závislostí;
  • Smysluplné použití varování a chyb.
Zpět na začátek