Blog overzicht

De platte wereld van BEM voor CSS

Cascading Style Sheets zijn het Wilde Westen als het aankomt op naamconventies. Iedereen classificeert op zijn eigen manier HTML-tags en een officiële schrijfwijze mist. Het onderhouden of wijzigen van CSS is daarom sterk afhankelijk van de wijze waarop je een HTML- en CSS-document inricht. Kan jij je na een half jaar herinneren wat je met een bepaalde selector bedoelde en durf je deze te wijzigen met de zekerheid dat er niets anders op de pagina verandert? Deze vragen zijn vooral van belang als je met collega’s aan grotere projecten werkt.

Block, Element, Modifier

Om met volle zekerheid aan onze stylesheets te kunnen sleutelen, hebben wij er bij TransIP voor gekozen om bij het schrijven van CSS gebruik te maken van de populaire naamconventie BEM. Hierdoor kunnen de developers onze websites makkelijk onderhouden en uitbreiden, ook al hebben ze de code niet zelf geschreven.

Voorbeeld van entiteiten voor BEMSource: getbem.com

De BEM-methode werkt met 3 verschillende entiteiten:

Block. Een block is een zelfstandige en herbruikbare entiteit die elementen, modifiers of zelfs andere blocks kan bevatten. In de bovenstaande afbeelding zijn het logo, het menu, de inputvelden en de buttons allemaal blocks.

Element. Een block bestaat soms uit meerdere onafscheidbare onderdelen, die elementen worden genoemd. Een element is altijd gekoppeld aan een block waardoor je het niet zelfstandig kan verplaatsen naar een andere locatie op een pagina. De menu-items zijn bijvoorbeeld elementen van het block ‘menu’.

Modifier. Een modifier bepaalt de staat van een block of element. In de bovenstaande afbeelding is de standaardkleur van het block ‘button’ grijs. Als je een modifier vastplakt aan dit block, kan je de grijze kleur van de button wijzigen naar bijvoorbeeld de kleur groen, zonder te sleutelen aan het originele block.

CSS leren schrijven met BEM: Block__Element--Modifier

Om CSS te leren schrijven en te werken met de 3 entiteiten van BEM is er slechts een kleine wijziging nodig in de manier waarop je HTML/CSS tot nu hebt geschreven. Het enige wat je hoeft te doen is elke HTML-tag die je van plan bent te stijlen met CSS een unieke class te geven. In je stylesheet selecteer je vervolgens de HTML-tag door middel van deze class. Selecties via ID’s (te specifiek) of HTML-tags (te globaal) zijn niet toegestaan.

Een ongeordende lijst stijl je bijvoorbeeld op de volgende manier:

 
Schrijfwijze blockHTMLCSS
Juist (class)<ul class=”product-list”> <li> Item 1 </li> </ul>.product-list { padding: 10px; }
Onjuist (ID)<ul id=”product-list”> <li> Item 1 </li> </ul>#product-list { padding: 10px; }
Onjuist (HTML-tag)<ul> <li> Item 1 </li> </ul>ul { padding: 10px; }

Het block mag je noemen zoals je zelf wilt, zolang het maar niet te specifiek is en jij of je collega’s maar snappen waar het voor staat (in dit geval ‘product-list’). Voor elementen en modifiers geldt overigens hetzelfde.

Als je een element van het block ‘product-list’ wilt stijlen, maak je hier ook een aparte class voor. De class van een element begint altijd met de naam van het block, gevolgd door twee laagliggende strepen en de naam van het element. Een list-item in een ongeordende lijst stijl je daarom op de volgende manier:

 
Schrijfwijze elementHTMLCSS
Juist (class)<ul class=”product-list”> <li class=”product-list__list-item”> Item 1 </li> </ul>.product-list__list-item { padding: 10px; }
Onjuist (ID)<ul id=”product-list”> <li id=”product-list__list-item”> Item 1 </li> </ul>#product-list__list-item { padding: 10px; }
Onjuist (HTML-tag)<ul> <li> Item 1> </li> </ul>ul li { padding: 10px; }

Wat als er meerdere lijsten op een pagina staan en je ter promotie één lijst extra wilt benadrukken door de tekst wat groter te maken? Aangezien dit maar een kleine modificatie is van het element wat je al hebt gemaakt (.product-list__list-item), is het zonde om een nieuw element te maken. Een modifier is een betere keuze voor dit doel.

Modifiers borduren voort op bestaande blocks of elementen en classificeer je door de te beginnen met de naam van het element, gevolgd door twee koppeltekens en de naam van de modifier.

Vergeet ook niet het block of element dat je wilt modificeren in de class te noemen, aangezien een modifier slechts aanvullende informatie bevat. Een modifier voor grote tekst stijl je zo:

 
Schrijfwijze modifierHTMLCSS
Juist (class)<ul class=”product-list”> <li class=”product-list__list-item product-list__list-item--promotie”> Item 1 </li> </ul>.product-list __list-item { padding: 5px; font-size: 1em; } .product-list__list-item--promotie { font-size: 2em; }
Niet mogelijk (2X ID)<ul id=”product-list”> <li id=”product-list__list-item product-list__list-item--promotie”> Item 1 </li> </ul>#product-list __list-item { padding: 5px; font-size: 1em; } #product-list__list-item--promotie { font-size: 2em; }
Onjuist (HTML-tag)<ul> <li class=”promotie”> Item 1 </li> </ul>ul li { padding: 5px; font-size: 1em; } .promotie { font-size: 2em; }

CSS BEM logo

Zo plat als een dubbeltje

Je vraagt je misschien af waarom het werken met ID’s of HTML-tags in je stylesheet als fout staat aangegeven in de bovenstaande tabellen. Dit heeft te maken met de platte structuur van BEM.

Het is de bedoeling dat je elke HTML-tag die je wilt stijlen, kan oproepen met 1 selector. Het nestelen van selectors is daarom een no-go. Dit betekent overigens niet dat je in HTML een tag niet mag nestelen, anders zou je bijvoorbeeld onmogelijk een ongeordende lijst kunnen maken. Deze tag kan je in CSS weer ‘ontnestelen’ door het een class te geven. Aangezien ID’s niet herbruikbaar zijn en HTML-tags vaak meerdere selectors vereisen, komen ze niet in aanmerking voor dit doel.

De platte structuur die je met deze werkwijze creëert, brengt verschillende voordelen met zich mee op het gebied van specificiteit, modulariteit, leesbaarheid en snelheid.

Specificiteit

In CSS vechten er verschillende selectors om de macht. De selector die het specifiekst is, wint. Specificiteit in CSS is op de volgende manier ingedeeld.

CSS specificiteit

Source: css-tricks.com

Stel dat je een button hebt aangemaakt met een ID en class ‘btn’. De selector die verwijst naar het ID btn, zal altijd voorrang hebben op de selector die verwijst naar de class btn. Zelfs als de class later in de code voorkomt, waardoor het eigenlijk voorrang moet krijgen.

In stylesheets waarin zowel inline stijlen, ID’s, classes en HTML-tags worden gebruikt, kan het een speurtocht zijn om uit te zoeken welke selector voorrang heeft en waarom. Doordat je alleen met (niet genestelde) classes werkt, voorkom je op voorhand problemen met specificiteit. Al je selectors zijn tenslotte van hetzelfde niveau.

Flexibiliteit en modulariteit

Blocks en elementen dragen in BEM hun eigen class en zijn zo volledig onafhankelijk van de HTML-tags waarin ze zich bevinden. Hierdoor is het makkelijk om bij een reorganisatie van je website van HTML-tags te wisselen, zonder dat dit invloed heeft op het uiterlijk van je website.

 
Soort layoutHTML
Oude layout met div-tag als parent<div> <ul class=”product-list”> <li class=”product-list__list-item”> Item 1 </li> </ul> </div>
Nieuwe layout met een article-tag als parent<article> <ul class=”product-list”> <li class=”product-list__list-item”> Item 1 </li> </ul> </article>

Deze onafhankelijkheid is ook van belang als het gaat om modulariteit. Een block afkomstig uit een header kan je bijvoorbeeld zonder problemen kopiëren en plaatsen naar een locatie buiten de header. Er bestaan namelijk geen stijlregels voor de header die ook invloed uitoefenen op het block. En aangezien je niet met ID’s mag werken, kan je blocks zelfs meerdere keren dupliceren. 

 
Locatie van het blockHTML
Block in de header-tag<header> <div class=”avatar”> <img class=”avatar__image ”> </div> </header>
Verplaatst naar de body-tag<body> <div class=”avatar”> <img class=”avatar__image ”> </div> </body>

Leesbaarheid

Dankzij de doordachte en strikte classificering van BEM kan je uit elke HTML-tag alle informatie verkrijgen die je nodig hebt. Zo zie je meteen of je met een block of element te maken hebt, en bij welk block een element hoort. Hetzelfde geldt voor modifiers omdat ze altijd in combinatie met hun block of element geschreven worden.

Hiernaast weet je dat collega’s dankzij BEM hun HTML- en CSS-code op precies dezelfde manier als jij zullen schrijven. Dit maakt de communicatie binnen een team een stuk efficiënter en neemt de angst om andermans code te wijzigen weg.

Snelheid

Door de platte structuur werk je steeds met 1 selector per CSS-regel. Een regel met maar 1 selector wordt sneller door een browser berekend dan een regel die werkt met genestelde selectors. Bij de selector ‘ul li’ worden bijvoorbeeld eerst alle li-tags in het document gezocht en dan pas alle li-tags die onderdeel zijn van een ul-tag. Dit is aanzienlijk meer werk dan alleen een li-tag opzoeken die de class ‘product-list__list-item’ bevat. Alhoewel dit verschil in snelheid in moderne browsers vrijwel nihil is, kan het wel interessant zijn voor oudere browsers.

 
SnelheidCSS
Snellere render door de browser.product-list__list-item {color: blue;}
Langzamere render door de browserul li {color: blue;}
CSS ICON

BEM resources

De volgende artikelen helpen je nog verder op weg als je aan de slag gaat met BEM. Hou bovendien ons blog in de gaten, want binnenkort behandelen we in een opvolgend artikel veelgestelde vragen over het werken met BEM.

Officiële BEM-websiteMindBEMdingBEM 101Battling BEMEvolution of BEM

BEM jij er ook een?

CSS leren schrijven met BEM zorgt voor makkelijk onderhoud en zelfvertrouwen bij het wijzigen van je code. Het kost even wat moeite om bijna alles van een class te voorzien, maar eenmaal gewend aan deze werkwijze gaat er een nieuwe (platte) wereld voor je open. Een wereld die je vooral zal waarderen als je (met meerdere mensen) aan een groot project werkt of je website maar enkele keren per jaar onderhoudt.


Werk jij ook met BEM of andere naamconventies? Laat jouw ervaringen achter in de commentaren hieronder.


Beoordeel dit artikel

Deel dit artikel

Gerelateerde artikelen

    • Leestijd: 8 minuten

Blog overzicht

Auteur: Akif Hodzic

Voorziet als contentmarketeer het blog van bruisende artikelen voor doorgewinterde techies en digitale nomaden om iedereen wegwijs te maken in de online wereld. Is daarnaast altijd te poken voor een potje Overwatch of een praatje over de laatste tv-series en tech-gadgets.