BEM pour les débutants : pourquoi vous avez besoin de BEM
Publié: 2022-03-10BEM rend votre code évolutif et réutilisable, augmentant ainsi la productivité et facilitant le travail d'équipe. Même si vous êtes le seul membre de l'équipe, BEM peut vous être utile. Néanmoins, de nombreux développeurs pensent qu'une approche système telle que BEM impose des limites supplémentaires à leur projet et rend votre projet surchargé, lourd et lent.
Nous rassemblerons tous les principaux aspects de BEM sous une forme condensée. Cet article vous aide à comprendre les idées de base de BEM en seulement 20 minutes, et à rejeter les préjugés selon lesquels l'approche système est préjudiciable à votre projet.
Le Big BEM comprend la méthodologie , les technologies , les bibliothèques et les outils . Dans cet article, nous parlerons davantage de la méthodologie elle-même car c'est l'expérience concentrée d'un grand nombre de développeurs et elle apporte une approche systématique à tout projet.
Afin de vous montrer quelques cas pratiques de BEM, nous allons aborder les technologies BEM et ignorer complètement les bibliothèques et les outils.
De la théorie à la pratique :
- Les principales raisons pour lesquelles nous n'utilisons aucun sélecteur à l'exception des classes
- Les bases du BEM
- Blocs et éléments
- Modificateurs et mélanges
- Blocs dans la structure de fichiers
- Avantages non évidents de la méthodologie
- Cas pratique : BEM n'est pas réservé qu'aux CSS
- BEM est un système personnalisable
Alors, BEM est-il un héros ou un méchant ? C'est à vous! Mais d'abord, lisez l'article.
Les principales raisons pour lesquelles nous n'utilisons aucun sélecteur à l'exception des classes
L'une des règles de base de la méthodologie BEM est de n'utiliser que des sélecteurs de classe. Dans cette section, nous vous expliquerons pourquoi.
- Pourquoi n'utilisons-nous pas d'identifiants ?
- Pourquoi n'utilisons-nous pas de sélecteurs de balises ?
- Pourquoi n'utilisons-nous pas un sélecteur universel ?
- Pourquoi n'utilisons-nous pas la réinitialisation CSS ?
- Pourquoi n'utilisons-nous pas de sélecteurs imbriqués ?
- Pourquoi ne pas combiner une balise et une classe dans un sélecteur ?
- Pourquoi n'utilisons-nous pas des sélecteurs combinés-
- Pourquoi n'utilisons-nous pas de sélecteurs d'attributs ?
Nous n'utilisons pas d'identifiants (sélecteur d'identifiants)
L'ID fournit un nom unique pour un élément HTML. Si le nom est unique, vous ne pouvez pas le réutiliser dans l'interface. Cela vous empêche de réutiliser le code.
Erreur commune
- Les identifiants sont nécessaires pour utiliser JavaScript.
Les navigateurs modernes peuvent fonctionner avec des identifiants ou des classes. Tout type de sélecteur est traité au même rythme dans le navigateur. - Les ID sont utilisés avec la
<label>
.
Si vous placez<label>
dans un contrôle, il n'a pas besoin d'ID. Au lieu de<input id="ID"><label for="ID">Text</label>
, utilisez simplement<label><input type="...">Text</label>
.
Nous n'utilisons pas de sélecteurs de balises
Le balisage de la page HTML est instable : un nouveau design peut modifier l'imbrication des sections, les niveaux d'en-tête (par exemple, de <h1>
à <h3>
) ou transformer le paragraphe <p>
en <div>
. N'importe lequel de ces changements cassera les styles écrits pour les balises. Même si la conception ne change pas, l'ensemble de balises est limité. Pour utiliser une mise en page existante dans un autre projet, vous devez résoudre les conflits entre les styles écrits pour les mêmes balises.
Un ensemble étendu de balises sémantiques ne peut pas non plus répondre à tous les besoins de mise en page.
Un exemple est lorsque l'en-tête de la page contient un logo. Un clic sur le logo ouvre la page principale du site ( index
). Vous pouvez le marquer avec des balises en utilisant la <img>
pour l'image et la balise <a>
pour le lien.
<header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>
Pour faire la distinction entre le lien du logo et un lien ordinaire dans le texte, vous avez besoin de styles supplémentaires. Supprimez maintenant le soulignement et la couleur bleue du lien du logo :
header a { ... }
Le lien du logo n'a pas besoin d'être affiché sur la page principale, alors modifiez le balisage de la page d'index :
<header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>
Vous n'avez pas besoin de supprimer le soulignement et la couleur bleue de la <span>
. Établissons donc des règles générales pour le lien du logo à partir de différentes pages :
header a, header span { ... }
À première vue, ce code semble correct, mais imaginez si le concepteur supprime le logo de la mise en page. Les noms des sélecteurs ne vous aident pas à comprendre quels styles doivent être supprimés du projet avec le logo. Le sélecteur "en-tête a" n'affiche pas le lien entre le lien et le logo. Ce sélecteur pourrait appartenir au lien dans le menu d'en-tête ou, par exemple, au lien vers le profil de l'auteur. Le sélecteur "header span" peut appartenir à n'importe quelle partie de l'en-tête.
Pour éviter toute confusion, utilisez simplement le sélecteur de classe de logo
pour écrire les styles de logo :
.logo { ... }
Nous n'utilisons pas la réinitialisation CSS
La réinitialisation CSS est un ensemble de règles CSS globales créées pour l'ensemble de la page. Ces styles affectent tous les nœuds de mise en page, violent l'indépendance des composants et rendent plus difficile leur réutilisation.
Dans BEM, "réinitialiser" et "normaliser" ne sont même pas utilisés pour un seul bloc. La réinitialisation et la normalisation annulent les styles existants et les remplacent par d'autres styles, que vous devrez modifier et mettre à jour ultérieurement dans tous les cas. Par conséquent, le développeur doit écrire des styles qui remplacent ceux qui viennent d'être réinitialisés.
Nous n'utilisons pas le sélecteur universel ( *
)
Le sélecteur universel indique que le projet comporte un style qui affecte tous les nœuds de la mise en page. Cela limite la réutilisation de la mise en page dans d'autres projets :
- Vous devez également transférer les styles avec un astérisque dans le projet. Mais dans ce cas, le sélecteur universel peut affecter les styles du nouveau projet.
- Les styles avec un astérisque doivent être ajoutés à la mise en page que vous transférez.
De plus, un sélecteur universel peut rendre le code du projet imprévisible. Par exemple, cela peut affecter les styles des composants de la bibliothèque universelle.
Les styles courants ne vous font pas gagner de temps. Souvent, les développeurs commencent par réinitialiser toutes les marges des composants ( * { margin: 0; padding: 0; }
), mais ils les définissent ensuite de la même manière que dans la mise en page (par exemple, margin: 12px; padding: 30px;
).
Nous n'utilisons pas de sélecteurs imbriqués
Les sélecteurs imbriqués augmentent le couplage de code et rendent difficile la réutilisation du code.
La méthodologie BEM n'interdit pas les sélecteurs imbriqués, mais elle recommande de ne pas trop les utiliser. Par exemple, l'imbrication est appropriée si vous devez modifier les styles des éléments en fonction de l'état du bloc ou du thème qui lui est attribué.
.button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }
Nous n'utilisons pas de sélecteurs combinés
Les sélecteurs combinés sont plus spécifiques que les sélecteurs simples, ce qui rend plus difficile la redéfinition des blocs.
Considérez le code suivant :
<button class="button button_theme_islands">...</button>
Supposons que vous définissiez des règles CSS dans le sélecteur .button.button_theme_islands
pour faire moins d'écriture. Ensuite, vous ajoutez le modificateur "actif" au bloc :
<button class="button button_theme_islands button_active">...</button>
Le sélecteur .button_active
ne redéfinit pas les propriétés de bloc écrites comme .button.button_theme_islands
car .button.button_theme_islands
est plus spécifique que .button_active
. Pour le redéfinir, combinez le sélecteur de modificateur de bloc avec le sélecteur .button
et déclarez-le sous le .button.button_theme_islands
car les deux sélecteurs sont également spécifiques :
.button.button_theme_islands {} .button.button_active {}
Si vous utilisez des sélecteurs de classe simples, vous n'aurez aucun problème à redéfinir les styles :
.button_theme_islands {} .button_active {} .button {}
Nous ne combinons pas une balise et une classe dans un sélecteur
Combiner une balise et une classe dans le même sélecteur (par exemple, button.button
) rend les règles CSS plus spécifiques, il est donc plus difficile de les redéfinir.
Considérez le code suivant :
<button class="button">...</button>
Supposons que vous définissiez des règles CSS dans le sélecteur button.button
. Ensuite, vous ajoutez le modificateur active
au bloc :
<button class="button button_active">...</button>
Le sélecteur .button_active
ne redéfinit pas les propriétés de bloc écrites comme button.button
car button.button
est plus spécifique que .button_active
. Pour le rendre plus spécifique, vous devez combiner le sélecteur de modificateur de bloc avec la balise button.button_active
.
Au fur et à mesure que le projet se développe, vous pourriez vous retrouver avec des blocs avec input.button
, span.button
ou a.button
. Dans ce cas, tous les modificateurs du bloc de button
et tous ses éléments imbriqués nécessiteront quatre déclarations différentes pour chaque instance.
Exceptions possibles
Dans de rares cas, la méthodologie permet de combiner des sélecteurs de balises et de classes. Par exemple, cela peut être utilisé pour définir le style des commentaires dans les systèmes CMS qui ne peuvent pas générer la mise en page correcte.
Vous pouvez utiliser le commentaire pour écrire un texte, insérer des images ou ajouter un balisage. Pour les faire correspondre à la conception du site, le développeur peut prédéfinir des styles pour toutes les balises disponibles pour l'utilisateur et les répercuter sur les blocs imbriqués :
<div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }
Nous n'utilisons pas de sélecteurs d'attributs
Les sélecteurs d'attribut sont moins informatifs que les sélecteurs de classe. Pour preuve, considérons un exemple avec un formulaire de recherche dans l'en-tête :
<header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>
Essayez d'utiliser les attributs de sélecteur pour écrire les styles de formulaire :
header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }
Dans cet exemple, vous ne pouvez pas dire avec certitude à partir du nom du sélecteur que les styles appartiennent au formulaire de recherche. L'utilisation de classes le rend plus clair. Les classes n'ont pas de restrictions qui vous empêchent d'écrire clairement. Par exemple, vous pouvez l'écrire comme ceci :
.form .search { ... }
Maintenant, le code est moins ambigu et il est clair que les styles appartiennent au formulaire de recherche.
Mais les sélecteurs imbriqués rendent toujours les règles CSS plus spécifiques et vous empêchent de transférer la mise en page entre les projets. Pour vous débarrasser de l'imbrication, utilisez les principes BEM.
Résumé : la class
est le seul sélecteur qui permet d'isoler les styles de chaque composant du projet ; augmentent la lisibilité du code et ne limitent pas la réutilisation de la mise en page.
L'isolement des styles CSS est le point de départ le plus fréquent du parcours BEM. Mais c'est le moins que BEM puisse vous offrir. Pour comprendre comment les composants indépendants isolés sont organisés dans BEM, vous devez apprendre les concepts de base, c'est-à-dire le bloc, l'élément, le modificateur et le mélange. Faisons cela dans la section suivante.
Les bases du BEM
- Blocs et éléments
- Modificateurs et mélanges
- Blocs dans la structure de fichiers
Bloc et éléments
La méthodologie BEM est un ensemble de règles universelles qui peuvent être appliquées quelles que soient les technologies utilisées, telles que CSS, Sass, HTML, JavaScript ou React.
BEM aide à résoudre les tâches suivantes :
- Réutilisez la mise en page ;
- Déplacez des fragments de mise en page dans un projet en toute sécurité ;
- Déplacez la mise en page finie entre les projets ;
- Créer un code stable, prévisible et clair ;
- Réduisez le temps de débogage du projet.
Dans un projet BEM, l'interface se compose de blocs pouvant inclure des éléments. Les blocs sont des composants indépendants de la page. Un élément ne peut pas exister en dehors du bloc, gardez donc à l'esprit que chaque élément ne peut appartenir qu'à un seul bloc.
Les deux premières lettres de BEM représentent les serrures B et les éléments E. Le nom du bloc est toujours unique. Il définit l'espace de noms des éléments et fournit une connexion visible entre les parties de bloc. Les noms de bloc sont longs mais clairs afin de montrer la connexion entre les composants et d'éviter de perdre des parties de ces composants lors du transfert de la mise en page.
Pour voir toute la puissance de la dénomination BEM, considérez cet exemple avec un formulaire. Selon la méthodologie BEM, le formulaire est implémenté à l'aide du bloc de form
. En HTML, le nom du bloc est inclus dans l'attribut class
:
<form class="form" action="/">
Toutes les parties du formulaire (le bloc de form
) qui n'ont pas de sens en elles-mêmes sont considérées comme ses éléments. Ainsi, la zone de recherche ( search
) et le bouton ( submit
) sont des éléments du bloc de form
. Les classes indiquent également qu'un élément appartient au bloc :
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Notez que le nom du bloc est séparé du nom de l'élément par un séparateur spécial. Dans le schéma de nommage classique BEM, deux traits de soulignement sont utilisés comme séparateur. Tout peut fonctionner comme séparateur. Il existe des conventions de nommage alternatives, et chaque développeur choisit celle qui lui convient. L'important est que les séparateurs vous permettent de distinguer les blocs des éléments et des modificateurs par programmation.
Les noms des sélecteurs indiquent clairement que pour déplacer le formulaire vers un autre projet, vous devez copier tous ses composants :
.form__search {} .form__submit {}
L'utilisation de blocs et d'éléments pour les noms de classe résout un problème important : cela nous aide à nous débarrasser des sélecteurs imbriqués. Tous les sélecteurs d'un projet BEM ont le même poids. Cela signifie qu'il est beaucoup plus facile de redéfinir les styles écrits selon BEM. Maintenant, pour utiliser le même formulaire dans un autre projet, vous pouvez simplement copier sa mise en page et ses styles.
L'idée de la dénomination des composants BEM est que vous pouvez définir explicitement la connexion entre le bloc et ses éléments.
Modificateurs et mélanges
Officiellement, « M » signifie Modifier, mais il implique également une notion plus importante dans BEM : « mix ». Les modificateurs et les mélanges apportent des modifications à un bloc et à ses éléments. Regardons cela de plus près.
Modificateurs
Un modificateur définit l'apparence, l'état et le comportement d'un bloc ou d'un élément. L'ajout de modificateurs est facultatif. Les modificateurs vous permettent de combiner différentes fonctionnalités de bloc, car vous pouvez utiliser n'importe quel nombre de modificateurs. Mais un bloc ou un élément ne peut pas se voir attribuer différentes valeurs du même modificateur.
Explorons comment fonctionnent les modificateurs.
Imaginez que le projet nécessite le même formulaire de recherche que dans l'exemple ci-dessus. Il doit avoir les mêmes fonctions mais avoir un aspect différent (par exemple, les formulaires de recherche dans l'en-tête et dans le pied de page doivent être différents). La première chose que vous pouvez faire pour changer l'apparence du formulaire est d'écrire des styles supplémentaires :
header .form {} footer .form {}
Le sélecteur d' header .form
a plus de poids que le sélecteur de form
, ce qui signifie qu'une règle remplacera l'autre. Mais comme nous en avons discuté, les sélecteurs imbriqués augmentent le couplage de code et rendent la réutilisation difficile, donc cette approche ne fonctionne pas pour nous.
Dans BEM, vous pouvez utiliser un modificateur pour ajouter de nouveaux styles au bloc :
<!-- Added the form_type_original modifier--> <form class="form form_type_original" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
La ligne <form class="form form_type_original"></form>
indique que le bloc s'est vu attribuer un modificateur de type
avec la valeur d' original
. Dans un schéma classique, le nom du modificateur est séparé du nom du bloc ou de l'élément par un trait de soulignement.
Le formulaire peut avoir une couleur, une taille, un type ou un thème de conception unique. Tous ces paramètres peuvent être définis avec un modificateur :
<form class="form form_type_original form_size_m form_theme_forest">
<form class="form form_type_original form_size_m form_theme_forest">
Le même formulaire peut avoir un aspect différent mais conserver la même taille :
<form class="form form_type_original form_size_m form_theme_forest"></form> <form class="form form_type_original form_size_m form_theme_sun"></form>
Mais les sélecteurs de chaque modificateur auront toujours le même poids :
.form_type_original {} .form_size_m {} .form_theme_forest {}
Important : Un modificateur ne contient que des styles supplémentaires qui modifient d'une manière ou d'une autre l'implémentation du bloc d'origine. Cela vous permet de définir l'apparence d'un bloc universel une seule fois et d'ajouter uniquement les fonctionnalités qui diffèrent du code de bloc d'origine dans les styles de modificateur.
.form { /* universal block styles */ } .form_type_original { /* added styles */ }
C'est pourquoi un modificateur doit toujours être sur le même nœud DOM avec le bloc et l'élément auquel il est associé.
<form class="form form_type_original"></form>
Vous pouvez utiliser des modificateurs pour appliquer des composants universels dans des cas très spécifiques. Le code du bloc et de l'élément ne change pas. La combinaison nécessaire de modificateurs est créée sur le nœud DOM.
Mélanges
Un mix permet d'appliquer la même mise en forme à différents éléments HTML et de combiner le comportement et les styles de plusieurs entités tout en évitant la duplication de code. Ils peuvent remplacer les blocs wrapper abstraits.
Un mix signifie que vous hébergez plusieurs entités BEM (blocs, éléments, modificateurs) sur un seul nœud DOM. Semblables aux modificateurs, les mélanges sont utilisés pour changer de bloc. Regardons quelques exemples de cas où vous devriez utiliser un mélange.
Les blocs peuvent différer non seulement visuellement mais aussi sémantiquement. Par exemple, un formulaire de recherche, un formulaire d'inscription et un formulaire de commande de gâteaux sont tous des formulaires. Dans la mise en page, ils sont implémentés avec le bloc "formulaire" mais ils n'ont aucun style en commun. Il est impossible de gérer de telles différences avec un modificateur. Vous pouvez définir des styles communs pour ces blocs mais vous ne pourrez pas réutiliser le code.
.form, .search, .register { ... }
Vous pouvez utiliser un mélange pour créer des blocs sémantiquement différents pour le même formulaire :
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Le sélecteur de classe .form
décrit tous les styles pouvant être appliqués à n'importe quel formulaire (commande, recherche ou inscription) :
.form {}
Vous pouvez maintenant créer un formulaire de recherche à partir du formulaire universel. Pour ce faire, créez une classe de search
supplémentaire dans le projet. Cette classe ne sera responsable que de la recherche. Pour combiner les styles et le comportement des classes .form
et .search
, placez ces classes sur un seul nœud DOM :
<form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Dans ce cas, la classe .search
est un bloc séparé qui définit le comportement. Ce bloc ne peut pas avoir de modificateurs responsables de la forme, des thèmes et des tailles. Ces modificateurs appartiennent déjà à la forme universelle. Un mélange permet de combiner les styles et le comportement de ces blocs.
Prenons un autre exemple où la sémantique du composant est modifiée. Voici un menu de navigation dans l'en-tête de page dans lequel toutes les entrées sont des liens :
<nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>
La fonctionnalité de lien est déjà implémentée dans le bloc de link
, mais les liens de menu doivent différer visuellement des liens dans le texte. Il existe plusieurs façons de modifier les liens du menu :
- Créez un modificateur d'entrée de menu qui transforme l'entrée en lien :
<nav class="menu"> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> </nav>
Dans ce cas, pour implémenter le modificateur, vous devez copier le comportement et les styles du bloc `link`. Cela entraînera une duplication de code. - Utilisez un mélange du bloc universel `link` et de l'élément `item` du bloc `menu` :
<nav class="menu"> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> </nav>
Avec le mélange des deux entités BEM, vous pouvez désormais implémenter la fonctionnalité de lien de base à partir du bloc `link` et des règles CSS supplémentaires à partir du bloc `menu`, et éviter la duplication de code.
Géométrie externe et positionnement : abandonner les wrappers HTML abstraits
Les mélanges sont utilisés pour positionner un bloc par rapport à d'autres blocs ou pour positionner des éléments à l'intérieur d'un bloc. Dans BEM, les styles responsables de la géométrie et du positionnement sont définis dans le bloc parent. Prenons un bloc de menu universel qui doit être placé dans l'en-tête. Dans la mise en page, le bloc doit avoir un retrait de 20 px par rapport au bloc parent.
Cette tâche a plusieurs solutions :
- Styles d'écriture avec retraits pour le bloc de menu :
.menu { margin-left: 20px; }
Dans ce cas, le bloc "menu" n'est plus universel. Si vous devez placer le menu dans le pied de page, vous devrez modifier les styles car les retraits seront probablement différents. - Créez le modificateur de bloc de menu :
<div> <ul class="menu menu_type_header"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
.menu_type_header { margin-left: 20px; } .menu_type_footer { margin-left: 30px; }
Dans ce cas, le projet comprendra deux types de menus, bien que ce ne soit pas le cas. Le menu reste le même. - Définissez le positionnement externe du bloc : imbriquez le bloc `menu` dans le wrapper abstrait (par exemple, le bloc `wrap`) en définissant tous les retraits :
<div class="wrap"> <ul class="menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
Pour éviter la tentation de créer des modificateurs et de changer les styles de bloc pour positionner le bloc sur la page, vous devez comprendre une chose :L'indentation d'un bloc parent n'est pas une fonctionnalité du bloc imbriqué. C'est une caractéristique du bloc parent. Il doit savoir que le bloc imbriqué doit être en retrait de la bordure d'un certain nombre de pixels.
- Utilisez un mélange. Les informations sur le positionnement des blocs imbriqués sont incluses dans les éléments du bloc parent. Ensuite, l'élément de bloc parent est mélangé dans le bloc imbriqué. Dans ce cas, le bloc imbriqué ne spécifie aucun retrait et peut être facilement réutilisé n'importe où.
Continuons avec notre exemple :
<div> <ul class="menu header__menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
Dans ce cas, la géométrie externe et le positionnement du bloc de menu
sont définis via l'élément header__menu
. Le bloc de menu
ne spécifie aucun retrait et peut être facilement réutilisé.
L'élément de bloc parent (dans notre cas, il s'agit header__menu
) exécute la tâche des blocs wrapper responsables du positionnement externe du bloc.
Blocs dans la structure de fichiers
Tous les projets BEM ont une structure de fichiers similaire. La structure de fichiers familière permet aux développeurs de naviguer plus facilement dans le projet, de basculer entre les projets et de déplacer des blocs d'un projet à un autre.
L'implémentation de chaque bloc est stockée dans un dossier de projet séparé. Chaque technologie (CSS, JavaScript, tests, templates, documentation, images) est dans un fichier séparé.
Par exemple, si l'apparence du bloc input
est définie avec CSS, le code est enregistré dans le fichier input.css
.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript
Le code des modificateurs et des éléments est également stocké dans des fichiers séparés du bloc. Cette approche vous permet d'inclure dans la construction uniquement les modificateurs et éléments nécessaires à l'implémentation du bloc.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript input_theme_sun.css # The "input_theme_sun" modifier implementation input__clear.css # The "input__clear" element implementation with CSS input__clear.js # The "input__clear" element implementation with JavaScript
Pour améliorer la navigation dans le projet, combinez des modificateurs de bloc avec plusieurs valeurs dans des répertoires.
La structure de fichiers de tout projet BEM se compose de niveaux de redéfinition (vous pouvez en savoir plus ici). Les niveaux de redéfinition vous permettent de :
- Diviser le projet en plateformes ;
- Mettez facilement à jour les bibliothèques de blocs incluses dans le projet ;
- Utiliser des blocs communs pour développer plusieurs projets ;
- Changez les thèmes de conception sans affecter la logique du projet ;
- Mener des expériences dans un projet en direct.
L'utilisation de blocs et le stockage de toutes les technologies de blocs dans le même dossier facilitent le déplacement des blocs entre les projets. Pour déplacer tous les styles et comportements du bloc avec la mise en page, copiez simplement le dossier du bloc dans le nouveau projet.
Avantages non évidents de la méthodologie
La commodité du développement parallèle
Dans BEM, toute mise en page est divisée en blocs. Les blocs étant indépendants, ils peuvent être développés en parallèle par plusieurs développeurs.
Un développeur crée un bloc en tant que composant universel qui peut être réutilisé dans n'importe quel autre projet.
Un exemple est la bibliothèque de blocs bem-components, qui contient des blocs universels, tels qu'un lien, un bouton et un champ de saisie. Il est plus facile de créer des blocs plus complexes à partir de composants universels. Par exemple, un sélecteur ou une case à cocher.
L'utilisation de blocs dans la mise en page du projet vous permet de gagner du temps lors de l'intégration de code écrit par plusieurs développeurs, garantit l'unicité des noms de composants et vous permet de tester les blocs au stade du développement.
Tester la mise en page
Il est problématique de tester la fonctionnalité de toute la page, surtout dans un projet dynamique connecté à une base de données.
Dans BEM, chaque bloc est couvert par des tests. Les tests sont une technologie d'implémentation de blocs, comme Javascript ou CSS. Les blocs sont testés au stade du développement. Il est plus facile de vérifier l'exactitude d'un bloc, puis d'assembler le projet à partir de blocs testés. Après cela, tout ce que vous avez à faire est de vous assurer que le wrapper de bloc fonctionne correctement.
Construction personnalisable d'un projet
Pour un développement pratique, tous les blocs et technologies d'un projet BEM sont placés dans des dossiers et fichiers séparés. Pour combiner les fichiers sources en un seul fichier (par exemple, pour mettre tous les fichiers CSS dans project.css
, tous les fichiers JS dans project.js
, etc.), nous utilisons le processus de génération.
La compilation effectue les tâches suivantes :
- Combine les fichiers source qui sont répartis sur le système de fichiers du projet ;
- Inclut uniquement les blocs, éléments et modificateurs nécessaires (entités BEM) dans le projet ;
- Suit l'ordre d'inclusion des entités ;
- Traite le code du fichier source pendant la construction (par exemple, compile le code LESS en code CSS).
Pour inclure uniquement les entités BEM nécessaires dans la construction, vous devez créer une liste de blocs, d'éléments et de modificateurs utilisés sur les pages. Cette liste s'appelle une déclaration .
Étant donné que les blocs BEM sont développés indépendamment et placés dans des fichiers séparés dans le système de fichiers, ils ne "savent" rien les uns des autres. Pour créer des blocs basés sur d'autres blocs, spécifiez les dépendances. Il existe une technologie BEM responsable de cela : les fichiers deps.js
Les fichiers de dépendance permettent au moteur de génération de savoir quels blocs supplémentaires doivent être inclus dans le projet.
Cas pratique : BEM n'est pas réservé qu'aux CSS
Dans les sections précédentes, tous les exemples de code sont pour CSS. Mais BEM permet de modifier le comportement du bloc et sa représentation en HTML de la même manière déclarative qu'en CSS.
Comment utiliser les modèles dans BEM
En HTML, le balisage de bloc est répété chaque fois que le bloc apparaît sur la page. Si vous créez le balisage HTML manuellement et que vous devez ensuite corriger une erreur ou apporter des modifications, vous devrez modifier le balisage pour chaque instance du bloc. Pour générer du code HTML et appliquer automatiquement les correctifs, BEM utilise des modèles ; les blocs sont responsables de la façon dont ils sont présentés en HTML.
Les modèles vous permettent de :
- Réduisez le temps utilisé pour le débogage du projet, car les modifications du modèle sont automatiquement appliquées à tous les blocs du projet ;
- Modifier la disposition des blocs ;
- Déplacez les blocs avec la mise en page actuelle vers un autre projet.
BEM utilise le moteur de template bem-xjst qui comporte deux moteurs :
- BEMHTML
Transforme la description BEMJSON de la page en HTML. Les modèles sont décrits dans les fichiers .bemhtml.js. - BEMTREE
Transforme les données en BEMJSON. Les modèles sont décrits au format BEMJSON dans des fichiers .bemtree.js .
Si les modèles ne sont pas écrits pour les blocs, le moteur de modèles définit la <div>
pour les blocs par défaut.
Comparez la déclaration des blocs et la sortie HTML :
Déclaration:
{ block: 'menu', content: [ { elem: 'item', content: { block: 'link'} }, { elem: 'item', elemMods: { current: true }, // Set the modifier for the menu item content: { block: 'link' } } ] }
HTML :
<div class="menu"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div>
Pour modifier la disposition du bloc de menu
, vous devez écrire des modèles pour le bloc :
- Modifions la balise du bloc de
menu
:block('menu')( tag()('menu') // Set the "menu" tag for the menu block )
HTML modifié :<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </menu>
Semblable au CSS, le modèle est appliqué à tous les blocs "menu" de la page. - Ajoutez un élément supplémentaire (
menu__inner
) qui fonctionne comme un wrapper interne et est responsable de la disposition des éléments dans le bloc demenu
. À l'origine, l'élémentmenu__inner
n'était pas inclus dans la déclaration, nous devons donc l'ajouter lors de la construction des modèles.
Les modèles BEM sont écrits en JavaScript, vous pouvez donc également utiliser JavaScript pour ajouter un nouvel élément au modèle :block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content }; }) )
<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__inner"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div> </menu>
- Remplacez les balises pour tous les éléments
inner
etitem
:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) )
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <div class="link"></div> </li> <li class="menu__item menu__item_current"> <div class="link"></div> </li> </ul> </menu>
- Définissez la balise
<a>
pour tous les liens de la page :block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) ); block('link')( tag()('a') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <a class="link"></a> </li> <li class="menu__item menu__item_current"> <a class="link"></a> </li> </ul> </menu>
- Modifiez le modèle existant. Les règles dans les modèles sont appliquées de la même manière que dans CSS : une règle inférieure remplace une règle supérieure. Ajoutez de nouvelles règles au modèle et changez la balise de lien de
<a>
à<span>
:block('link')( tag()('a') ); block('link')( tag()('span') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <span class="link"></span> </li> <li class="menu__item menu__item_current"> <span class="link"></span> </li> </ul> </menu>
BEM est un système personnalisable
La méthodologie BEM vous fournit des règles strictes pour créer un système dans votre projet. Mais en même temps, de nombreuses règles BEM peuvent être personnalisées. La méthodologie BEM vous permet de modifier la convention de dénomination, de choisir la structure de fichier la plus pratique ou d'ajouter les technologies de votre choix au bloc.
Vous pouvez maintenant vous connecter au système et créer votre propre super-héros de BEM !
Comment tirer le meilleur parti de BEM
Pour commencer à apprendre les principes BEM, visitez notre site Web. Si vous avez des questions à poser à l'équipe, rejoignez notre chaîne Telegram ou ouvrez une discussion sur notre forum BEM.