Block, Element, Modifier w CSS


19 kwietnia 2014 / Mr.Mr


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:

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.

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.

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.

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

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:

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:


32 odpowiedzi na “Block, Element, Modifier w CSS”

  1. Comandeer pisze:

    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.

    • 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.

      • Comandeer pisze:

        .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.

      • .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”.

      • Comandeer pisze:

        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.

      • Comandeer pisze:

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

      • 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).

      • Comandeer pisze:

        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.

      • Mr.Mr pisze:

        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.

      • Comandeer pisze:

        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.

      • Mr.Mr pisze:

        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.

      • Comandeer pisze:

        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)

      • 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? ;)

      • …a lepsze jest wrogiem dobrego :)

      • Mr.Mr pisze:

        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ć.

      • Mr.Mr pisze:

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

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

    • Comandeer pisze:

      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…

  2. Piotr Nalepa pisze:

    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.

    • 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.

      • Piotr Nalepa pisze:

        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.

  3. Sebastian Żebrowski pisze:

    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.

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

      • Sebastian Żebrowski pisze:

        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)?

      • Mr.Mr pisze:

        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).

      • Sebastian Żebrowski pisze:

        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.

    • Mr.Mr pisze:

      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

      • Sebastian Żebrowski pisze:

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

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

  4. Wilhelm pisze:

    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?

    • Comandeer pisze:

      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 ;)).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.