Zásady psaní respektujícího CSS

Naposledy upraveno: 3. 6. 2018 – Autor: Martin Michálek

Pište kód jednotně a hlavně tak, aby se dobře četl jiným nebo třeba vám samotným za rok. Počítejte s tím, že lidé umí CSS. To ostatní není jisté. Pište proto CSS kód a moc si jej neupravujte. Respektujte vlastnosti lidí i CSS.

Obsah

Tyhle zásady psaní vycházejí z OOCSS, BEM a dalších přístupů a nástrojů.

Předpoklady

  • Design vašeho projektu je vymyšlený komponentově a systematicky, ideálně podle principů atomického designu. Výjimky jsou možné, ale nesmí být moc časté.
  • Píšete čisté nebo preprocesorové CSS, nikoliv CSS v JS.
  • Styly nezapisujete výlučně pomocí užitkových tříd.

Doporučené nástroje

  • Píšeme čisté CSS nebo pomocí preprocesorů. Doporučuji dnes převládající Sass v konvenční SCSS syntaxi, protože je totožná se způsobem zápisu v CSS.
  • Kód zpracovává postprocesor (PostCSS) a sestavovací nástroje (Grunt, Gulp). Díky tomu můžeme automaticky dělat různé hacky v kódu, které není pěkné dávat do čteného kódu: Například minifikaci nebo přidávání prefixů.
  • Při kompilaci nastavujeme Source Maps, abychom v prohlížeči viděli napojení na zdrojové soubory.
  • Pro sjednocení nastavení editorů používáme EditorConfig.
  • Prettier nám automaticky opravuje formátování v kódu ještě před commitem.
  • Pro kontrolu psaní používáme Stylelint, nejlépe v mé výchozí konfiguraci.

1) Obecná pravidla

1.1) CSS píšeme s respektem k vlastnostem jazyka

Bereme ohled na kaskádu, hlavně specifičnost a pořadí selektorů, a také na globální povahu jazyka.

// Cilem je, aby vsechny nadpisy mely velikost 1.25rem
// a varianta pouzivana v .box pak velikost 1.5rem.

// Spatne:

// Nedrzime specificitu nizko a nemame spravne
// poradi, proto nas zachrani jen !important

.heading--large {
  font-size: 1.5rem !important;
}

.box h2 {
  font-size: 1.25rem;
}

// Dobre:

.heading {
  font-size: 1.25rem;
}

.heading--large {
  font-size: 1.5rem;
}

1.2) Nevytváříme zbytečně konstrukce neobsažené v CSS

Pokud to není nezbytně nutné nebo to výrazně nepomáhá čitelnosti kódu, netvoříme proprietární funkce v preprocesorech. CSS umí číst všichni, na rozdíl od specifických konstrukcí. V deklarativní části píšeme jednoduchý kód co nejvíce podobný běžnému CSS.

// Dobre:

.box {
  font-size: 1.25rem;
  line-height: 1.4;
}

// Spatne:

.box {
  @include fs-lh(1.25rem, 1.4);  // Mixin neznameho obsahu
}

Jsou ale samozřejmě opodstatněná použití mixinů – v „programátorské“ části kódu. Například při generování mřížky layoutu, animací a dalších extrémně se opakujících částí stylů.

2) Soubory a struktura

2.1) Kód rozdělujeme do malých souborů

Jeden problém řeší jeden soubor. Vyhýbáme se souborům míchajícím více komponent, funkcí nebo o délce větší než 200 řádků kódu.

2.2) Soubory umísťujeme do adresářů podle kategorií, v nichž specificita roste a počet dotčených HTML elementů se snižuje

Tipy pro metody organizace: jednoduché projekty. Složitější podle ITCSS.

// Dobre:

@import "base/blanka.scss";
@import "base/typography.scss";

@import "components/box-variables.scss";
@import "components/box.scss";
@import "components/heading.scss";

@import "utilities/margins-paddings.scss";

Další doporučení:

  1. V adresáři se zdrojovým CSS máme jeden hlavní soubor. Všechny ostatní jsou v adresářích. Víme tak, který otevřít jako první. Doporučuji jej pojmenovat index.scss.
  2. Atomické soubory sestavovacím nástrojem skládáme do větších kvůli efektivitě při rychlosti načítání.
  3. Pokud to váš sestavovací nebo kompilační nástroj umí, využijte automatické importování souborů z adresáře: @import "utitities/*".

3) Psaní komponent

3.1) OOCSS: používáme objektový zápis

Držíme se hlavních pravidel:

  1. CSS není závislé na struktuře HTML.
  2. Specifičnost selektorů držíme co nejníže.
  3. Komponenta nesmí být závislá na rodiči.
  4. Všechny prvky komponenty prefixujeme jejím názvem.

Vyhneme se tak možným problémům s kolizí komponent nebo jejich částí. Více je v textu o OOCSS.

// Spatne:

.page-cart .box ul > li { … }

// Dobre:

.box-item-small { … }

3.2) BEM: pojmenováním odlišujeme bloky, elementy a modifikátory

Pomůže nám to jednoznačně určit typ třídy už z HTML nebo dokumentace. Více je v textu o BEM.

// Spatne:

<div class="side-bar side-bar-left">
  <div class="box box-with-heading side-bar-inner">

// Dobre:

<div class="side-bar side-bar--left">
  <div class="box box--with-heading side-bar__inner">

Další doporučení:

  1. Nepojmenováváme komponenty nebo funkce zkratkami. My si je možná zapamatujeme, ale situaci zase zkomplikujeme ostatním.
  2. Kód složitějších komponent dělíme na deklarativní (CSS) a programátorský (imperativní, konstrukce preprocesorů): například proměnné (box-variables.scss), lokální mixiny (box-mixins.scss) a nakonec samotný CSS kód importující uvedené (box.scss). To vše samozřejmě jen za podmínky, že si to složitost kódu komponenty vyžádá.
  3. Vycházíme ze vzorové šablony SCSS souboru. Strukturu souboru děláme zjevnější pomocí Markdown nadpisů, pokud to vyžaduje. Do hlavičky přidáváme odkaz na dokumentaci. Pod hlavičkou souboru máme strukturu komponenty pro snadnější vstřebání složitějších celků. Části komponent drží pořadí podle metodiky BEM.
  4. BEM komponenty lintujeme pomocí selector-bem-pattern, pluginu do Stylelintu.

4) Psaní kódu v deklaracích

4.1) Základní formát psaní podle Prettier

Základní formát psaní přebíráme od Prettier. Například:

  1. Odsazujeme dvěma mezerami.
    Takové odsazení se totiž vykresluje stejně ve všech editorech.
  2. Každý selektor v deklaraci patří na vlastní řádku.
  3. Mezi deklaracemi je vždy jeden volný řádek.
  4. Za čárkami v hodnotách bude vždy mezera.
  5. Desetinné hodnoty mají na začátku vždy nulu.
    Píše se to tak v prostředí běžného psaní. Vyhýbáme tak také silně nepřirozeným konstrukcím jakko -.25rem.
  6. Jednotlivé deklarace a zavináčová pravidla oddělujeme v kódu volným řádkem.

Prettier máme nainstalovaný tak, aby nám všechny prohřešky rovnou sám opravoval ještě před odesláním do repozitáře.

4.2) Pokročilejší formát kódu hlídá Stylelint

Stylelint používáme v této konfiguraci. Příklady nastavení:

  1. Nejvyšší úroveň zanoření deklarace je 1.
  2. Všechny barvy v hexa tvaru musejí být uvedené malými písmeny, lidem se lépe čtou.
  3. Nejsou povoleny vendor prefixy.
  4. Nejvyšší povolená specificita je 0,3,0 – tři třídy.
  5. Nejsou povoleny id selektory (např. #container).
  6. V hodnotách funkcí, deklarací písem, vlastnosti content nebo selektorech se vždy používají dvojité uvozovky.
    V principu je sice možné na většině míst uvozovky nepoužívat, jenže ve výjimečných situacích jsou vyžadovány: například u selektorů podle atributu (a[href^=http://] nefunguje) nebo definici formátu písma (format(woff) také nefunguje).

4.3) Vlastní hodnoty zobecňujeme co nejvíce, pravidla nebo selektory co nejméně

Zobecňování do lokálních a globálních proměnných je správné:

// Spatne:

.box {
  @include f-s(1.25); // Tezko rict, co se pod tim skryva
  color: #edef33;  // Proc zrovna tato barva?
  @media (min-width: 320px) { … } // Proc zrovna tento breakpoint?
}

// Dobre:

.box {
  font-size: 1.25rem;
  color: $color-primary;
  @media (min-width: #{$media-small}) { … }
}

Další doporučení:

  1. Pokročilé vlastnosti preprocesorů jako @extend nebo placeholdery pokud možno vůbec nepoužíváme. Obvykle dělají více škody než užitku. Mění například pořadí v kódu a podobně jako mixiny vytvářejí abstrakci v kódu specifickou pro náš projekt.
  2. Mixiny používáme jen pokud jsou nezbytně nutné pro pochopení kódu nebo odstranění extrémního opakování deklarací. Třeba pro generování mřížky layoutu nebo u složitějších animací. Nikdy je nevytváříme pro zrychlení zápisu základních CSS vlastností. K tomu slouží editory nebo nástroj Emmet.
  3. Direktivy @include dáváme na začátek deklarací, jsou důležité.

4.3) Šetříme se zanořováním

  1. Nezanořujeme do vyšší než druhé úrovně.
  2. Povoleno je jen zanoření pro následníky BEM komponenty a v druhé úrovni pro pseudotřídy nebo Media Queries.
  3. Ampersandové (&__element) zanoření v selektorech pro vyšší než druhou úroveň nepoužíváme. Komplikuje nalezení správného selektoru a kodér ztrácí jistotu nad názvem a specificitou selektoru, který vytváří.
  4. Vyhýbáme se dlouhým zanořeným deklaracím – monolitům.
// Spatne:

.box {
  border: 1px solid $border-color;

  &__heading {
    font-size: $font-size-lg;

    @media #{$media-xs} {
      &--large {
        font-size: $font-size-md;
      }
    }
  }
}  

// Dobre:

.box {
  border: 1px solid $border-color;
}  

.box__heading {
  font-size: $font-size-lg;
}

.box__heading--large {
  @media #{$media-xs} {
    font-size: $font-size-md;
  }  
}

4.4) Kód píšeme podle specifikace, hacky automatizujeme

Kód píšeme vždy podle specifikací W3.org. Části, které potřebujeme pro ošetření specifických prohlížečů, automatizujeme. Například vendor prefixy přidáváme Autoprefixerem.

Další doporučení:

  1. Pořadí pravidel: U složitějších deklarací dáváme důležité vlastnosti na první místo: pozicování, box model a pak teprve ostatní pravidla.
  2. Matematické výrazy zapisujeme vždy v závorkách a s mezerami uvnitř. Např. margin-top: (2 * $gutter);.

5) Komentáře

5.1) Pokud je to potřeba k pochopení důvodu a kontextu, vždy ke kódu píšeme komentář

V jiných jazycích je potřeba okomentovat důvod, v CSS ještě kontext. Někdy má na prohlíženou část vliv předcházející kód. Jindy prohlížená část ovlivňuje následující. Více je v praktické ukázce v článku.

// Dobre:

.box {
  // Pro potreby absolutne pozicovanych komponent
  // jako .icon a .badge: 
  position: relative;
}

Další doporučení:

  1. Ponecháváme šířku řádky pro komentáře na maximu 80 znacích, aby se to dobře četlo.
  2. Komentáře v kódu píšeme raději anglicky. Nikdy totiž nevíme, kdo do projektu nastoupí po nás. Pokud vybereme češtinu, píšeme raději bez diakritiky. Velká část česko-slovenských vývojářů používá anglickou klávesnici.
  3. Standardně používáme tiché, preprocesorové komentáře (// comment). CSS komentáře (/* comment */) jen v hlavičkách souborů kvůli snadnějšímu dohledání v neminifikovaných souborech.
  4. Pro výraznější oddělení částí souborů používáme strukturální komentáře vycházející z Markdown nadpisů. Vzor.
  5. Pokud používáme // TODO komentáře, vždy vysvětlíme důvodu. Nenahrazujeme jimi úkoly ze systému úkolů.
  6. U složitějších komentářů používáme referenci na ovlivněný kód. Ukázka.

To je vše, děkuji za pozornost a respektujte prosím povahu CSS.


  • Verze: 1.6
  • Autor: Martin Michálek
  • Zdroj: rcss-zasady.md
  • Náměty na doplnění, diskuze a pull requesty jsou vítány
  • Stejně jako další obsah ze Vzhůru dolů jej můžete upravit a využít pro vlastní účely s podmínkou dodržení licence

Komentáře