HTML5 & CSS3

Block, Element, Modifier w CSS

Block, Element, ModifierMiałeś kiedyś taką sytuację, że pod koniec dużego projektu sam nie mogłeś połapać się we własnym kodzie? A może jesteś częścią większego zespołu i często nie wiesz dlaczego Twoi koledzy tworzą takie dziwaczne konstrukcje w arkuszach? Witaj w klubie! Każdy frontendowiec miał coś takiego. Można powiedzieć, że to niestety część zawodu, ale nie martw się bo są sposoby na to by radzić sobie z takimi problemami. Jednym z rozwiązań jest BEM, czyli Block, Element, Modifier – metodologia tworzenia kodu wypracowana przez Yandex po to by ułatwić deweloperom życie.

Założenia

BEM to sposób myślenia o tworzeniu aplikacji webowych. Ten sposób myślenia przekłada się na techniki frontendowe, które pozwalają na szybsze tworzenie stron, którymi łatwiej zarządzać. BEM w swoich założeniach podobny jest do OOP, gdyż również dąży do tego by w pewien uniwersalny sposób opisywać kodem realia świata.

Fundamentalnym elementem tegoż sposobu opisywania jest podział tworzonej strony na pewne konstrukcyjne części. Przykład poniżej:

Webroad.pl - podział elementów na stronie 

Jak widać łatwo możemy odnależć części strony, które są fundamentem jej konstrukcji. Mamy nagłówek, bloki po bokach (które zresztą składają się na boczne bloki w postaci kolumny tzw. sidebary), główną kolumnę i kafelki reklamujące najnowsze artykuły.

Podstawowym elementem budowy strony jest Blok, który może być prosty lub złożony (jeśli w jego skład wchodzą inne bloki). Bloki składają się z  elementów, czyli części, które spełniają jakieś określone funkcje. Bardzo ważnym jest aby bloki były od siebie niezależne nawet do tego stopnia, że swobodnie można zagnieżdżać jeden w drugim lub wyciągać jeden zagnieżdżony w innym bloku i przenieść w zupełnie inne miejsce strony.

Poniżej możecie zobaczyć przykład dwóch elementów (zielona ramka) wewnątrz bloku:

Webroad.pl - przykłady elementów BEM

Aby móc się posługiwać blokami i ich elementami musimy się jakoś do nich odnosić. W tym celu nadajemy im unikalną nazwę, która identyfikuje blok w strukturze strony i element w ramach danego bloku.

To co opisaliśmy do tej pory ma znaczenie uniwersalne i może odnosić się do pliku XML stworzonego na podstawie metodologii BEM jak i do naszego arkusza stylów. Teraz skupimy się na CSS.

BEM vs. CSS

Jeśli chcemy używać BEM do pisania arkuszy stylów musimy pamiętać o kilku rzeczach:

  • Każdemu blokowi i/lub elementowi musimy nadać unikalną nazwę (w tym wypadku chodzi o klasę CSS)
  • Nie możemy stosować selektorów elementu HTML
  • Wystrzegamy się stosowania selektorów opartych o zasadę kaskadowości (selektory potomka)
  • Nie używamy selektorów id

Samo stosowanie BEM w praktyce nie jest trudne i odpowiada schematowi opisanemu wyżej. Zobaczmy przykład:

<form class="contact">
...
</form>

Powyższy formularz to nasz blok, który może być częścią składową jakiegoś section, czy jakiejkolowiek innej części strony (tym się teraz nie przejmujemy).

Wewnątrz bloku znajdują się elementy, których nazwy tworzymy przez dodanie nazwy elementu do nazwy bloku. Taka konstrukcja sprzyja minimalizowaniu kontekstowości i kaskadowości.

<form class="contact">

<input type="text" class="contact_input"/>

<input type="email" class="contact_input"/>

</form>

Konwencja tworzenia nazw może być różna. Ważne aby stosować jedną przez całość arkusza.

Modyfikatory

Czasami będziemy musieli zastosować zmiany w naszym bloku lub elemencie, gdyż tego będzie wymagał od nas zamierzony projekt wyglądu strony, czy aplikacji. Dlatego w BEM wymyślono modyfikatory, które pozwalają na to by móc wprowadzać zmiany w blokach i elementach bez łamania zasad BEM.

<form class="contact">

<input type="text" class="contact_input contact_input--name"/>

<input type="email" class="contact_input"/>

</form>

Właściwie to modyfikatory są kolejnym elementem konwencji nazewniczej BEM. Są to klasy, które tworzymy po to aby zmienić właściwiości wyświetlanych elementów HTML.

W powyższym przykładzie zastosowaliśmy modyfikację elementu contact_input. W tym celu stworzyliśmy po prostu nową klasę o nazwie contact_input–name. Nie dość, że od razu widzimy do czego odnosi się modyfikator to od razu wiemy też, że mamy do czynienia z modyfikatorem.

Elementy można też modyfikować przez dodanie modyfikatora do bloku i zapisanie CSS tak aby w tym przypadku elementy danego bloku zmieniały swoje wartości lub zyskiwały nowe właściwości.

<form class="contact contact--footer">

<input type="text" class="contact_input"/>

<input type="email" class="contact_input"/>

</form>

Do powyższego kodu HTML należy dopisać odpowiednią deklarację w CSS:

.contact--footer contact_input {
border:2px solid #fff;
}

W ten sposób w bloku o modyfikatorze contact–footer zmieniamy wszystkie elementy contact_input.

Jeśli chcemy modyfikować blok powinniśmy po prostu stworzyć w tym celu odpowiednią klasę modyfikatora:

.contact--footer {
display:inline-block;
}

Wtedy formularze o klasie contact, które dodatkowo otrzymają modyfikator contact–footer wyświetlane będą z wartością i właściwością display:inline-block.

Analogicznie jak w przypadku elementów, bloki, które same są zagnieżdżone w innych blokach też mogły by być modyfikowane przez modyfikator (klasę) dodawaną do bloku „rodzica”. Jeden problem jaki jest z takim sposobem związany to to, że przy szerokim stosowaniu wracamy do kontekstowości, której BEM stara się wystrzegać. Jednak z drugiej strony nie dajmy się ześwirować…

Podsumowanie

BEM to bardzo przydatny sposób myślenia o konstrukcji stron internetowych i warstwy front end aplikacji webowych. W zakresie CSS i HTML pozwala on na pisanie bardziej przejrzystych i czytelnych arkuszy stylów, które są łatwiejsze w utrzymaniu.

Pamiętajmy jednak, że BEM to też znacznie więcej niż CSS i HTML – to cały sposób myślenia o aplikacjach internetowych związany chociażby z konstrukcją templatek widoków. Temat jest szeroki i zainteresowanych jego zgłębieniem zapraszam na stronę BEM – bem.info.

Zdjęcie pochodzi z: bem.info

Tagi:CSS3promowanytutorial

komentarze 32

  • Awatar
    Comandeer

    19 kwietnia 2014 21:20

    W przypadku BEM warto podać kilka przykładów wykorzystania in wild:
    – SUIT: https://github.com/suitcss/suit
    – Inuit.css: https://github.com/csswizardry/inuit.css

    BEM to po prostu kolejna warstwa abstrakcji… niepotrzebna w przypadku mniejszych projektów.

    Odpowiedz
    • Awatar
      Michał Załęcki

      19 kwietnia 2014 22:26

      BEM nawet w mniejszych projektach rozwiązuje Ci przynajmniej jeden duży problem, mianowicie, wprowadzanie zmian w już istniejącym projekcie np. po pół, po roku. Patrzysz na selektor i wiesz dokładnie o jaki button czy tabelę chodzi bez zaglądania do źródła. Warto stosować tym bardziej, że nie wymaga to jakiejś dodatkowej pracy.

      Odpowiedz
      • Awatar
        Comandeer

        19 kwietnia 2014 22:30

        .menu w małym projekcie raczej też jest jednoznaczne ;)
        W mniejszych projektach BEM wymaga _o wiele_ więcej pracy, bo tam często wystarczy zastosować prostą kaskadowość i hierarchię elementów. Nie wydaje mi się, żeby potrzebne było w nich całkowite oddzielenie wyglądu przez spłaszczenie hierarchii i przerzucenie wszystkiego na klasy.

        Odpowiedz
      • Awatar
        Michał Załęcki

        19 kwietnia 2014 22:38

        .menu, ok. Ale jak mam np. .twiter-timeline to nie wiem czy chodzi o jakiś większy wrapper czy już iframe. A .wrapper–twitter i .twitter już rozwiewają wątpliwości.

        Prawda jest taka, że w naprawdę małych projektach można by pakować CSS liniowo, bo czemu nie? Zadzała? Tak, a że kod wygląda jak wygląda… użytkownika i tak to nic nie obchodzi. Problematyczne robi się dopiero wprowadzanie zmian w takim „potworku”.

        Odpowiedz
      • Awatar
        Comandeer

        19 kwietnia 2014 22:42

        Ale przecież to jest bez znaczenia czy używam BEM, czy nie. Jak se debilnie nazwę klasę to jest to moja wina. W BEM też można nadawać oderwane od rzeczywistości nazwy bloków.

        Co do liniowego CSS-a: na produkcji przecież winien taki być ;) Ale nikt nie edytuje takich potworków, bo trzyma na gicie/SVN-ie wersję developerską, gdzie wszystko jest podzielone tak, jak webmaster lubi.

        Odpowiedz
      • Awatar
        Michał Załęcki

        19 kwietnia 2014 22:46

        Pisząc liniowo miałem na myśli w atrybutach :D
        http://www.w3.org/TR/html401/present/styles.html#h-14.2.2

        Odpowiedz
      • Awatar
        Comandeer

        19 kwietnia 2014 22:47

        Ekhm, to już po prostu webmaster wystawia świadectwo o sobie ;)

        Odpowiedz
      • Awatar
        Michał Załęcki

        19 kwietnia 2014 22:53

        No cóż, medalu raczej za to nie dostanie :)

        Wracaj do BEM to jest to kwestia preferencji. Nie powiemy, że „ta strona jest za mała na BEM, powinieneś to zrobić inaczej”, jasne, że coś takiego: .button–big-red-with-black-icon-and-bright-blue-text jest co najmniej nietrafionym pomysłem (abstrahując do wątpliwych walorów estetycznych).

        Odpowiedz
      • Awatar
        Comandeer

        19 kwietnia 2014 22:55

        Ja po prostu nie widzę sensu w takim pisaniu małych stron. Przykładem może być moja domowa: szybciej mi tak naprawdę przyjdzie przepisanie stylów na nowo niźli ich modyfikacja. No i strona jest podzielona aż na 4 części: nagłówek, menu, treść i stopkę. Tak prosta struktura, że nawet nie ma po co wprowadzać .site-header, .site-header__logo itd.

        Odpowiedz
      • Awatar
        Mr.Mr

        19 kwietnia 2014 23:42

        Myślę, że w przypadku małych projektów sensowność jest dyskusyjna, ale mocne argumenty są zarówno za jak i przeciw. Osobiście skłonił bym się jednak ku sugestii Michała. Zawsze w przypadku rozbudowy witryny można łatwiej zacząć z BEM jeśli już taką konwencję nazewniczą stosujemy.

        Odpowiedz
      • Awatar
        Comandeer

        20 kwietnia 2014 11:11

        To zależy jak definiujemy mały projekt. Dla mnie nie ma sensu brudzić kodu HTML klasami gdy mamy 2 rodzaje list na stronie i można je rozróżnić całkowicie po kontekście ich wystąpienia. Nie ma po prostu potrzeby wprowadzania dodatkowej warstwy abstrakcji. W utrzymaniu tego kodu nic to nie pomoże.

        Odpowiedz
      • Awatar
        Mr.Mr

        20 kwietnia 2014 12:18

        Ja nadal mam dziwne wrażenie, że masz rację i zarazem jej nie masz (tzn. nie do końca). Osobiście wolałbym wprowadzić klasy bo z doświadczenia wiem, że projekty lubią się rozszerzać ;) więc wolałbym sobie na przyszłość oszczędzić przepisywania kodu.

        Odpowiedz
      • Awatar
        Comandeer

        21 kwietnia 2014 14:56

        Jeszcze raz powrócę do mojej strony domowej: czy odniosę jakąś korzyść z zastosowania BEM? Nie, bo kod strony jest po prostu za mały. Przez zastosowanie BEM do stylowania stworzyłbym dwukrotnie większy kod i nie podniósłbym czytelności tego kodu.
        .nav li raczej nagle się nie rozrośnie do .nav li cośtam i nie widzę po prostu sensu w dostawianiu .nav, .nav-item.
        Jeśli nie ma potrzeby tworzyć nadmiarowego kodu, to się go nie tworzy. Co innego jeśli np piszemy framework – wówczas winien być elastyczny i tutaj się BEM sprawdza (oczywiście zawsze w połączeniu z OOCSS)

        Odpowiedz
      • Awatar
        Michał Kortas

        21 kwietnia 2014 16:59

        Uważam, że każdy zna swoje potrzeby i każdy może sobie samemu wyznaczyć prywatną granicę pomiędzy prostą stroną, która nie potrzebuje super-hiper-ekstra dodatków do jej tworzenia oraz taką, gdzie korzystanie ze wspomagaczy jest wręcz niezwykle przydatne. Osobiście nie użyłbym BEM przy budowie mikro stronki informacyjnej. Jak to się mówi? Nadgorliwość jest gorsza od faszyzmu? ;)

        Odpowiedz
      • Awatar
        Michał Załęcki

        21 kwietnia 2014 19:00

        …a lepsze jest wrogiem dobrego :)

        Odpowiedz
      • Awatar
        Mr.Mr

        19 lipca 2014 12:40

        W kwestii BEM vs. małe projekty – http://www.smashingmagazine.com/2014/07/17/bem-methodology-for-small-projects/

        Artykuł średni, mało konkretów i IMO właściwie brak odpowiedzi na podstawowe pytania… ale jest to jakiś głoś w dyskusji, więc postanowiłem wkleić.

        Odpowiedz
      • Awatar
        Mr.Mr

        22 kwietnia 2014 08:43

        I Ty przeciwko Nam? :) IMO można sobie na BEM pozwolić zawsze. To już kwestia oceny webmastera.

        Odpowiedz
      • Awatar
        Michał Kortas

        22 kwietnia 2014 08:58

        Hahaha :) Właśnie to napisałem – to już kwestia oceny każdego projektu z osobna.

        Odpowiedz
    • Awatar
      Comandeer

      17 lutego 2016 13:42

      Aleś Ty głupi, Comandeer… Oczywiście, że BEM przydaje się nawet w mniejszych projektach! Popatrz na swoją własną stronę WWW i na problemy ze specyficznością, na które się tam nadziewasz! Weź to przepisz na BEM i miej wreszcie spokój…

      Odpowiedz
  • Awatar
    Piotr Nalepa

    20 kwietnia 2014 09:42

    Z własnego doświadczenia wiem, że BEM się nie sprawdza przy naprawdę dużych, skomplikowanych stronach. Wprowadza to za dużo zamieszania. Lepiej stosować OOCSS. Jest prościej i przyjemniej. I dzięki stosowaniu inteligentnego nazewnictwa unikamy makaronizmów.

    Odpowiedz
    • Awatar
      Michał Załęcki

      20 kwietnia 2014 10:53

      Przy dużych projektach nie wyobrażam sobie niekorzystania z np. SASS, gdzie możemy rozszerzać/dziedziczyć selektory. Nic nie stoi na przeszkodzie połączenia BEM i OOCSS. Otrzymamy bardziej przejrzysty HTML kosztem trochę większego pliku CSS. Warto dodać, że w takim rozwiązaniu nie będziemy musieli powracać do kodu HTML, a jedynie usuniemy lub dodamy kilka dyrektyw @extend. Szczególnie przydatne okaże się to gdy frontendowiec nie ma dostępu, bądź jest on ograniczony, do kodu który „wypluwa” kod HTML.

      Odpowiedz
      • Awatar
        Piotr Nalepa

        20 kwietnia 2014 18:29

        Akurat ja sobie to wyobrażam, bo miałem okazję pracować przy dużym projekcie bez SASS i LESS. Zarządzanie zależnościami między kawałkami kodu może doprowadzić większą ekipę developerów do bałaganu. Co innego jak skład liczy 2-3 osoby, a co innego gdy ma 30 osób.

        Odpowiedz
  • Awatar
    Sebastian Żebrowski

    20 kwietnia 2014 09:51

    Jedna mała uwaga, Wasz blog czytają również początkujący webmasterzy, nie do końca mam pojęcie o tym, co piszecie ;) Przydałaby się jakiś krótki video tutorial, jakieś przykłady stron oparte na BEM.

    Odpowiedz
    • Awatar
      Michał Załęcki

      20 kwietnia 2014 10:46

      Dziękujemy za sugestię. Przykładem strony, która korzysta z BEM jest dobrze znany blog http://csswizardry.com/

      Odpowiedz
      • Awatar
        Sebastian Żebrowski

        20 kwietnia 2014 13:18

        Czytałem ten artykuł, jest dobry, ale mógłby być lepszy np. ID jest be – suchy tekst, żadnego przykładu. Przekazujecie dużo wiedzy – teoria, a najlepiej uczyć się na praktyce ;) Ponadto używacie takich słów jak „refaktoryzacja kodu” – co to znaczy? Fajnie by było zrobić jakaś legendę, bądź dodać „title”.

        EDIT:

        Może zapoczątkujecie jakąś serie artykułów o frameworkach (Jak ich używać w praktyce)?

        Odpowiedz
      • Awatar
        Mr.Mr

        20 kwietnia 2014 13:54

        Hmm… ale sprawa z ID sprowadza się do tego, że nie powinno się go używać (co do zasady – w komentarzach do tego artykułu temat jest rozwinięty trochę o niuanse).

        Odpowiedz
      • Awatar
        Sebastian Żebrowski

        20 kwietnia 2014 14:00

        Ok, ale teorie zawsze powinniście jakimś przykładem poprzeć. Ja przez całą edukację mam teorie, jedyna praktyka przez te lata to miesiąc w serwisie komputerowym.

        Odpowiedz
    • Awatar
      Mr.Mr

      20 kwietnia 2014 12:21

      BEM w zakresie CSS jest dość prosty… właściwie to chodzi o konwencję nazewniczą + ograniczanie kaskadowości co wpływa na brak pisania kontekstowych arkuszy stylów.
      Może to Ci pomoże: http://www.youtube.com/watch?v=AIwJhTJD-rk

      Odpowiedz
      • Awatar
        Sebastian Żebrowski

        20 kwietnia 2014 13:11

        U mnie z angielskim trochę słabo, mam nadzieję, że coś ogarnę ;)

        Odpowiedz
    • Awatar
      Michał Kortas

      21 kwietnia 2014 17:00

      Będziemy pamiętać na przyszłość. Dzięki za wskazówkę! :)

      Odpowiedz
  • Awatar
    Wilhelm

    13 marca 2016 17:01

    Hmm, ok. Jednak mam pytanie. Co zrobić w przypadku kiedy to selektor np. określający wygląd inputów ma być globalny? Bo z tego co ustaliłem czytając artykuł BEM styluje każdy blok osobno. Można zrobić deklaracje klas globalnych, ale czy to wtedy nie będzie złamana struktura BEM?

    Odpowiedz
    • Awatar
      Comandeer

      13 marca 2016 17:03

      W BEM bloki mogą się ze sobą mieszać, np. blok wyszukiwarki może składać się z osobnych bloków poszczególnych inputów. Stąd taką globalną klasę inputów można po prostu uważać za osobny blok (choć tak, brzmi to nieco naciąganie ;)).

      Odpowiedz

Zostaw odpowiedź