Niveau 24 — Architecture CSS

L'Architecture CSS

Organisez votre CSS comme un pro : BEM, SMACSS, ITCSS, OOCSS, CUBE CSS, Atomic CSS… Découvrez les méthodologies qui transforment un fouillis de styles en un système maintenable et scalable.

1. Pourquoi l'architecture CSS ?

En une phrase : L'architecture CSS est un ensemble de conventions, de patterns et de méthodologies qui permettent d'organiser les feuilles de style pour les rendre maintenables, lisibles et scalables sur des projets de toute taille.

Sans architecture, un projet CSS devient rapidement un cauchemar de maintenabilité. Les sélecteurs se contournent, les spécificités explosent, les classes sont nommées de façon aléatoire, et chaque modification risque de casser quelque chose d'autre.

Pourquoi ça compte

Sans architecture Avec architecture
Classes nommées au hasard (.red, .big, .box2) Classes sémantiques et prévisibles (.card__title, .btn--primary)
Sélecteurs ultra-spcifiques (#main > div:nth-child(3) .title) Sélecteurs plats et modulaires (.card__title)
Duplication massive de styles Composants réutilisables, DRY
Fichier CSS monolithique de 5000 lignes Fichiers modulaires et ciblés
Peur de toucher au CSS Confiance dans les modifications
Conflits entre développeurs Conventions claires, travail en équipe fluide
Conseil : L'architecture CSS n'est pas une option — c'est une nécessité dès que votre projet dépasse quelques centaines de lignes de CSS. Même un petit projet bénéficie de conventions claires.

2. Les méthodologies CSS en détail

2.1 BEM — Block Element Modifier

Définition : BEM est une convention de nommage qui organise le CSS en blocs (composants autonomes), éléments (parties d'un bloc) et modificateurs (variantes ou états). C'est la méthodologie la plus populaire au monde.

Règles de nommage BEM

/* Structure : bloc__element--modificateur */

/* BLOC — composant autonome */
.card { }

/* ÉLÉMENT — partie du bloc (double underscore __) */
.card__header { }
.card__body { }
.card__footer { }
.card__title { }
.card__image { }

/* MODIFICATEUR — variante ou état (double tiret --) */
.card--featured { }
.card--dark { }
.card--compact { }

/* ÉLÉMENT + MODIFICATEUR */
.card__title--large { }
.card__button--disabled { }

Exemples concrets de noms BEM

Blocs
.navigation .form .header .sidebar .modal
Éléments
.navigation__item .form__input .header__logo .sidebar__menu .modal__title
Modificateurs
.navigation__item--active .form__input--error .header--sticky .sidebar--collapsed .modal--open
Erreurs BEM courantes :
/* ❌ Trop de profondeur — max 3 niveaux */
.page__content__card__header__title { }

/* ✅ Suffisant */
.card__title { }

/* ❌ Modificateur sans bloc */
.--active { }
__title { }

/* ✅ Toujours avec le bloc parent */
.card--active { }
.card__title { }

/* ❌ Élément qui existe seul */
.user { }        /* pas de .user__ ? Ce n'est pas un élément */
.user__avatar { } /* OK — avatar est un élément de user */
Règles d'or pour BEM :
  • Ne jamais imbriquer plus de 3 niveaux (.bloc__el__el--mod max)
  • Un élément ne peut exister que dans son bloc parent
  • Un modificateur ne change qu'une apparence, pas la structure
  • Utiliser des noms sémantiques, pas visuels (.card__title, pas .card__big-text)
  • Le séparateur de mots est le tiret simple - (kebab-case)

Exemple BEM complet — HTML + CSS

HTML

<article class="card card--featured">
  <div class="card__image">
    <img src="photo.jpg" alt="...">
    <span class="card__badge card__badge--new">
      Nouveau
    </span>
  </div>
  <div class="card__content">
    <h3 class="card__title">Titre</h3>
    <p class="card__text">Description</p>
    <div class="card__meta">
      <span class="card__date">12 mars</span>
      <span class="card__author">Jean</span>
    </div>
  </div>
  <div class="card__footer">
    <button class="card__btn card__btn--primary">
      Lire
    </button>
    <button class="card__btn card__btn--ghost">
      Partager
    </button>
  </div>
</article>

Rendu

Nouveau

Titre de la carte

Description du contenu avec les éléments BEM bien organisés.

12 mars · Jean

Correspondance CSS BEM

/* BLOC */
.card {
  border: 2px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
  background: white;
}

/* MODIFICATEUR de bloc */
.card--featured {
  border-color: #2563eb;
}

/* ÉLÉMENTS */
.card__image {
  position: relative;
  height: 200px;
  background: linear-gradient(135deg, #2563eb, #7c3aed);
}

.card__content { padding: 1.5rem; }
.card__title { margin: 0 0 0.5rem; font-size: 1.25rem; }
.card__text { color: #64748b; margin: 0 0 1rem; line-height: 1.6; }
.card__meta { display: flex; gap: 0.5rem; font-size: 0.8rem; color: #94a3b8; }

.card__footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid #e2e8f0;
  display: flex;
  gap: 0.5rem;
}

/* ÉLÉMENTS + MODIFICATEURS */
.card__badge {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  padding: 0.25rem 0.75rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.card__badge--new { background: #2563eb; color: white; }

.card__btn {
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 600;
}

.card__btn--primary { background: #2563eb; color: white; }
.card__btn--ghost { background: transparent; color: #2563eb; }

2.2 SMACSS — Scalable and Modular Architecture for CSS

Définition : SMACSS (Jonathan Snook) catégorise chaque règle CSS en 5 catégories : Base, Layout, Module, State et Theme. C'est un cadre plus qu'une convention de nommage.
/* ============================================
   SMACSS — Les 5 catégories
   ============================================ */

/* 1. BASE — Reset et styles par défaut des éléments */
body { font-family: sans-serif; }
h1, h2, h3 { margin: 0; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

/* 2. LAYOUT — Structure de la page (préfixe: l-) */
.l-header { }
.l-sidebar { }
.l-content { }
.l-footer { }
.l-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
}

/* 3. MODULE — Composants réutilisables (préfixe: .) */
.card { }
.card__title { }
.card__image { }
.btn { }
.btn--primary { }
.nav { }
.nav__item { }

/* 4. STATE — États dynamiques (préfixe: is-) */
.is-active { }
.is-hidden { }
.is-open { }
.is-disabled { }
.is-loading { }

/* 5. THEME — Variations visuelles (préfixe: theme-) */
.theme-dark { }
.theme-light { }
.theme-high-contrast { }
SMACSS — hiérarchie des catégories
═══════════════════════════════════

  BASE (éléments HTML)
    └── styles par défaut, reset
    └── pas de classe, pas de IDs
    └── body, h1, a, img, table...

  LAYOUT (page structure)
    └── préfixe: l-
    └── .l-header, .l-sidebar, .l-content
    └── grid, flexbox, positionnement

  MODULE (composants)
    └── pas de préfixe spécial
    └── .card, .btn, .nav, .form
    └── parties réutilisables

  STATE (états dynamiques)
    └── préfixe: is-
    └── .is-active, .is-hidden
    └── modifié par JS ou media queries

  THEME (variations visuelles)
    └── préfixe: theme-
    └── .theme-dark, .theme-light
    └── couleurs, polices spécifiques

Les 5 catégories SMACSS et leur hiérarchie

2.3 ITCSS — Inverted Triangle CSS

Définition : ITCSS organise le CSS en 7 couches (layers) ordonnées par portée et spécificité croissantes, formant un triangle inversé. Chaque couche a un rôle précis et des règles d'import strictes.
1. Settings — Variables, tokens de design
Variables CSS, couleurs, espacements
2. Tools — Fonctions et mixins (préprocesseur)
@function, @mixin Sass
3. Generic — Reset et normalize
*, box-sizing, margin reset
4. Elements — Styles nus des éléments HTML
body, h1-h6, a, p, ul
5. Objects — Structures non décoratives
.container, .grid, .wrapper
6. Components — Composants UI
.card, .btn, .nav, .modal
7. Utilities — Overrides et helpers
.hidden, .sr-only, .mt-4
/* ============================================
   ITCSS — Imports dans l'ordre
   ============================================ */

/* 1. Settings — Tokens de design */
@import 'settings/variables';
@import 'settings/colors';
@import 'settings/typography';

/* 2. Tools — Fonctions et mixins */
@import 'tools/functions';
@import 'tools/mixins';

/* 3. Generic — Reset global */
@import 'generic/reset';
@import 'generic/normalize';

/* 4. Elements — Styles nus */
@import 'elements/headings';
@import 'elements/links';
@import 'elements/lists';

/* 5. Objects — Layout structures */
@import 'objects/container';
@import 'objects/grid';
@import 'objects/wrapper';

/* 6. Components — Composants UI */
@import 'components/header';
@import 'components/card';
@import 'components/button';
@import 'components/form';
@import 'components/modal';

/* 7. Utilities — Overrides */
@import 'utilities/visibility';
@import 'utilities/spacing';
@import 'utilities/text';

2.4 OOCSS — Object Oriented CSS

Définition : OOCSS (Nicole Sullivan) repose sur 2 principes fondamentaux : la séparation de la structure et de la peau (structure vs. skin), et la séparation des conteneurs et du contenu. Chaque "objet" CSS est réutilisable et combinable.
/* ============================================
   OOCSS — Séparation structure / peau
   ============================================ */

/* STRUCTURE — la forme (objets réutilisables) */
.media {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
.media__body { flex: 1; }

/* PEAU — l'apparence (skins combinables) */
.media--light {
  background: #f8fafc;
  border: 1px solid #e2e8f0;
}
.media--dark {
  background: #1e293b;
  color: white;
}
.media--primary {
  border-left: 4px solid #2563eb;
}

/* UTILISATION — combinaison structure + peau */
/* <div class="media media--light media--primary"> */

/* Autre exemple avec les boutons */
/* Structure */
.btn { display: inline-flex; align-items: center; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; }
.btn--large { padding: 0.75rem 1.5rem; }
.btn--small { padding: 0.25rem 0.5rem; }

/* Peau */
.btn--primary { background: #2563eb; color: white; }
.btn--secondary { background: #64748b; color: white; }
.btn--danger { background: #dc2626; color: white; }

/* Combinaison : btn + btn--large + btn--primary */

2.5 CUBE CSS

Définition : CUBE CSS (Heydon Pickering) est une méthodologie basée sur 4 concepts : Composition (structures de layout), Utility (helpers utilitaires), Block (composants) et Exception (overrules). Elle met l'accent sur la cascade et la "désinvolture" — laisser les styles par défaut faire le travail.
/* ============================================
   CUBE CSS — Les 4 concepts
   ============================================ */

/* COMPOSITION — Layout global, structures de page */
/* Pas de style visuel, juste de la structure */
.composition {
  display: grid;
  gap: var(--gap, 1rem);
  padding: var(--padding, 1rem);
}

/* UTILITY — Helpers utilitaires, overrides */
.u-text-center { text-align: center; }
.u-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
.u-bg-primary { background: #2563eb; }
.u-mt-4 { margin-top: 1rem; }

/* BLOCK — Composants, entités de contenu */
.card {
  border: 1px solid var(--border);
  border-radius: var(--radius, 8px);
  padding: var(--space, 1rem);
}
.card__title { font-size: 1.25rem; font-weight: 700; }
.card__body { color: var(--text-secondary); }

/* EXCEPTION — Overrides contextuels */
.card--featured {
  /* Exception au bloc .card */
  border-color: var(--color-primary);
  box-shadow: var(--shadow-lg);
}

/* Le bloc gère son propre padding, margin, background... */
/* La composition gère le layout */
/* Les utilities sont des raccourcis ponctuels */
/* Les exceptions modifient un bloc dans un contexte spécifique */

2.6 Atomic CSS / Utility-first (Tailwind CSS)

Définition : L'approche Atomic/Utility-first applique une classe par propriété CSS. Chaque classe fait une seule chose. C'est le principe derrière Tailwind CSS. Le HTML devient plus verbeux, mais le CSS est minimal et les conflits impossibles.
<!-- Approche classique (composants) -->
<button class="btn btn-primary">Envoyer</button>

<!-- Approche Atomic / Utility-first (Tailwind) -->
<button class="
  inline-flex items-center justify-center
  px-4 py-2
  bg-blue-600 text-white font-semibold
  rounded-lg
  hover:bg-blue-700
  focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
  transition-colors
  disabled:opacity-50 disabled:cursor-not-allowed
">Envoyer</button>

<!-- Chaque classe = 1 propriété CSS -->
<!-- px-4    → padding-left: 1rem; padding-right: 1rem; -->
<!-- py-2    → padding-top: 0.5rem; padding-bottom: 0.5rem; -->
<!-- bg-blue-600 → background-color: #2563eb; -->
<!-- rounded-lg  → border-radius: 0.5rem; -->
<!-- hover:bg-blue-700 → @media(hover:hover) { &:hover { ... } } -->
Quand utiliser l'approche utility-first ? Idéal pour les prototypages rapides, les projets avec des designs changeants, et les équipes qui veulent des conflits CSS quasi impossibles. Moins idéal pour les très gros projets où la réutilisation de composants est primordiale.

3. Visualisation

3.1 Tableau comparatif des méthodologies

Critère BEM SMACSS ITCSS OOCSS CUBE CSS Atomic
Type Nommage Catégorisation Architecture Principes Cadre Nommage
Complexité ⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐
Spécificité ✓ Contrôlée ✓ Contrôlée ✓ Contrôlée ~ Variable ✓ Contrôlée ✓ Très basse
DRY
Courbe d'apprentissage Facile Moyen Élevée Moyen Moyen Facile
Taille du CSS généré Moyen Moyen Moyen Optimisé Moyen Grand (sans purge)
Popularité ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐
Ideal pour Tout projet Projets moyens Gros projets Design systems Projets modernes Prototypage rapide

3.2 Organisation des fichiers par méthodologie

BEM — Fichiers par composant

css/ components/ card.css /* .card, .card__* */ button.css /* .btn, .btn--* */ nav.css /* .nav, .nav__* */ form.css /* .form, .form__* */ modal.css /* .modal, .modal__* */ layout/ header.css sidebar.css footer.css utilities/ helpers.css main.css /* imports */

ITCSS — Fichiers par couche

css/ 01-settings/ _variables.css _colors.css _typography.css 02-tools/ _mixins.css 03-generic/ _reset.css _normalize.css 04-elements/ _headings.css 05-objects/ _container.css _grid.css 06-components/ _card.css _button.css 07-utilities/ _visibility.css main.css

3.3 Ordre des imports ITCSS — Triangle inversé

╔══════════════════════════════════════════════════════════════════╗
║                    ITCSS — TRIANGLE INVERSÉ                      ║
╠══════════════════════════════════════════════════════════════════╣
║                                                                  ║
║  SPECIFICITÉ     │   COUCHE                                     ║
║  CROISSANTE      │                                               ║
║                  │                                               ║
║  ─────────────── │ ────────────────────────────────────          ║
║  Faible          │  7. Utilities    ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓   ║
║                  │  6. Components   ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓        ║
║                  │  5. Objects      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓             ║
║                  │  4. Elements     ▓▓▓▓▓▓▓▓▓▓▓                ║
║                  │  3. Generic      ▓▓▓▓▓▓▓▓                   ║
║                  │  2. Tools        ▓▓▓▓▓                      ║
║  Forte           │  1. Settings     ▓▓▓                         ║
║                  │                                               ║
║  ════════════════════════════════════════════════════════════   ║
║  Portée          │  Globale ◄────────────► Spécifique            ║
║  Quantité        │  Petite ◄─────────────► Grande                ║
║  Risque conflit  │  Faible ◄────────────► Élevé                  ║
╚══════════════════════════════════════════════════════════════════╝

Le triangle inversé d'ITCSS : les couches les plus spécifiques sont en bas

4. Exemples progressifs

4.1 Projet complet — Architecture BEM avec fichiers modulaires

/* ============================================
   main.css — Point d'entrée unique
   ============================================ */
@import 'settings/variables.css';
@import 'generic/reset.css';
@import 'layout/grid.css';
@import 'components/card.css';
@import 'components/button.css';
@import 'components/nav.css';
@import 'utilities/helpers.css';
/* ============================================
   settings/variables.css — Design tokens
   ============================================ */
:root {
  /* Couleurs */
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-secondary: #7c3aed;
  --color-success: #16a34a;
  --color-warning: #f59e0b;
  --color-error: #dc2626;
  --color-text: #1e293b;
  --color-text-secondary: #64748b;
  --color-bg: #ffffff;
  --color-bg-secondary: #f8fafc;
  --color-border: #e2e8f0;

  /* Espacement */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;

  /* Typographie */
  --font-sans: 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'Cascadia Code', monospace;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;

  /* Ombres */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1);

  /* Bordures */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  /* Transitions */
  --transition-fast: 0.15s ease;
  --transition-base: 0.3s ease;
}
/* ============================================
   generic/reset.css — Reset minimal
   ============================================ */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: 1.6;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { cursor: pointer; font: inherit; }
/* ============================================
   layout/grid.css — Grille responsive
   ============================================ */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--space-4);
}

.grid {
  display: grid;
  gap: var(--space-6);
}

.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 768px) {
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
}
/* ============================================
   components/card.css — Composant carte (BEM)
   ============================================ */
.card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.card:hover {
  box-shadow: var(--shadow-md);
}

.card__image {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
}

.card__content {
  padding: var(--space-6);
}

.card__title {
  font-size: var(--text-xl);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.card__text {
  color: var(--color-text-secondary);
  margin-bottom: var(--space-4);
}

.card--featured {
  border-color: var(--color-primary);
}

.card--dark {
  background: #1e293b;
  border-color: #334155;
  color: #f1f5f9;
}
/* ============================================
   components/button.css — Composant bouton (BEM)
   ============================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border: 2px solid transparent;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: var(--text-base);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.btn--primary {
  background: var(--color-primary);
  color: white;
}

.btn--primary:hover {
  background: var(--color-primary-hover);
}

.btn--outline {
  background: transparent;
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.btn--outline:hover {
  background: var(--color-primary);
  color: white;
}

.btn--ghost {
  background: transparent;
  color: var(--color-text-secondary);
}

.btn--ghost:hover {
  background: var(--color-bg-secondary);
  color: var(--color-text);
}

.btn--small { padding: var(--space-2) var(--space-4); font-size: var(--text-sm); }
.btn--large { padding: var(--space-4) var(--space-8); font-size: var(--text-lg); }
/* ============================================
   utilities/helpers.css — Classes utilitaires
   ============================================ */
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

.u-text-center { text-align: center; }
.u-text-right { text-align: right; }
.u-mt-4 { margin-top: var(--space-4); }
.u-mb-4 { margin-bottom: var(--space-4); }
.u-hidden { display: none; }
.u-flex { display: flex; }
.u-flex-center { display: flex; align-items: center; justify-content: center; }

4.2 SMACSS — Layout de page complet

/* ============================================
   SMACSS — Layout de page type blog
   ============================================ */

/* BASE */
body { font-family: system-ui, sans-serif; color: #1e293b; }
h1 { font-size: 2rem; margin-bottom: 1rem; }
p { margin-bottom: 1rem; line-height: 1.7; }

/* LAYOUT */
.l-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
  background: white;
  border-bottom: 1px solid #e2e8f0;
}

.l-main {
  max-width: 1200px;
  margin: 2rem auto;
  padding: 0 1rem;
}

.l-sidebar {
  padding: 2rem;
  background: #f8fafc;
}

/* MODULE */
.post { margin-bottom: 2rem; padding: 1.5rem; border: 1px solid #e2e8f0; border-radius: 8px; }
.post__title { font-size: 1.5rem; margin-bottom: 0.5rem; }
.post__date { font-size: 0.8rem; color: #94a3b8; }
.post__excerpt { color: #475569; }

.tag { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 4px; font-size: 0.75rem; background: #eff6ff; color: #2563eb; }
.tag--hot { background: #fef2f2; color: #dc2626; }

/* STATE */
.is-featured { border-left: 4px solid #2563eb; }
.is-hidden { display: none; }
.is-loading { opacity: 0.5; pointer-events: none; }

4.3 Utility-first — Layout rapide avec classes utilitaires

<!-- Layout complet sans écrire une ligne de CSS personnalisé -->
<div class="container mx-auto px-4 max-w-6xl">
  <header class="flex items-center justify-between py-4 mb-8">
    <h1 class="text-2xl font-bold text-gray-900">Mon Site</h1>
    <nav class="flex gap-6">
      <a href="#" class="text-gray-600 hover:text-blue-600 transition-colors">Accueil</a>
      <a href="#" class="text-gray-600 hover:text-blue-600 transition-colors">Blog</a>
      <a href="#" class="inline-flex items-center px-4 py-2 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition-colors">Connexion</a>
    </nav>
  </header>

  <main class="grid grid-cols-1 md:grid-cols-3 gap-8">
    <article class="md:col-span-2">
      <div class="bg-white rounded-xl border border-gray-200 overflow-hidden shadow-sm hover:shadow-md transition-shadow">
        <img src="photo.jpg" class="w-full h-48 object-cover" alt="...">
        <div class="p-6">
          <h2 class="text-xl font-bold mb-2">Titre de l'article</h2>
          <p class="text-gray-500 mb-4">Extrait de l'article...</p>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-semibold hover:bg-blue-700">Lire la suite</button>
        </div>
      </div>
    </article>

    <aside class="space-y-6">
      <div class="bg-gray-50 rounded-xl p-6">
        <h3 class="font-bold mb-3">À propos</h3>
        <p class="text-sm text-gray-500">Description du blog...</p>
      </div>
    </aside>
  </main>
</div>

4.4 CUBE CSS — Composant Card avec cascade

/* ============================================
   CUBE CSS — Composant Card
   ============================================ */

/* COMPOSITION — Le conteneur */
.card-composition {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* BLOCK — Le composant */
.cube-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-bg);
}

.cube-card__img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
}

.cube-card__body {
  padding: var(--space-6);
}

.cube-card__title {
  font-size: var(--text-xl);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.cube-card__text {
  color: var(--color-text-secondary);
  line-height: 1.6;
}

/* UTILITY — Overrides ponctuels */
.u-card-highlight { border-color: var(--color-primary); }

/* EXCEPTION — Contexte spécifique */
.sidebar .cube-card {
  flex-direction: row;
}

.sidebar .cube-card__img {
  width: 120px;
  aspect-ratio: 1;
}

5. Erreurs fréquentes

Erreur 1 : Nommer les classes selon leur apparence
/* FAUX — le nom dépend du style visuel */
.red-text { color: red; }
.big-box { font-size: 2rem; }
.rounded { border-radius: 50%; }
.shadow { box-shadow: 0 2px 4px rgba(0,0,0,0.1); }

/* CORRECT — nommer selon la fonction/sémantique */
.error-message { color: var(--color-error); }
.heading-primary { font-size: 2rem; }
.avatar { border-radius: 50%; }
.card { box-shadow: var(--shadow-sm); }
Erreur 2 : Imbriquer trop de sélecteurs (spécificité toxique)
/* FAUX — spécificité excessive, impossible à surcharger */
#main > div > section > article > h2.title { }
.page .content .sidebar .widget .list .item .link { }

/* CORRECT — sélecteurs plats et modulaires (BEM) */
.card__title { }
.sidebar__link { }
Erreur 3 : Utiliser !important comme raccourci
/* FAUX — !important casse la cascade */
.title { font-size: 2rem !important; }
.text { color: blue !important; padding: 1rem !important; }

/* CORRECT — résoudre le problème de spécificité */
.card__title { font-size: 2rem; }
/* Si un !important est vraiment nécessaire, le limiter aux utilities */
.u-text-center { text-align: center !important; }
Erreur 4 : Ne pas suivre la convention choisie
/* INCOHÉRENT — mélange de conventions dans un même projet */
.card { }                    /* BEM */
.card__title { }             /* BEM */
.post-content { }            /* Pas BEM */
.btn-success { }             /* SMACSS ou BEM ? */
.is-active { }               /* SMACSS */
.u-mt-4 { }                  /* Utility */

/* CORRECT — choisir UNE méthodologie et la suivre partout */
.card { }                    /* BEM */
.card__title { }             /* BEM */
.card__text { }              /* BEM */
.card--featured { }          /* BEM */
.btn { }                     /* BEM */
.btn--primary { }            /* BEM */
Erreur 5 : Fichier CSS monolithique
/* FAUX — un seul fichier de 3000 lignes */
/* styles.css : 3000 lignes de CSS non organisé */

/* CORRECT — fichiers modulaires importés via main.css */
/* main.css imports :
   @import 'settings/variables';
   @import 'generic/reset';
   @import 'components/card';
   @import 'components/button';
   @import 'components/nav';
   @import 'utilities/helpers';
*/
Erreur 6 : Confondre BEM avec de l'imbrication HTML
/* FAUX — trop d'imbrication d'éléments BEM */
.card { }
.card__header { }
.card__header__title { }      /* ❌ Imbrication interdite */
.card__header__title__icon { } /* ❌ Trois niveaux max */

/* CORRECT — un seul niveau d'élément */
.card { }
.card__header { }
.card__title { }      /* Titre de la carte, pas du header */
.card__icon { }       /* Icône de la carte */
Erreur 7 : Dupliquer les styles au lieu de créer des composants
/* FAUX — même style copié-collé 5 fois */
.page-header { background: #2563eb; color: white; padding: 2rem; border-radius: 8px; }
.section-header { background: #2563eb; color: white; padding: 2rem; border-radius: 8px; }
.card-header { background: #2563eb; color: white; padding: 2rem; border-radius: 8px; }

/* CORRECT — un composant réutilisable */
.section-header {
  background: var(--color-primary);
  color: white;
  padding: var(--space-8);
  border-radius: var(--radius-md);
}
/* Réutiliser .section-header partout */

6. Bonnes pratiques

Les règles d'or de l'architecture CSS :
  • Choisir UNE méthodologie et la suivre partout — BEM est le meilleur point de départ pour la majorité des projets.
  • Séparer les fichiers par composant — chaque composant CSS dans son propre fichier.
  • Utiliser un fichier d'entrée unique (main.css ou index.css) qui importe tous les autres.
  • Adopter des variables CSS (tokens) pour les couleurs, espacements, ombres, etc.
  • Restreindre la spécificité — jamais plus de 2 niveaux de sélecteurs.
  • Limiter !important aux seules classes utilitaires d'override.
  • Nommer selon la sémantique, pas selon l'apparence visuelle.
  • Documenter les conventions dans un guide de style ou un README dédié.

Quand utiliser quelle méthodologie ?

Contexte Méthodologie recommandée Pourquoi
Petit site vitrine BEM simple Facile à apprendre, suffisant pour la taille
Application web moyenne BEM + fichiers modulaires Organisation claire, maintenable
Gros projet / Design system ITCSS + BEM Séparation des couches, scalabilité
Prototype rapide Utility-first (Tailwind) Vitesse de développement maximale
Design system partagé OOCSS + BEM Séparation structure/peau, réutilisabilité
Projet maintenu par une grande équipe ITCSS + CUBE CSS Règles claires, gestion de la cascade

7. Mini-défi

Défi 1 : Convertir en BEM

Transformez ce CSS non-BEM en architecture BEM propre :

/* AVANT — Non-BEM */
.sidebar .menu .item a.active { color: #2563eb; font-weight: bold; }
.modal .content .close-btn { position: absolute; top: 1rem; right: 1rem; }
.form .field .error-msg { color: #dc2626; font-size: 0.85rem; }

/* APRÈS — BEM */
.nav__link--active { color: #2563eb; font-weight: bold; }
.modal__close { position: absolute; top: 1rem; right: 1rem; }
.form__error { color: #dc2626; font-size: 0.85rem; }

Défi 2 : Créer un design token system

Créez un fichier tokens.css avec au minimum 15 variables couvrant : couleurs, espacement, typographie, ombres et bordures.

/* tokens.css */
:root {
  /* 5 couleurs minimum */
  --color-primary: #2563eb;
  --color-secondary: #7c3aed;
  --color-success: #16a34a;
  --color-warning: #f59e0b;
  --color-error: #dc2626;

  /* 5 espacements minimum */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;

  /* 3 tailles de texte */
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.25rem;

  /* 2 ombres */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.1);

  /* 2 rayons */
  --radius-md: 8px;
  --radius-lg: 12px;
}

Défi 3 : Composant BEM complet

Créez un composant "produit" en BEM avec : image, badge, titre, prix, bouton d'ajout au panier, et un modificateur "épuisé".

<!-- HTML attendu -->
<div class="product product--sold-out">
  <div class="product__image-wrapper">
    <img class="product__image" src="..." alt="...">
    <span class="product__badge product__badge--sale">-30%</span>
  </div>
  <h3 class="product__title">Nom du produit</h3>
  <div class="product__pricing">
    <span class="product__price">29,99 €</span>
    <span class="product__price product__price--old">42,99 €</span>
  </div>
  <button class="product__btn product__btn--add">Ajouter au panier</button>
</div>

Défi 4 : Organiser les fichiers ITCSS

Organisez les fichiers CSS d'un projet de blog en 7 couches ITCSS. Listez chaque fichier et son contenu typique.

/* Structure attendue :
css/
  01-settings/_variables.css       → Couleurs, espacements, tokens
  02-tools/_mixins.css              → @mixin responsive, @function
  03-generic/_reset.css             → *, box-sizing, body
  04-elements/_headings.css         → h1-h6, a, p
  05-objects/_container.css         → .container, .wrapper, .grid
  06-components/_card.css           → .card, .card__*
  06-components/_nav.css            → .nav, .nav__*
  06-components/_post.css           → .post, .post__*
  07-utilities/_helpers.css         → .u-hidden, .u-text-center
  main.css                          → imports dans l'ordre ITCSS
*/

Défi 5 : SMACSS — Layout de dashboard

Créez un layout de dashboard avec les 5 catégories SMACSS : Base (reset), Layout (grid), Module (cartes), State (loading, active), Theme (dark).

/* SMACSS Layout Dashboard */
/* BASE */
body { font-family: system-ui, sans-serif; }

/* LAYOUT */
.l-dashboard { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }
.l-dashboard__sidebar { background: #1e293b; color: white; }
.l-dashboard__main { padding: 2rem; background: #f8fafc; }

/* MODULE */
.stat-card { background: white; border-radius: 12px; padding: 1.5rem; }
.stat-card__label { font-size: 0.85rem; color: #64748b; }
.stat-card__value { font-size: 2rem; font-weight: 700; }

/* STATE */
.is-loading { opacity: 0.5; pointer-events: none; }
.is-active { background: rgba(255,255,255,0.1); }

/* THEME */
.theme-dark .l-dashboard__main { background: #0f172a; }
.theme-dark .stat-card { background: #1e293b; color: white; }

8. Projets pratiques

Projet 1 : Design system BEM complet

Créez un design system avec les composants suivants en BEM :

  • Boutons : primaire, secondaire, outline, ghost + tailles (small, medium, large)
  • Cartes : avec image, titre, texte, bouton + modificateurs (featured, dark)
  • Alertes : success, warning, error, info
  • Formulaires : input, select, textarea avec états (focus, error, disabled)
  • Design tokens (variables) pour tout le système
  • Fichiers organisés par composant

Projet 2 : Blog ITCSS

Créez un blog complet en suivant l'architecture ITCSS :

  • 7 dossiers pour les 7 couches ITCSS
  • Variables dans 01-settings
  • Reset dans 03-generic
  • Layout responsive dans 05-objects
  • Composants (article, sidebar, nav) dans 06-components
  • Utilities dans 07-utilities
  • Fichier main.css avec imports dans l'ordre

Projet 3 : Comparaison de méthodologies

Créez le même composant (une carte produit) avec 4 approches différentes :

  • Avec BEM pur
  • Avec SMACSS (catégorisation)
  • Avec utility-first (comme Tailwind)
  • Avec CUBE CSS
  • Comparez les avantages/inconvénients de chaque approche

9. Révision

Récapitulatif des méthodologies

Méthodologie Concept clé Syntaxe / Structure
BEM Nommage : Bloc__Élément--Modificateur .card__title--large
SMACSS 5 catégories : Base, Layout, Module, State, Theme .l-header, .is-active
ITCSS 7 couches ordonnées par portée Settings → Tools → Generic → Elements → Objects → Components → Utilities
OOCSS Séparation structure / peau .media + .media--dark
CUBE CSS Composition, Utility, Block, Exception Layout → Helpers → Composants → Overrides
Atomic 1 classe = 1 propriété CSS .bg-blue-600 .px-4 .rounded-lg

Quiz rapide

  1. Quels sont les 3 concepts de BEM et comment se nomment-ils ?
  2. Quelles sont les 5 catégories de SMACSS ?
  3. Combien de couches ITCSS et dans quel ordre ?
  4. Quel est le principe fondamental d'OOCSS ?
  5. Quel est l'avantage principal de l'approche utility-first ?
  6. Pourquoi faut-il éviter les sélecteurs à plus de 2 niveaux ?
  7. Comment nommer correctement un état actif en SMACSS ?
  8. Quel est le rôle de la couche "Settings" dans ITCSS ?
  9. BEM recommande-t-il d'imbriquer les éléments (card__header__title) ?
  10. Quelle méthodologie recommandez-vous pour un petit projet vitrine ?
Réponses :
  1. Bloc (composant), Elément (partie du bloc avec __), Modificateur (variante avec --).
  2. Base, Layout, Module, State, Theme.
  3. 7 couches : Settings, Tools, Generic, Elements, Objects, Components, Utilities.
  4. Séparer la structure (forme, layout) de la peau (apparence, couleurs).
  5. Vitesse de développement, pas de conflits CSS, CSS minimal (avec purge).
  6. Éviter les conflits de spécificité et rendre le CSS plus facile à maintenir et à surcharger.
  7. .is-active (préfixe is-).
  8. Contenir les variables CSS et les tokens de design.
  9. Non, BEM recommande max 3 niveaux (bloc__element--modifier).
  10. BEM simple, c'est la méthodologie la plus accessible et suffisante pour les petits projets.

Cheat sheet rapide

/* ============================================
   BEM — Nommage
   ============================================ */
.card { }
.card__header { }
.card__title { }
.card__image { }
.card--featured { }
.card--dark { }
.card__title--large { }

/* ============================================
   SMACSS — Catégories
   ============================================ */
/* Base */    body { }
/* Layout */  .l-header { }
/* Module */  .card { }
/* State */   .is-active { }
/* Theme */   .theme-dark { }

/* ============================================
   ITCSS — Imports (ordre obligatoire)
   ============================================ */
@import '01-settings/variables';
@import '02-tools/mixins';
@import '03-generic/reset';
@import '04-elements/headings';
@import '05-objects/container';
@import '06-components/card';
@import '07-utilities/helpers';

/* ============================================
   OOCSS — Structure + Peau
   ============================================ */
/* Structure */  .media { display: flex; }
/* Peau */       .media--dark { background: #1e293b; }

/* ============================================
   Règles d'or
   ============================================ */
/* 1. Max 2 niveaux de sélecteurs */
/* 2. BEM pour le nommage */
/* 3. Variables CSS pour les tokens */
/* 4. Fichiers par composant */
/* 5. !important = utilities seulement */
/* 6. Nommer selon la sémantique */