Styl, konwencje i struktura CSS. Sass, OOCSS, BEM, rscss, SMACSS, OMG?

css-sass-black

Poziom zaawansowany

Co to znaczy być zajętym? Ano na przykład nie mieć absolutnie czasu nawet na nowe posty na blogu, chociaż tematów jest cała rzeka. Tak oto byłem zajęty, zawodowo oraz prywatnie. Dziś wracamy „on-line” z tematem, i to nie byle jakim… Zyskiwać czas można poprzez optymalizację codziennych czynności, ich automatyzację i organizację. I zawsze staram się to krok po kroku wdrażać. Efekty widać gołym okiem – więcej czasu, mniejsze zmęczenie i frustracja.

W aspekcie programowania można by tutaj napisać o narzędziach, np. webpack. Ale temu poświęcimy oddzielne posty. Dziś skupimy się na podejściach do pisania stylów CSS w dobry, komfortowy dla nas (i dla innych) sposób, aby to co stworzymy było łatwe w utrzymaniu i rozbudowie.

„Long term value of the software is directly proportional to the quality of code base…”
— Douglus Crockford

Czy znacie style guides i konwencje CSS? Na przykład OOCSS, BEM, rscss, SMACSS. A może OMG? Być może stosujecie wybrane podejście do tworzenia CSS, być może jedynie obiło się o uszy, ale nie porwało Was na tyle, aby to zastosować. A może widzieliście już przykłady CSS w tutorialach napisane z użyciem BEMa czy innego SMACSSa, ale nie zwracaliście uwagi na takie detale. Ten artykuł bierze pod lupę właśnie podejścia o pisania CSS, organizacji plików, nazywania klas CSS, itp. Team jest obszerny i wyjdzie poza jeden artykuł.

Notka: jako że od dawna piszę style prawie wyłącznie przy użyciu Sass (SCSS – Syntactically Awesome Style Sheets), również artykuły i przykłady kodów odnosić się będą do tego preprocesora CSS, zwanego też „CSS with superpowers” 🙂 Poświęcimy mu oddzielny artykuł, póki co można zerknąć na oficjalną stronę: http://sass-lang.com po więcej informacji.

Wydawnictwo Strefa Kursów

Pracę z Sass można zacząć (kto jeszcze tego nie zrobił) szybko i przyjemnie. Nie trzeba nawet tracić zbytnio czasu na narzędzia i konfiguracje – web framework, którego używacie prawdopodobnie wspiera Sass. Sam pracuję głównie w Ruby on Rails (RoR) oraz node.js, gdzie nie ma żadnych z tym problemów.

Co do style giude, to jeśli chodzi o JavaScript / ES6, moim ulubionym jest ten opracowany przez Airbnb:

https://github.com/airbnb/javascript

To samo dotyczy podejścia do pisania (S)CSS:

https://github.com/airbnb/css

Dla wybranych składni możemy sobie zainstalować i skonfigurować odpowiedni linting.

UWAGA: mam jedno zastrzeżenie do rekomendacji Airbnb, co do letter case dla bloków. Nie przepadam za PascalCase / camelCase, zwłaszcza we front-end development. Oczywiście np. w Ruby / RoR (które uwielbiam) używamy PascalCase dla nazw klas i snake_case dla nazw metod, gdzie wygląda to świetnie. Po prostu jakoś tak… bardzo pasuje akurat tak, a nie inaczej.

W przypadku CSS zdecydowanie preferuję kebab-case (spinal-case, hyphen delimited, https://en.wikipedia.org/wiki/Letter_case#Special_case_styles), stąd też nie piszę żadnych:

.pageHead {}
.sub_header {}
...

tylko:

.page-head {}
.sub-header {}
...

Oczywiście jest to tylko moja własna preferencja.

Tak naprawdę podejść i konwencji, zarówno dla JS i CSS, jest cała masa. My powinniśmy oczywiście używać takiej, która jest rozsądna, spójna ORAZ komfortowa dla nas. Jeśli nie mamy własnego, „lepszego” zbioru zasad, skorzystajmy z jednego z dostępnych. Mój wybór to konwencje od inżynierów Airbnb. I jak widzimy, w przypadku przewodnika dla CSS, również tam pojawia się rekomendacja używania BEM i/lub OOCSS. Tym będziemy się zajmować. Tak naprawdę… ważne jest nie tyle jakie konwencje wybieramy (… niby dlaczego A jest lepsze od B? może dla mnie, ale nie koniecznie dla Ciebie …). Ważne jest, aby trzymać się wybranych konwencji konsekwentnie. Wtedy naprawdę skorzystamy, w przeciwnym razie prędzej czy później powstanie niepotrzebny bałagan.

Zacznijmy jednak od kilku słów na temat Sass / SCSS, oraz przede wszystkim, od struktury plików dla naszych stylów.

„Writing CSS is easy. Writing maintainable CSS is hard.”

Dlaczego to wszystko ma znaczenie? OK, sam nie lubię tego „Overengineering’u”, który zdaje się być typowy dla środowiska programistów front-end. Stąd mamy miliardy narzędzi, bibliotek, approaches i „racji” co do pisania kodów JS i CSS. Niektórzy programiści niestety zdają również być, delikatnie mówiąc, dziwni, próbując narzucać jakieś podejście jako „jedyne słuszne”.

Bzdury… Niektórzy są irytująco leniwi, jako że problemem zdaje się dla nich stawianie średnika na końcu linijki. Albo problem „czy muszę uczyć się PHP lub innego języka, skoro znam JS”… nie ma to jak pasja do programowania, co? 🙂

OK, ja uczyłem się języków jeden po drugim, i nigdy nie widziałem w tym problemu (ale może jestem już dinozaurem 🙂 ?). Trochę też trwało, zanim znalazłem „swoje miejsce” w programowaniu. Dziś jest inaczej, dziś jest znacznie prościej. Wszystko mamy podane na tacy, dostęp do rozwiązań i wiedzy. Mamy na tacy wręcz za dużo, dlatego trzeba wybrać coś dla siebie.

Wiadomo że zawodowo używa się kilku języków i narzędzi, cała reszta może być for fun, czy dla pasji. Może też przydać się np. do rozwoju jakiegoś projektu open source, bądź poratować nas, gdy kiedyś okaże się, że potrzebny nam większy skill. W końcu ta branża jest dynamiczna jak chyba żadna inna.

Co więc z tymi średnikami? Helloooł, a programowałeś w czymkolwiek innym? Ja uwielbiam Język Ruby i jego konwencję. No i brak średników. Jednak co do JS i CSS, to przez wszystkie lata przywykłem do średników na końcu. Zwyczajnie. I Innych detali, jak wcięcia, itp. Wiem kiedy kod wygląda dla mnie dobrze, a kiedy nie…

Ktoś w swoich projektach jak najbardziej może używać .sass zamiast .scss lub Standard JS zamiast Airbnb JS. Grunt żeby było komfortowo i praktycznie. Oraz spójnie. Dla mnie komfortowo i praktycznie jest tak, a nie inaczej, stąd też trzymam się konwencji Airbnb dla JS, oraz preferuję składnię .scss ponad .sass. Jeśli pokażę jednak przykłady kodu według moich ulubionych konwencji, NIE powinno być żadnego problemu dla innych, aby szybko zaadaptować je do używanych przez siebie podejść. Dla prawdziwego programisty takie detale to małe piwo.

Wspominam o tym, ponieważ warto być elastycznym i adaptować się. Szczególnie w teamie. A ja pracując przez lata w różnych team’ach i projektach, po prostu musiałem „wskoczyć” w sposób programowania teamu, zamiast próbować go zmieniać – na siłę, a już na pewno nie hejtować.

Dobre, uzasadnione zmiany są zwykle mile widziane. Ale przebudowa ponad połowy kodu dla samej sztuki, albo czyjegoś wyznania… „a bo w ostatnią sobotę oglądałem video-tutorial z hiper fajnym, trendy podejściem – musimy przerobić nasz kod, będzie fajniejszy i łatwiejszy w utrzymaniu”. Hola, a czy obecny kod nie jest?

Cóż… Sam nienawidzę rozwiązań, które zdają się jedynie tworzyć problemy, ale je rozwiązać, lub takich, które rozwiązują jeden „problem”, ale w jego miejsce przynoszą 10 innych… Takich „cudów” unikamy, sięgamy po sensowne, faktycznie potrzebne rozwiązania, które przynoszą realne korzyści i dają udogodnienia.

Tak czy inaczej, warto szukać sposobności do pójścia naprzód, zamiast wymówek. Rozwijajmy się, śledźmy nowe trendy i budujmy nowoczesne oprogramowanie. Dobry, czysty i spójny kod, który nie będzie przestarzały za 5 minut. W nowoczesnych podejściach fajne jest to, że znacznie łatwiej niż kiedyś możemy aktualizować nasze rozwiązania do nowszych wersji.

Ale na tym dość już filozofii, nie chcę wchodzić w te tematy rzeki. Do dzieła!

Składnia Sass vs SCSS

Sass to świetna sprawa. Daje nam mixiny, zmienne i inne udogodnienia pozwalające pisać dobry kod szybciej. Mamy do wyboru składnię Sass (stosujemy dla niej pliki z rozszerzeniem .sass) oraz SCSS (pliki .scss). Jak wspomniałem wyżej, zdecydowanie wolę w tym przypadku składnię SCSS i używam jej na co dzień. Innym może pasować z kolei składnia Sass i to jest jak najbardziej w porządku. Przynajmniej dopóki nie narzuca mi tej składni, bądź nie marnuje cennego czasu na debatowanie o wyższości jednej na drugą… Zdecydowanie wolę produkować – realizować pracę i projekt, zamiast zatapiać się w bezsensownych dyskusjach, o kwestiach tak naprawdę kosmetycznych.

Jak by nie było, warto znać obie składnie, są one oczywiście podobne, z pewnymi różnicami. Znając jedną praktycznie znamy też od ręki drugą 🙂 Przykład poniżej.

Składnia .sass

.block  // no opening curly-bracket
  font-size: 1em  // no semi-colons
  color: $text-color
  border: 1px solid $border-color
  // no closing curly-bracket, idents

Składnia .scss

.block {              // opening curly-bracket
  font-size: 1em;     // semi-colons separating declarations
  color: $text-color;
  border: 1px solid $border-color;
}                     // closing curly-bracket

Czyli brak nawiasów klamrowych, średników, oraz wcięcia (o które musimy dba w .sass) vs nawiasy klamrowe i średniki. Dla

Przy okazji jeszcze kilka słów o nested styles i operatorze &. Od wersji 3.3 Sass daje nam możliwość nie tylko zagnieżdżania, ale i użycia selector reference (&) do generowania bardziej zaawansowanych selektorów. Przykład:

#main {
  color: #000;
  &-sidebar { 
    border: 1px solid; 
  }
}

Sass skompiluje to do takiej postaci:

#main {
  color: #000;
}

#main-sidebar {
  border: 1px solid; 
}

Sass zadba o odpowiedni CSS wynikowy dla przeglądarek. Nasz kod w źródłach z kolei będzie ładnie pogrupowany i przejrzysty (o ile poznamy te podstawowe konstrukcje Sass).

Powyższe podejście jest bardzo pomocne w pisaniu stylów w konwencjach takich jak BEM. Po co nam ten BEM? Ta (bądź inne konwencje / metodologie) przydają się przy budowie większych projektów. Gdy nasz kod urośnie, szybko możemy docenić podejście tego typu. Więcej o BEM w kolejnej części, ale już w tej dotkniemy innych metodologii (OOCSS).

Przykład – kod SCSS + BEM:

// Block (B)
.project-deadline {
  // Block element (E)
  &__date {
    color: $color-red;
  }

  // Block element (E)
  &__header {
    font-weight: 700;
  }

  // ...

  // Block modifier (M)
  &--highlight {
    color: $color-green;
  }

  // ... 
}

Zostaną utworzone klasy CSS:

– .project-deadline__date

– .project-deadline__header

– .project-deadline–highlight

Co do samych styleguides, to zyskują one na popularności w społecznościach programistów. I bardzo dobrze. Projekty oraz teamy się rozrastają, ale żaden problem, gdy korzystamy z określonego styleguide. Dostępnego i znanego powszechnie, lub opracowanego wewnętrznie w teamie (ale może warto się podzielić ze społecznością? :-)).

Spójność i określone standardy co do składni i formatowania, wcięć, struktury plików i folderów, nazewnictwa, zmiennych (a nawet stałych), grupowania, itd, czynią po prostu łatwiejszym życie nasze i nowych członków teamu.

Sass i struktura plików oraz folderów naszego projektu

Do rzeczy. Nasz kod będzie rósł, warto więc sensownie go pogrupować. Skorzystamy z partiali – skoro Sass nam je daje – korzystajmy. Sam stosuję i polecam wzorzec „7-1”, opisany np. tutaj:

https://sass-guidelin.es

Generalnie rozdzielmy nasze partiale w folderach, według rodzaju. Mamy 7 różnych folderów (typów) oraz jeden plik główny (root level, zwykle main.scss lub manifest.scss, …). Plik ten importuje partiale których potrzebujemy, udostępniając w wynikowym pliku style, które w nich stworzyliśmy.

W nietrywialnych projektach sprawdzi się taka struktura. Warto spróbować. Przykład poniżej:

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

W tego typu strukturze możemy ułożyć nasze pliki. BTW – przykład na GitHubie:

https://github.com/HugoGiraudel/sass-boilerplate/tree/master/stylesheets

Uwaga: folder „abstracts” zależnie od naszych preferencji, możemy również nazwać „utilities”.

Pozostaje jeszcze plik główny, w którym importujemy nasze partiale. Może on wyglądać tak:

@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';

A tutaj przykład a projektu (bazującego na RoR):

Sample files structure (in Rails 5.1 based project)

Sample files structure (in Rails 5.1 based project)

Mam nadzieję że przyda się również w Waszych projektach. Warto oczywiście popatrzeć na inne architektury:

https://www.sitepoint.com/look-different-sass-architectures

Polecam poczytać również:

http://sass-lang.com/guide

https://sass-guidelin.es

http://sass-lang.com/documentation/file.SASS_REFERENCE.html

https://www.sitepoint.com/sass-mixin-placeholder


Pora na dalsze kroki. W tej części zaczniemy od konwencji znanych z OOCSS.

Metodologie CSS: OOCSS

Można powiedzieć że metodyka dość wiekowa. Sam jej nie preferuję (ogólnie wolę BEM), choć używałem jej w jednym z projektów jakiś czas temu. Moim zdaniem dość prosto jest zacząć korzystać z tej metodyki. Możliwe że nasz obecny projekt mniej lub bardziej podąża zalecaniami tej metodyki, więc nie trudno będzie zaadaptować ją w naszym kodzie.

OOCSS czyli Object Oriented CSS inspirowany jest metodykami programowania obiektowego. Podobnie jak w OOP, dąży się do re-używalności kodu CSS. Do grupowania go w twory przypominające „obiekty”. Łatwe w użyciu w różnych miejscach aplikacji WWW.

W tym podejściu wyróżnia się nawet pojęcie „obiektu” rozumianego jako kawałek kodu HTML (grupa elementów bądź pojedynczy element), wraz z odpowiadającymi mu klasami CSS. Prosty formularz szukania (search box) czy też zapisania do newslettera, mogą być przykładem obiektu. Żeby metodyka „działała” jak należy, powinniśmy myśleć w kategoriach OOCSS, zwłaszcza pamiętając o regułach:

A. Separacja struktury od stylu (separate structure and skin)

B. Separacja kontenerów i zawartości (separate container and content)

W kwestii reguły A, chodzi generalnie o tworzenie wpierw klas bardziej globalnych, które definiują ogólną strukturę obiektów danego rodzaju, a następnie klas bardziej szczegółowych (wyspecjalizowanych), które odpowiadają za specyficzny styl obiektu, również w zależności od sytuacji (wariantu).

W kwestii reguły B, możemy pomyśleć o „niezależności” obiektu. Według OOCSS obiekt powinien wyglądać tak samo, niezależnie w jakim kontenerze go umieściliśmy.

Przyjęcie konwencji OOCSS oddala nas od pisania „kodu spaghetti”. Koncentruje się na elastycznych, modularnych, łatwo wymienialnych komponentach.

Przykład – separate structure and skin:

Tak NIE robimy:

.button-1 {
  width: 100px;
  height: 25px;
  background: #fff;
  border-radius: 5px;
}

Tak robimy:

.button-1 {
  width: 100px;
  height: 25px;
}

.skin-1 {
    background: #fff;
    border-radius: 5px;
}

Użycie:

<a class="button-1 skin-1" href="#">Test</a>

Przykład – separate container and content

Tak NIE robimy:

#sidebar .list .list-body {
  font-size: 13px;
  color: #fff;
  background-color: #d00;
  // dalsze style ...
  ...
}

Tak robimy:

.sidebar {
  padding: 2px;
  left: 0;
  margin: 3px;
  position: absolute;
  width: 130px;
}

.list {
  margin: 3px;
}

.list-header {
  font-size: 16px;
  color: #d00;
}

.list-body {
  font-size: 13px;
  color: #fff;
  background-color: #d00;
}

...

W podobny sposób możemy tworzyć dalsze style, np.:

– .btn {} // struktura
– .btn-blue {} // skin

oraz warianty np. różne „skiny” czyli wygląd. Dobrym pomysłem jest również a także odseparowanie elementów według rozmiaru:

– .btn-small {} // mały przycisk
– .btn-medium {} // średni przycisk

i inne warianty dla naszych „obiektów”.

Z Sass jeszcze łatwiej

Ten prosty przykład pokazuje skorzystanie z cech Sass do pisania schludnego OOCSS.

Wpierw definiujemy placeholder’y, pamiętając o zasadach OOCSS:

%button {
  min-width: 130px;
  padding: 1.1em;
  border-radius: 1.2em;
}

%twitter-bg {
  color: #fff;
  background: #55acee;
}

%facebook-bg {
  color: #fff;
  background: #3b5998;
}

Następnie używamy ich poprzez metodę extend (https://sass-guidelin.es/#extend):

.btn {
  &--twitter {
    @extend %button;
    @extend %twitter-bg;
  }
  &--facebook {
    @extend %button;
    @extend %facebook-bg;
  }
}

To wszystko:

<a href="#" class="btn--twitter">Twitter</a>
<a href="#" class="btn--facebook">Facebook</a>

Nie chodzi więc o żadną czarną magię. Chodzi o sensową organizację stylów dla określonych elementów strony, podobnie jak rozważamy obiekty pisząc kod OO.

Jako programista który latami pisał kod OOP, można powiedzieć że przez jakiś czas (mniej lub bardziej świadomie) stosowałem pewne reguły OOCSS podczas pisania kodów frontendu. Później zacząłem interesować się również innymi podejściami. OOCSS powiem szczerze, jest OK ale jak dla mnie, chyba troszkę zbyt old-schoolowy. I nie wiem jak dobrze grał by w naprawdę dużym projekcie.

W przez jakiś czas stosowałem metodologię RSCSS (https://github.com/rstacruz/rscss), jednak nie do końca spełniła ona moje oczekiwania. Jak dotąd BEM „współpracuje” najlepiej, choć ewidentnie czasem mega długie nazwy klas mogą zacząć być męczące. Ale o tym już w kolejnym artykule.

Zasoby

http://helion.pl/view/8448w/sasspp.htm

https://nafrontendzie.pl/metodyki-css-1-oocss

https://www.keycdn.com/blog/oocss

https://toddmotto.com/getting-started-with-object-orientated-css-oocss-creating-a-button-kit

http://www.nicoespeon.com/en/2013/05/dive-into-oocss

https://www.smashingmagazine.com/2011/12/an-introduction-to-object-oriented-css-oocss

http://saddamazad.com/2015/12/object-oriented-css-with-sass

Styl, konwencje i struktura CSS – podsumowanie

Koniec części 1 mini-cyklu o metodykach CSS. I tak postał spory artykuł. Mamy tu trochę mojego lania wody na wstępie, ale dalej już bardziej konkretnie. Mam nadzieję że przyda się opis struktury plików i folderów, jakim możemy się posłużyć organizując pliki w naszych projektach. Mamy też overview OOCSS oraz zasoby.

Jak widać OOCSS to całkiem proste reguły. Wprowadzenie tej metodyki wymaga jednak trochę pracy na początku, a także przestawienia programistów na odpowiedni sposób myślenia. Trzeba mieć też na uwadze, że różne konwencje / metodologie nie są dokładnie tym samym (pokrywają mniej lub bardziej pewne aspekty organizacji i pisania kodu).

A przy okazji nadmienię, że stworzyłem projekt własnej metodologii, jako że wszystkie z dostępnych obok swoich zalet, zawsze mają jakieś mniejsze bądź większe wady. Oczywiście wady te mogą dawać się we znaki dopiero po jakimś czasie (w większym projekcie). Moja konwencja to coś bardzo wygodnego, czerpiącego z dobrych cech RSCSS, BEM, oraz szczypty OOCSS moich własnych „przypraw” 🙂 Aktualnie pracuję nad bardzo dużym projektem, rozpocząłem programowanie frontu, i właśnie coś takiego może być najlepszym wyjściem (jeśli BEM da się we znaki :-)). Póki co – eksperymentuję, jeśli jednak zdecyduję się na opracowanie własnej konwencji, opublikuję ją oczywiście na Githubie i opiszę na blogu.

Zapraszam także do cz. 2:

http://javascript-html5-tutorial.pl/styl-konwencje-i-metodologie-css-czesc-2-sass-bem-rscss-smacss-wtf.html

Elo!

Programista WWW i aplikacji mobilnych z wieloletnim doświadczeniem. Bloger 🙂 Anty-lewak 🙂 Pasjonat programowania, nowych technologii, a także sportu i motoryzacji.

Twitter LinkedIn Google+ Skype Xing 

Podaj dalej: Share on Facebook1Tweet about this on TwitterShare on Google+0Share on LinkedIn0Share on Tumblr0Digg thisEmail this to someonePin on Pinterest0
Możesz skomentować leave a response, lub podać trackback z własnej strony.
  • CeLeS

    „// Block (B)
    .project-deadline {
    // Block element (E)
    &__date {
    color: $color-red;
    }

    // Block element (E)
    &__header {
    font-weight: 700;
    }

    // …

    // Block modifier (M)
    &–highlight {
    color: $color-green;
    }

    // …
    }”

    Nie powstanie jak wspomniana w teksie klasa – .project-deadline__header–highlight