Lekcja 28
Nazewnictwo klas i BEM-like naming
W małym pliku CSS przypadkowe nazwy klas wydają się niewinne. W większym projekcie szybko prowadzą do kolizji, nadpisywania stylów i kodu, którego nikt nie chce ruszać. W tej lekcji nauczysz się nadawać klasom nazwy, które opisują komponent, jego części i warianty.
Cele lekcji
Po ukończeniu tej lekcji będziesz umieć:
- rozpoznać nazwy klas, które będą trudne w utrzymaniu,
- wyjaśnić różnicę między blokiem, elementem i modyfikatorem,
- pisać klasy w stylu
block__element--modifier, - odróżniać klasę komponentu od klasy stanu i utility,
- unikać zbyt głębokiego zagnieżdżania selektorów,
- projektować nazwy klas tak, aby były odporne na rozbudowę komponentu.
Kontekst praktyczny
Nazewnictwo klas jest podstawą pracy zespołowej. Gdy komponent ma jasne klasy, łatwiej go znaleźć, rozszerzyć i naprawić. Dobre nazwy zmniejszają zależność od struktury HTML i ograniczają ryzyko, że zmiana w jednej sekcji przypadkowo popsuje inną.
Problem nazw ogólnych
Nazwy typu .box, .title, .green albo .left nie mówią, do czego należą. Im większy projekt, tym większa szansa, że taka klasa zostanie użyta w kilku miejscach i zacznie wymuszać nadpisywanie stylów.
.box {
padding: 1rem;
}
.title {
font-size: 1.25rem;
}
.green {
background: #dcfce7;
}
Te nazwy opisują wygląd albo położenie, ale nie opisują roli komponentu. Po kilku tygodniach nie wiadomo, czy .box jest kartą lekcji, panelem formularza czy kontenerem promocji.
Model BEM-like
BEM dzieli nazwę klasy na trzy pojęcia: blok, element i modyfikator. W praktyce frontendowej często używa się wersji BEM-like, czyli tej samej logiki bez nadmiernego formalizmu.
.course-card {}
.course-card__title {}
.course-card__meta {}
.course-card--featured {}
.course-card jest samodzielnym komponentem. __title i __meta są częściami tego komponentu. --featured jest wariantem całego komponentu.
Blok
Blok to samodzielny komponent, który można przenieść w inne miejsce strony bez zmiany jego sensu. Dobry blok ma nazwę rzeczownika albo krótkiego wyrażenia opisującego rolę.
.pricing-card {
display: grid;
gap: .75rem;
padding: 1rem;
border: 1px solid var(--color-border);
}
Nazwa .pricing-card mówi więcej niż .card, jeśli w projekcie istnieją też karty lekcji, karty produktu i karty profilu.
Element
Element to część bloku, która nie ma sensu jako samodzielny komponent. Zapisujemy go po podwójnym podkreśleniu: block__element.
.pricing-card__title {
margin: 0;
font-size: 1.25rem;
}
.pricing-card__price {
font-size: 2rem;
font-weight: 800;
}
Nie twórz łańcuchów typu .pricing-card__header__title. Jeśli element zaczyna mieć własne podczęści, rozważ nowy blok albo prostszą strukturę.
Modyfikator
Modyfikator opisuje wariant bloku albo elementu. Zapisujemy go po podwójnym myślniku: block--modifier albo block__element--modifier.
.pricing-card--featured {
border-color: #60a5fa;
background: #eff6ff;
}
.pricing-card__badge--success {
background: #dcfce7;
color: #166534;
}
Modyfikator nie powinien istnieć bez klasy bazowej. Element powinien mieć najpierw .pricing-card, a dopiero potem .pricing-card--featured.
Stan i utility
Stan opisuje aktualną sytuację komponentu, na przykład aktywny, otwarty albo ładowany. Utility to mała klasa pomocnicza, która robi jedną rzecz. Nie mieszaj ich z nazwami komponentów bez potrzeby.
.accordion {
border: 1px solid var(--color-border);
}
.accordion.is-open {
border-color: #60a5fa;
}
.u-visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
}
W tym projekcie możesz spotkać klasy stanu typu .is-open. Są czytelne, gdy opisują stan komponentu, ale nie powinny zastępować nazw jego części.
Demo nazewnictwa
Demo porównuje ten sam komponent opisany nazwami ogólnymi i nazwami BEM-like. Różnica nie polega na wyglądzie, tylko na tym, jak łatwo będzie utrzymać kod po rozbudowie.
Nazwy ogólne
Wygląda poprawnie, ale klasy nie mówią, gdzie komponent żyje i co można bezpiecznie zmienić.
.boxzbyt ogólna.titlekolizje.greenopis wyglądu
Nazwy komponentu
Klasy opisują blok, elementy i wariant, więc komponent można rozszerzać bez zgadywania.
.course-cardblok.course-card__titleelement.course-card--featuredwariant
Najczęstsze błędy początkujących
- Nazywanie klas po kolorze, wielkości albo położeniu zamiast po roli komponentu.
- Tworzenie zbyt ogólnych klas typu
.card,.item,.contentw dużym projekcie. - Zagnieżdżanie selektorów tak głęboko, że HTML staje się częścią kontraktu CSS.
- Używanie modyfikatora bez klasy bazowej komponentu.
- Mieszanie klas komponentu, stanu i utility bez jasnej zasady.
- Zmiana nazwy klasy bez sprawdzenia, gdzie jest używana w HTML i JavaScript.
Mini zadanie
Przepisz prostą kartę profilu na nazwy BEM-like.
- Wybierz blok, na przykład
.profile-card. - Dodaj elementy:
__avatar,__name,__rolei__actions. - Dodaj modyfikator
--compactalbo--featured. - Dodaj stan
.is-loading, jeśli karta ma wariant ładowania. - Sprawdź, czy żadna klasa nie opisuje wyłącznie koloru albo położenia.
Checklista
- Potrafię wskazać blok, element i modyfikator w komponencie.
- Wiem, kiedy nazwa klasy jest zbyt ogólna.
- Nie tworzę klas zależnych od konkretnego miejsca w HTML.
- Używam modyfikatorów do wariantów, a nie do zastępowania klasy bazowej.
- Rozdzielam klasy komponentu, stanu i utility.
- Projektuję nazwy tak, aby inna osoba mogła bezpiecznie rozbudować komponent.
Podsumowanie lekcji
Dobre nazwy klas są częścią architektury CSS. BEM-like naming pomaga utrzymać komponenty, bo jasno oddziela blok, jego elementy i warianty. Nie chodzi o długie nazwy dla samych nazw, tylko o przewidywalność i mniejsze ryzyko przypadkowych kolizji.
Kolejny krok roadmapy to zmienne CSS i design tokens.
Przejdź do Lekcji 29