Méthodologie BEM pour le CSS

mis à jour le 9 mars 2021

Ayant travaillé pour différents clients, dans de nombreuses agences web ou en freelance, j’ai été exposé à des méthodes variées de production du code CSS.
Certains projets se basant sur un code sans aucune méthodologie, d’autres extrêmement structurés. Il semble aujourd’hui que la méthodologie BEM fasse consensus auprès des développeurs Front-End.

Que signifie BEM ?

BEM est un sigle pour Blocks – Elements – Modifiers. Ce qui en français serait traduit ainsi : Blocs – Éléments – Modificateurs.
Trois entités qui vont permettre de découper et organiser tous les composants d’une page web.

Quel est le concept qui se cache derrière ses 3 lettres ?

BEM envisage la composition d’une page web en deux types de « composants » :

  • Le bloc est un composant «parent» contenant un ou plusieurs éléments. Le bloc peut être indépendant, et lorsque pris hors contexte d’une page spécifique, garde du sens.
    • Par exemple : un menu, un pied de page (footer), un menu latéral (sidebar).
  • L’élément est un composant appartenant à un bloc. Il faut considérer un élément comme l’enfant d’un bloc.
    • Par exemple : le titre d’un bloc, une page d’un menu.

Enfin BEM introduit le concept de modificateur.

  • Le modificateur va introduire une notion de comportement. Il se modifie en fonction du contexte de la page ou d’une action de l’utilisateur. Le modificateur peut aussi bien être appliqué à un bloc qu’à un élément.
    • Par exemple : un fond de couleur différente pour une page spécifique, un élément rendu visible (ou caché) après un clic de l’utilisateur.
Structure CSS à la BEM d'une page web
Structure CSS à la BEM d’une page web (en l’occurrence la page portfolio)

La convention de nommage BEM

En BEM, toutes les classes CSS sans exception commencent nécessairement par le nom du bloc. Par exemple pour le menu : .menu.

Si on souhaite ajouter dans notre bloc .menu un élément item, on va le nommer .menu__item. On sépare le bloc de l’élément par deux underscores.

Le code HTML correspondrait à cela :

<div class="menu">
    <div class="menu__item">Page 1</div>
</div>


Il est donc facile de lire le code et de comprendre que .menu__item est un élément de .menu.

Pour le modificateur, on sépare le bloc ou l’élément par deux tirets .bloc__element--modificateur :

<div class="menu">
    <div class="menu__item">Page 1</div>
    <div class="menu__item  menu__item--is-open">Page 2</div>
    <div class="menu__item">Page 3</div>
</div>

Cette norme de rédaction des classes est une recommandation, vous êtes libre d’utiliser un underscore plutôt que deux, ou faire du camel case. Il faut simplement respecter une hiérarchie et rendre le code aussi lisible que possible.

Voici l’exemple du code CSS (simplifié) pour le bloc «project» de l’illustration ci-dessus :

.project {
    width: 100%;
    position: relative;
    margin-bottom: 50px;
    min-height: 260px;
}
.project__title {
    font-size: 30px;
    display: inline;
    background-color: #fff;
    color: blue;
}
.project__logo {
    width: 260px;
    height: 260px;
    padding: 10px;
    background-color: blue;
}

L’exemple du code CSS (simplifié) pour l’élément «catégories de project» et son modificateur de l’illustration ci-dessus :

.project__categories {
    padding: 10px;
    display: inline-block;
}
.project__categories-item {
    font-size: 13px;
    display: inline-block;
    background-color: steelblue;
    color: blue;
}
/* modificateur pour catégorie active */
.project__categories-item--is-active {
    background-color: white;
}

BEM réduit les risques de conflits de nommage

Un des problèmes que l’on rencontre rapidement en rédigeant du CSS, c’est de se retrouver avec des noms de classes similaires. La méthodologie BEM impose un nommage des classes qui élimine quasiment les risques de conflits CSS.

  • sans BEM :
/* titre de la page nommée simplement .titre */
.titre {
    font-size: 15px;
    color: red;
}
/* 
titre d'un article dans la page également 
appelé .titre voici donc un conflit, deux classes 
qui se superposent ! 
*/
.titre {
    font-size: 30px;
    color: blue;
}
  • avec BEM :
/* titre de la page nommée .page__titre /*
.page__titre {
    font-size: 15px;
    color: red;
}
/* titre d'un article dans la page appelé .article__titre . 
On a éliminé le conflit en nommant suivant 
une convention nos éléments. */
.article__titre {
    font-size: 30px;
    color: blue;
}

Constat : Le conflit est résolu et en plus le code est plus compréhensible (de mon point de vue en tout cas).

BEM réduit les risques de conflits liés à la spécificité

La spécificité en CSS est une logique épineuse avec laquelle il vaut mieux éviter de s’amuser.

Un exemple de conflit de spécificité sans BEM :

/* le CSS */
h3 { color: green; }
h3#main { color: orange; }
h3.navigation { color: yellow;}
<!-- le HTML -->
<h3 class="navigation" id="main">Titre de niveau trois</h3>

À votre avis, de quelle couleur sera le titre h3 ?
Si vous avez de bonnes notions de CSS, vous le savez déjà. Dans tous les cas, si on avait appliqué la méthodologie BEM, nous ne nous poserions même pas la question.

Résolution du conflit de spécificité avec BEM :

/* le CSS */
.title-h3 { color: green; }
.main__title-h3 { color: orange; }
.navigation__title-h3 { color: yellow;}
<!-- le HTML -->
<h3 class="title-h3  navigation__title-h3">Titre de niveau trois</h3>

BEM proscrit l’utilisation de l’attribut id. On vient donc de résoudre le conflit majeur de l’exemple. Enfin j’ai choisi de surcharger le style par défaut du titre h3 appelé .title-h3 avec la classe .navigation__title-h3. Si des déclarations CSS entrent en conflits au sein de 2 ou plusieurs classes, ce sera la dernière classe déclarée qui appliquera ses déclarations.

BEM est extrêmement modulaire et réutilisable

BEM CSS réutilisable, portable

En résolvant les deux conflits vus ci-dessus, BEM impose une méthodologie qui rend la rédaction de CSS plus rigide mais aussi plus sûre. Il est facile d’utiliser les différentes classes produites dans toutes les pages sans se soucier des conflits.

On envisage alors le code comme un assemblage de briques réutilisables, modulaires et extensibles. Il est même possible de réutiliser certaines briques, d’un projet à un autre, sans rencontrer de conflits.

Aller plus loin avec BEM CSS

Nous avons abordé les principes de bases de la méthodologie BEM et vu comment BEM permet de solidifier notre code.

Pour tirer le meilleur de BEM (et de CSS tout simplement), je recommande d’utiliser une syntaxe améliorée CSS comme Sass, Less ou PostCSS.
Sans rentrer dans les détails, ces langages permettent de séparer le code CSS en fichiers distincts, d’imbriquer des déclarations, d’utiliser des variables réutilisables et d’une façon générale de rendre le code plus léger et plus compréhensible pour le développeur front-end.

Ainsi, BEM couplé à Sass par exemple, assure une souplesse et une portabilité très bonne du code. Ce sera certainement l’objet d’un prochain article !
Vous pouvez aussi découvrir 8 règles pour organiser votre code CSS.

Si vous voulez approfondir vos connaissances en CSS en général, ce qui est complémentaire de la méthodologie BEM, vous pouvez consulter une liste des meilleures ressources CSS sur le web et en livres.

En savoir plus sur BEM via getbem.com ou bem.info (en anglais).