Introduction à la méthodologie BEM
Publié: 2022-03-11Qu'est-ce que la méthodologie BEM ?
Lorsque vous créez des sites Web plus petits, la façon dont vous organisez vos styles n'est généralement pas un gros problème. Vous créez vos fichiers habituels, écrivez tous les CSS nécessaires, et c'est tout. Cependant, lorsqu'il s'agit de projets plus importants et plus complexes, la façon dont vous organisez votre code devient cruciale . La structure du code est encore plus importante si vous travaillez dans une équipe composée de plusieurs développeurs front-end et back-end.
Aujourd'hui, il existe de nombreuses méthodologies dans le but de réduire le code CSS et de rendre votre code CSS plus maintenable. Dans cet article, je vais vous expliquer et donner quelques exemples de l'un d'entre eux : BEM. BEM signifie B lock E lement Modifier. L'idée principale est d'accélérer le processus de développement et de faciliter le travail d'équipe des développeurs en organisant les classes CSS en modules indépendants. Si vous avez déjà vu un nom de classe comme header__form--search
, c'est BEM en action. Oui, les classes peuvent être nommées très longtemps, mais elles sont toutes lisibles et compréhensibles.
Notez que la meilleure pratique consiste à utiliser BEM uniquement avec des classes, et non des ID, car les classes vous permettent de répéter les noms si nécessaire et de créer une structure de codage plus cohérente. De plus, si vous souhaitez diviser votre site Web en modules organisés, il doit être composé de la même structure : bloc, élément et modificateur. Où chaque bloc peut avoir plusieurs éléments, et le bloc et les éléments peuvent avoir plusieurs modificateurs. Cependant, commençons d'abord par la structure BEM de base et expliquons-la avec des exemples.
Bloquer
Un bloc représente un objet dans votre site Web. Considérez-le comme de plus gros morceaux structurels de votre code. Les blocs les plus courants sur chaque site Web aujourd'hui sont l'en-tête, le contenu, la barre latérale, le pied de page et la recherche. Les blocs dans BEM sont toujours un point de départ pour enchaîner vos classes CSS. Jetez un œil à quelques exemples de blocs :
- un contenu
- un menu
- un formulaire de recherche
.content {/* Styles */} .menu {/* Styles */} .search {/* Styles */}
Élément
Un élément est un composant du bloc qui remplit une fonction particulière. Cela ne devrait avoir de sens que dans le contexte de son bloc :
- un article de contenu
- un élément de menu
- un champ de saisie de recherche
.content__article {/* Styles */} .menu__item {/* Styles */} .search__input {/* Styles */}
Modificateur
Un modificateur est la façon dont nous représentons les variations d'un bloc. Si vous avez déjà utilisé Bootstrap, le meilleur exemple serait la taille des boutons. Les tailles des boutons ne sont que des variations de taille du bouton lui-même, ce qui en fait le modificateur :
- un article vedette de contenu
- un lien de menu
- un champ de recherche avec ou sans icône
.content__article--featured {/* Styles */} .menu__item--link {/* Styles */} .search__input--icon {/* Styles */}
Conventions de nommage
L'objectif principal de la méthodologie BEM est de rendre les noms des sélecteurs CSS aussi informatifs et transparents que possible. Le style BEM d'origine est défini de la manière suivante :
Le nom du bloc est généralement un seul mot comme .header
, mais si vous avez une définition de bloc plus longue, il est divisé par un seul trait d'union -
:
.lang-switcher {/* Styles */}
Le nom de l'élément commence par un double trait de soulignement __
:
.lang-switcher__flag {/* Styles */}
Le nom du modificateur commence par un seul trait de soulignement _
:
.lang-switcher__flag_basic {/* Styles */}
Il n'y a qu'une seule règle très critique dans la méthodologie BEM - un modificateur ne peut pas être utilisé en dehors du contexte de son propriétaire.
Exemple:
.btn_big {/* Styles */}
Vous pouvez utiliser btn_big
uniquement si l'en-tête est également défini.
Mauvais exemple :
<div class=”btn_big”>...</div>
Bon exemple:
<div class=”btn btn_big”>...</div>
Outre ces styles BEM originaux, il existe des schémas de nommage alternatifs comme les styles Harry Roberts et CamelCase.
Exemple de style Harry Roberts :
.block-name__element-name--modifier-name {/* Styles */}
Exemple de style CamelCase :
.BlockName__ElementName_ModifierName {/* Styles */}
Il y en a peu d'autres aussi, mais ces deux-là sont les plus courants. Personnellement, je suis fan de la convention de nommage proposée par Harris Roberts, qui a les règles suivantes :
- Les noms sont écrits en minuscule
- Les mots dans les noms des entités BEM sont séparés par un trait d'union
-
- Un nom d'élément est séparé d'un nom de bloc par un double trait de soulignement
__
- Les modificateurs booléens sont délimités par des doubles tirets
--
- Les modificateurs de type clé-valeur ne sont pas utilisés
La raison pour laquelle cette convention de dénomination est bien mieux formée que d'autres est que vous pouvez facilement distinguer l'élément modificateur des autres. Dans les conventions de nommage d'origine, le modificateur serait défini comme ceci :
.block__element_modifier {/* Styles */}
Mais comme vous pouvez le voir, il n'y a pas beaucoup de différence entre un trait de soulignement simple et double. D'un autre côté, le double trait d'union fournit une séparation nette et vous pouvez voir le modificateur instantanément :
.block__element--modifier {/* Styles */}
Exemple BEM dans différents formats
Veuillez noter qu'en plus de CSS, BEM est également très utile pour organiser vos fichiers JSON, XML, arborescents ou tout format prenant en charge l'imbrication. Considérez la méthodologie BEM comme un bon moyen de créer votre interface utilisateur.
Considérons le code HTML suivant, structuré au format BEM :
<header class=”header”> <img class=”header__logo”> <form class=”header__search-from”> <input class=”header__search-from__input” type=”input”> <button class=”header__search-from__button” type=”button”> </form> <div class=”header__lang-switcher”></div> </header>
La même chose peut être obtenue en utilisant les formats JSON et XML.
XML :
<block:header> <block:logo/> <block:search-from> <block:input/> <block:button/> </block> <block:lang-switcher/> </block>
JSON :
{ block: 'header', content: [ { block: 'logo' }, { block: 'search-form', content: [ { block: 'input' }, { block: 'button' } ] }, { block: 'lang-switcher' } ] }
Organisation du système de fichiers d'un projet BEM
Dans BEM, il est essentiel d'organiser vos fichiers de manière correcte. Non seulement BEM vous offre une excellente organisation des classes CSS et les rend parfaitement compréhensibles, mais vous offre également une structure de fichiers très maintenable. Prenons un exemple de projet utilisant la technique d'organisation de fichiers BEM avec des fichiers SASS :
blocks/ input/ __box/ --big/ input__box--big.scss input__box.scss button/ --big/ button--big.scss
Comme vous pouvez le voir ci-dessus, rien qu'en voyant la structure des sous-dossiers dans votre dossier principal, tout est clair et organisé. De cette façon, peu importe qui travaille après vous ou si vous travaillez après quelqu'un, car il est incroyablement facile de suivre le même schéma.
Diviser le projet BEM en plates-formes
Outre l'organisation de vos fichiers à l'aide des techniques de la méthodologie BEM, vous pouvez également aborder des éléments plus spécifiques. Par exemple, si vous créez un projet Web qui sera entièrement réactif et que le client a spécifié que certains blocs sur le mobile sont totalement différents de ceux sur les appareils de bureau, il serait préférable de diviser votre structure de dossiers BEM en plates-formes. Exemple d'organisation des boutons sur différentes plateformes :
common.blocks/ button/ button.scss desktop.blocks/ button/ buttons.scss mobile.blocks/ button/ button.scss
Notez qu'il ne s'agit que d'un exemple si vous souhaitez organiser l'ensemble de votre projet en utilisant la méthodologie BEM. L'arborescence de fichiers avec la structure BEM n'est pas obligatoire pour utiliser BEM correctement, vous pouvez utiliser BEM uniquement dans certains segments du projet. Jusqu'à présent, je n'ai pas utilisé cette organisation de structure de fichiers BEM stricte où chaque élément et modificateur a son fichier créé. Au lieu de cela, je crée simplement une structure de fichiers pour les blocs qui ont une déclaration de ses éléments et modificateurs.
BEM en pratique
Puisque vous êtes maintenant familiarisé avec les conventions de nommage, je vais démontrer la méthodologie BEM dans la pratique. Disons que nous avons ce code HTML en action :
<a class=”btn btn--big btn--primary-color” href=”#” title=”Title”> <span class=”btn__price”>$3.99</span> <span class=”btn__text”>Product</span> </a>
Avec le balisage CSS suivant appliqué :
.btn__price {/* Styles */} .btn__text {/* Styles */} .btn--big {/* Styles */} .btn--primary-color {/* Styles */}
Maintenant, ne vous y trompez pas. Jusqu'à présent, dans nos exemples, nous avions presque toujours un bloc, un élément et un modificateur, ce qui n'est pas toujours le cas.
Par exemple, disons que nous avons un bloc nommé person . Une personne a des jambes et des mains, elle peut aussi être une femme ou un homme. Si nous voulons définir une personne de sexe masculin avec une main droite, cela ressemblera à ceci :
.person--male__hand--right {/* Styles */}
Vous pouvez maintenant voir la véritable signification du BEM. Nous avons défini une personne dont le modificateur est un genre. Comme peu importe qu'une personne soit un homme ou une femme, elle a une main, et la main est un élément. Et encore une fois, chaque personne peut avoir la main droite ou gauche, ce qui est encore une fois un modificateur.

Dans un autre cas, si nous voulons définir une personne générale avec une seule main, nous le ferons comme ceci :
.person__hand {/* Styles */}
Comme vous pouvez le constater, une fois que vous vous êtes familiarisé avec BEM, il est très facile de structurer votre structure CSS et HTML avec.
Utilisation de BEM avec des préprocesseurs CSS
Personnellement, je ne peux pas imaginer démarrer un nouveau projet sans utiliser l'un des préprocesseurs CSS. Comme vous le savez tous, les préprocesseurs sont une excellente chose et ils nous offrent de nombreux avantages, et surtout, ils correspondent parfaitement à la méthodologie BEM.
Dans l'exemple suivant, vous pouvez voir l'exemple le plus typique de BEM, en combinaison avec SASS :
.person { &__hand {/* Styles */} &__leg {/* Styles */} &--male { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } &--female { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } }
Le code SASS sera compilé dans le CSS suivant :
.person__hand {/* Styles */} .person__leg {/* Styles */} .person--male {/* Styles */} .person--male__hand {/* Styles */} .person--male__hand--left {/* Styles */} .person--male__hand--right {/* Styles */} .person--male__leg {/* Styles */} .person--male__leg--left {/* Styles */} .person--male__leg--right {/* Styles */} .person--female {/* Styles */} .person--female__hand {/* Styles */} .person--female__hand--left {/* Styles */} .person--female__hand--right {/* Styles */} .person--female__leg {/* Styles */} .person--female__leg--left {/* Styles */} .person--female__leg--right {/* Styles */}
Si vous voulez aller encore plus loin, vous pouvez utiliser un mixins SASS pratique pour BEM :
/// Block Element /// @param {String} $element - Element's name @mixin element($element) { &__#{$element} { @content; } } /// Block Modifier /// @param {String} $modifier - Modifier's name @mixin modifier($modifier) { &--#{$modifier} { @content; } }
Et vous pouvez l'utiliser comme ceci :
.person { @include element('hand') {/* Person hand */} @include element('leg') {/* Person leg */} @include modifier('male') { /* Person male */ @include element('hand') { /* Person male hand */ @include modifier('left') { /* Person male left hand */ } @include modifier('right') { /* Person male right hand */ } } } }
Ce qui produira la sortie CSS suivante :
.person__hand { /* Person hand */ } .person__leg { /* Person leg */ } .person--male { /* Person male */ } .person--male__hand { /* Person male hand */ } .person--male__hand--left { /* Person male left hand */ } .person--male__hand--right { /* Person male right hand */ }
Je sais que vous n'aurez probablement pas un cas d'utilisation aussi long, mais c'est un excellent exemple de la façon dont BEM est utilisé et pourquoi il est si puissant, à la fois dans les projets à petite et à grande échelle.
Démarrage de votre projet BEM
Comme expliqué dans la documentation officielle de BEM, le moyen le plus simple de démarrer votre propre nouveau projet BEM consiste à utiliser le référentiel GIT existant. Utilisez simplement la commande Git clone :
$ git clone https://github.com/bem/project-stub.git
Ensuite, allez dans un répertoire nouvellement créé et installez toutes les dépendances :
$ npm install
Toutes les dépendances requises seront installées :
Construisez le projet à l'aide d'ENB :
$ node_modules/.bin/enb make
Exécutez un mode serveur pour le développement :
$ node_modules/.bin/enb server
En conséquence, le message suivant apparaît :
Server started at 0.0.0.0:8080
Maintenant, cela signifie que le serveur est opérationnel. Vous pouvez désormais consulter les résultats sur cette adresse :
http://localhost:8080/desktop.bundles/index/index.html
Comme vous pouvez le voir, il y a beaucoup d'éléments déjà créés qui sont définis dans le fichier bemjson
qui se trouve ici :
project-stub/desktop.bundles/index/index.bemjson.js
Vous pouvez voir et explorer la structure actuelle du fichier qui génère tout ce code HTML, que vous voyez dans votre fichier localhost index.html
. Nous allons modifier ce fichier pour obtenir notre projet BEM "Person" que nous avons expliqué dans un chapitre précédent. Vous pouvez supprimer (ou commenter) tout le code du fichier index.bemjson.js
, et le remplacer par celui-ci :
module.exports = { block: 'page', title: 'Person BEM', favicon : '/favicon.ico', head : [ { elem : 'meta', attrs : { name : 'description', content : '' } }, { elem : 'meta', attrs : { name : 'viewport', content : 'width=device-width, initial-scale=1' } }, { elem : 'css', url : 'index.min.css' } ], scripts: [{ elem : 'js', url : 'index.min.js' }], content: [ { block: 'person', content: [ { elem: 'male', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Male person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Male person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Male person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Male person hand -- right' } ] }, { elem: 'female', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Female person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Female person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Female person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Female person hand -- right' } ] }, ] } ] };
Maintenant, le code HTML suivant sera généré :
<div class="person"> <div class="person__male"> <div class="person__leg person__leg_side_left"> Male person leg -- left </div> <div class="person__leg person__leg_side_right"> Male person leg -- right </div> <div class="person__hand person__hand_side_left"> Male person hand -- left </div> <div class="person__hand person__hand_side_right"> Male person hand -- right </div> </div> <div class="person__female"> <div class="person__leg person__leg_side_left"> Female person leg -- left </div> <div class="person__leg person__leg_side_right"> Female person leg -- right </div> <div class="person__hand person__hand_side_left"> Female person hand -- left </div> <div class="person__hand person__hand_side_right"> Female person hand -- right </div> </div> </div>
Comme vous pouvez le voir dans le code ci-dessus, le schéma de codage BEM par défaut a été utilisé dans ce scénario puisque nous utilisons simplement les paramètres par défaut que BEM nous a fournis. Il existe de nombreuses autres commandes et options que vous pouvez explorer et utiliser, telles que la création de nouvelles pages, de nouveaux blocs ou la modification de BEM HTML. Je n'irai pas trop loin là-dedans, et tout se trouve dans la documentation officielle de BEM.
Avantages et préoccupations
Avantages
- BEM est excellent pour l'entretien. Combien de fois avez-vous dû travailler après quelqu'un sur un projet à grande échelle et avez-vous trop peur de changer quoi que ce soit sans que quelque chose d'inconnu ne s'effondre ? Lorsque vous utilisez BEM, vous connaissez le but exact de l'élément et dans quel bloc il peut apparaître.
- Les noms de classe sont logiques et intuitifs, et chaque membre de l'équipe sait ce que fait cet élément sur le site Web. BEM donne à tous les membres d'un projet une syntaxe déclarative qu'ils peuvent partager afin qu'ils soient sur la même page.
- BEM élimine les sélecteurs CSS imbriqués. Chaque élément HTML a sa propre classe CSS, et par son nom, vous savez quel est son objectif. Un sélecteur pour les gouverner tous .
Préoccupations et erreurs courantes
- N'allez pas trop loin dans la nidification. La règle principale devrait être de ne pas utiliser plus de deux niveaux de parent et d'enfant.
- Faites attention à l'endroit où vous commencez votre portée de bloc. Une erreur courante ici est lorsqu'un développeur utilise un bloc, mais il ne se rend pas compte qu'à un stade ultérieur du développement, ce même bloc aura un bloc parent principal qui enfreindra éventuellement la règle d'imbrication.
- Évitez SASS @extend. Pour citer Harry Roberts à ce sujet :
Vous pouvez créer un plus grand nombre de combinaisons dans la vue en ne "liant" pas les classes ensemble dans Sass. Le HTML a une bien meilleure trace papier dans la mesure où vous pouvez voir chaque classe agir sur un morceau du DOM. Votre CSS reste beaucoup plus mince dans la mesure où vous n'avez pas à créer de nouvelles classes d'espace réservé (ou les classes manifestes qui les combinent) chaque fois que vous souhaitez créer une nouvelle partie de l'interface utilisateur.
Conclusion
Quand j'ai vu le schéma de codage BEM pour la première fois, ma première pensée a été :
Ces cours sont tout simplement trop longs à écrire et à lire.
Mais après l'avoir essayé, je ne peux plus imaginer commencer un nouveau projet sans l'utiliser. Pour moi, BEM a considérablement amélioré la maintenabilité de mon code, et je peux dire avec certitude que chaque développeur qui va être "jeté" dans le projet basé sur BEM rattrapera très rapidement l'ensemble de la structure du code.
Malgré tout cela, il y a beaucoup de discussions sur les réseaux sociaux à propos de BEM. Certains disent que BEM n'est pas bon, se demandant pourquoi ils devraient écrire des classes de noms aussi longs au lieu de simplement utiliser des éléments imbriqués HTML par défaut. Eh bien, personne ne dit que vous devez aimer BEM, mais le fait est que la majorité des développeurs frontaux l'adoptent et le trouvent extrêmement utile.