BEM w CSS

bem css

W tym wpisie przedstawię krótko znaną metodykę nazewnictwa w CSS o nazwie BEM (z ang. “Block Element Modifier”). Tak naprawdę jest to ten rodzaj wpisu który powinien powstać dawno temu. Jednak każdy z nas ma ograniczoną ilość godzin w ciągu dnia. Postanowiłem dodać ten wpis bo dzięki temu sam mogę lepiej przeanalizować temat i go zapamiętać. Samą metodykę mam zamiar wprowadzać w swoich nowych projektach, m.in. w skrypcie Notice3.

Dlaczego używać metodyk nazewnictwa?

Dlaczego w ogóle korzystać z metodyk nazewnictwa? Pomaga to utrzymać porządek w kodzie CSS, szczególnie przy większych projektach. Ułatwia też przenoszenie poszczególnych elementów w inne miejsca w kodzie lub do innego projektu. Po za tym inna osoba w zespole która będzie analizować kod CSS będzie miała łatwiejsze zadanie gdy wszyscy będą się trzymali ustalonej metodyki nazewnictwa. Po za tym my sami odniesiemy korzyść gdy po czasie będziemy analizować swój własny kod – trzymając się danej metodyki szybciej będziemy wiedzieli co do czego służy.

Wprowadzenie do BEM

BEM jest jedną z popularniejszych metodyk nazewnictwa w CSS. Wprowadza on podział elementów na 3 grupy:

  • blok – samodzielna jednostka na stronie np. menu, stopka, formularz
  • element – część bloku która nie ma samodzielnego znaczenia i musi znajdować się w danym bloku jak np. kontrolki formularza
  • modyfikator – flaga na elemencie, lub wariant elementu

Konwencja nazewnicza dla tych grup wygląda następująco:

  • .block – oznacza nazwę jednostki na stronie, jest to pierwsze słowo w nazwie klas CSS
  • .block__element – nazwa bloku z dodanymi dwoma podkreślaniami i nazwą elementu oznacza że klasa CSS dotyczy elementu w danym bloku
  • .block__element–modifier – jeśli za nazwą elementu dodamy dwa myślniki i nazwę modyfikatora oznacza że dotyczy ona wariantu danego elementu

BEM w praktyce

Zobaczmy teraz jak w praktyce możemy wykorzystać tą wiedzę. Przykładowe menu stworzone zgodnie z BEM mogłoby wyglądać następująco (kod HTML):

<nav class="menu">
  <a href="#" class="menu__link menu__link--active">Strona główna</a>
  <a href="#" class="menu__link">Oferta</a>
  <a href="#" class="menu__link">Kontakt</a>
</nav>

Kod CSS mógłby wyglądać w ten sposób:

.menu{
  background-color: #ddd;
}
.menu__link{  // klasa CSS dla wszystkich linków w menu
  font-size: 14px;
  color: #000; 
}
.menu__link--active{
  color: #FF0000; 
}

Widzimy tutaj nazwę bloku z klasą „menu”. Wewnątrz niego znajdują się linki z klasami „menu__link” (nazwa bloku, dwa podkreślenia i nazwa elementu”. Aktywny link ma dodatkową klasę CSS „menu__link–active” (nazwa bloku, dwa podkreślenia, nazwa elementu, dwa myślniki i nazwa wariantu). Należy zwrócić uwagę że aktywny link ma standardowa klasę CSS taką jaką posiadają pozostałe linki w menu i oprócz niej dodatkową klasę CSS dla wariantu aktywnego linka.

Przy okazji należy pamiętać o kilku dodatkowych zasadach w BEM:

  • Nie należy używać identyfikatorów elementów (np. #menu) ani nazw elementów (np. nav)
  • Nie należy używać selektorów potomków (np. .menu .menu__link), nie dotyczy modyfikatorów bloków (np. menu__link–active .menu__img)

Zagnieżdżanie elementów w BEM

A jaką nazwę powinien mieć element znajdujący się w innym elemencie bloku?

Załóżmy taką sytuację:

<nav class="menu">
  ...
  <ul class="menu__list">
    <li class="?"></li>
  </ul>
</nav>

Jaką klasę powinien mieć element li? „menu__list__item”? Czy może „menu__item”?
Ogólnie nie powinno się nadawać klas w stylu „menu__list__item” czyli blok__element__element. Zamiast tego można element zagnieżdzony w elemencie też przypisywać do blogu czyli np. „menu__item”.

Można też wykorzystać inne podejście i po prostu blok zagnieżdżać w bloku. Wtedy przykład mógłby wyglądać następująco:

<header class="header">
  ...
  <div class="header__logo">
    ...
  </div>
  <ul class="menu">
    <li class="menu__item"></li>
    ...
  </ul>
</header>

Widzimy tutaj, że blok „menu” jest zagnieżdżony w bloku „header” ale przy okazji jest niezależnym blokiem od header.

Podsumowanie

Jak widać podstawowe zasady BEM nie są zbyt skomplikowane. Oczywiście jak to zwykle bywa, na początku może być trochę trudno się przyzwyczaić ale szybko można zauważyć w praktyce korzyści ze stosowania tej konwencji nazewniczej. Nasz kod CSS będzie bardziej modularny, re-używalny i raczej płaski. Oczywiście BEM to tylko jedna z wielu konwencji nazewniczych w CSS. Może używasz innej i uważasz, że jest lepsza niż BEM? Podziel się tym w komentarzu:)