BEM vs Tailwind : Pourquoi j'ai choisi BEM pour mon CSS
Découvrez pourquoi la méthodologie BEM reste une approche supérieure à Tailwind CSS pour construire des interfaces maintenables, accessibles et performantes.
Le problème du CSS moderne
Le CSS est un langage puissant mais qui peut rapidement devenir ingérable dans des projets de grande envergure. Deux approches dominent aujourd’hui le paysage : Tailwind CSS (utility-first) et BEM (Block Element Modifier).
Après avoir utilisé les deux en production, j’ai fait mon choix. Voici pourquoi.
Qu’est-ce que BEM ?
BEM signifie Block, Element, Modifier. C’est une méthodologie de nommage créée par Yandex qui impose une structure claire à votre CSS.
La syntaxe
/* Block : composant autonome */
.card { }
/* Element : partie du block (double underscore) */
.card__title { }
.card__image { }
.card__button { }
/* Modifier : variation (double tiret) */
.card--featured { }
.card--compact { }
.card__button--disabled { }
Exemple concret
<article class="card card--featured">
<img class="card__image" src="..." alt="..." />
<h2 class="card__title">Mon article</h2>
<p class="card__description">Une description concise.</p>
<a class="card__button card__button--primary" href="#">Lire plus</a>
</article>
.card {
display: flex;
flex-direction: column;
gap: var(--space-md);
padding: var(--space-lg);
border: 1px solid var(--color-border);
border-radius: 8px;
}
.card--featured {
border-color: var(--color-accent);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card__title {
font-family: var(--font-heading);
font-size: var(--text-xl);
}
.card__button {
display: inline-block;
padding: var(--space-sm) var(--space-md);
background: var(--color-accent);
color: var(--color-bg);
border: none;
border-radius: 4px;
}
.card__button--primary {
background: var(--color-accent);
}
Les avantages de BEM
1. Spécificité CSS prévisible
Avec BEM, chaque sélecteur a une spécificité de 0-1-0 (une seule classe). Pas de cascade imprévisible, pas de !important nécessaire.
/* BEM : toujours 1 classe = spécificité 0-1-0 */
.card { } /* 0-1-0 */
.card__title { } /* 0-1-0 */
.card--featured { } /* 0-1-0 */
Comparez avec Tailwind où la surcharge nécessite des hacks :
<!-- Tailwind : besoin de !important ou d'ordre spécifique -->
<div class="bg-red-500 hover:bg-blue-500">
2. Séparation des préoccupations
BEM sépare structure (HTML) et style (CSS). Votre HTML reste propre et sémantique.
<!-- BEM : HTML lisible -->
<nav class="nav">
<a class="nav__link nav__link--active" href="/">Accueil</a>
<a class="nav__link" href="/projets">Projets</a>
</nav>
<!-- Tailwind : HTML pollué -->
<nav class="flex gap-4 p-4 bg-white border-b">
<a class="px-3 py-1 text-sm font-medium text-gray-900 border-b-2 border-red-500" href="/">Accueil</a>
<a class="px-3 py-1 text-sm font-medium text-gray-500 hover:text-gray-900" href="/projets">Projets</a>
</nav>
3. Design tokens natifs
BEM s’intègre parfaitement avec les custom properties CSS pour créer un design system cohérent.
:root {
--color-accent: #C41E3A;
--space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
--font-heading: ui-serif, Georgia, serif;
}
.card {
gap: var(--space-md);
border-color: var(--color-border);
}
Avec Tailwind, vous devez configurer tailwind.config.js et recompiler à chaque changement.
4. Pas de build step
BEM fonctionne avec du CSS pur. Aucun outil de build, aucun PostCSS, aucune dépendance.
# BEM : rien à installer
# Écrivez du CSS, c'est tout.
# Tailwind : chaîne de build complète
npm install tailwindcss postcss autoprefixer
npx tailwindcss init
# + configuration postcss.config.js
# + compilation à chaque changement
5. Taille CSS prévisible
Avec BEM, vous n’écrivez que le CSS dont vous avez besoin. Votre fichier CSS final fait 5-10 KB pour un portfolio.
Tailwind génère un fichier CSS de 50-100 KB même avec PurgeCSS, car il inclut toutes les variantes (hover, focus, responsive) que vous n’utilisez pas.
6. Accessibilité intégrée
BEM encourage une structure HTML sémantique car le CSS ne dicte pas le markup.
<!-- BEM : HTML sémantique naturel -->
<header class="header">
<nav class="header__nav" aria-label="Navigation">
<a class="header__link header__link--active" href="/">Accueil</a>
</nav>
</header>
<!-- Tailwind : tentation de div-iser tout -->
<div class="flex justify-between items-center p-4 bg-white">
<div class="flex gap-4">
<a class="text-sm font-medium text-gray-900" href="/">Accueil</a>
</div>
</div>
7. Maintenance à long terme
Après 2 ans, un projet BEM reste compréhensible. Chaque classe indique clairement sa fonction et son contexte.
/* BEM : on sait exactement à quoi sert chaque règle */
.project__image { } /* Image d'un projet */
.project__image--large { } /* Variante large */
/* Tailwind : après 6 mois, bon courage */
<!-- Que fait cette classe exactement ? -->
<div class="w-full h-64 object-cover rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300">
Les limites de Tailwind
1. HTML illisible
<!-- Un simple bouton -->
<button class="inline-flex items-center justify-center px-6 py-3 text-base font-medium text-white bg-red-600 rounded-lg shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200">
Cliquer ici
</button>
2. Couplage fort HTML/CSS
Changer le design nécessite de modifier le HTML. Impossible de créer un thème alternatif sans toucher au markup.
3. Classes utilitaires ≠ composants
Tailwind vous donne des briques, pas des composants. Vous finissez par recréer des patterns BEM… dans votre HTML.
<!-- Ce "composant" bouton se répète partout -->
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
<button class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600">
<button class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600">
4. Faux sentiment de productivité
Tailwind semble rapide au début, mais la complexité cognitive augmente avec la taille du projet. Retrouver où un style est appliqué devient un cauchemar.
Quand utiliser Tailwind ?
Tailwind n’est pas “mauvais”. Il a sa place dans certains contextes :
- Prototypage rapide : quand la vitesse prime sur la maintenance
- Projets jetables : landing pages one-shot, démos
- Équipes sans designer : quand chaque développeur doit “faire son propre CSS”
Mais pour un produit maintenu sur le long terme, BEM reste supérieur.
Conclusion
| Critère | BEM | Tailwind |
|---|---|---|
| Lisibilité HTML | ✅ Classes sémantiques | ❌ Classes utilitaires |
| Spécificité | ✅ Prévisible (0-1-0) | ⚠️ Dépend de l’ordre |
| Build step | ✅ Aucun | ❌ PostCSS requis |
| Taille CSS | ✅ 5-10 KB | ⚠️ 50-100 KB |
| Maintenance | ✅ Excellente | ⚠️ Difficile à long terme |
| Design tokens | ✅ Natif (custom properties) | ⚠️ Config requise |
| Accessibilité | ✅ HTML sémantique | ⚠️ Tentation des div |
| Prototypage | ⚠️ Plus lent | ✅ Très rapide |
BEM n’est pas une technologie, c’est une discipline. Elle vous force à penser vos composants avant de les coder. Et c’est exactement ce dont un projet a besoin pour rester maintenable.