Polar Code 🎭

Command Palette

Search for a command to run...

11
Pièce N°11

Module 11 — L'urbanismedu css, éviter le bidonville de sélecteurs

Archives CSS — Quand le code devient une ville

Date de consignation : Nuit du 21 mars — Ordonnancement méthodique

Le projet avait grandi. Ce qui commençait comme une page simple avec 200 lignes de CSS était devenu un monstre. 5000 lignes. Des sélecteurs qui se mariaient, divorçaient, s'entretuaient. Des !important partout comme des graffitis. Des propriétés redondantes, contradictoires, oubliées.

On ne pouvait plus toucher à une classe sans en casser trois autres. Le CSS était devenu une maison de fous. Un asile où chaque règle criait plus fort que la précédente.

C'est là que l'architecture est entrée. Pas comme une révolution, mais comme un plan d'urbanisme. Une méthodologie. Une discipline.


11.1 — BEM : LE SYSTÈME DE COORDONNÉES

Nommer pour ne pas se perdre

BEM n'est pas une syntaxe. C'est une philosophie. Une manière de penser les interfaces comme des assemblages de blocs, pas comme des pages.

/* AVANT : Le chaos */
.header nav ul li a.active {
  color: red;
}

.card .image .caption .title {
  font-size: 1.2em;
}

/* APRÈS BEM : La clarté */
.menu__link--active {
  color: var(--color-primary);
}

.card__title {
  font-size: 1.2em;
}

📐 Les trois piliers de BEM

/* BLOCK : L'entité indépendante */
.card { 
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 1rem;
}

/* ELEMENT : Une partie du bloc */
.card__image {
  width: 100%;
  height: auto;
  border-radius: 4px 4px 0 0;
}

.card__title {
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
}

.card__body {
  color: #666;
  line-height: 1.5;
}

/* MODIFIER : Une variation */
.card--featured {
  border-color: var(--color-primary);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.card__button--disabled {
  opacity: 0.5;
  pointer-events: none;
}

🧩 HTML correspondant

<article class="card card--featured">
  <img class="card__image" src="photo.jpg" alt="">
  <div class="card__content">
    <h3 class="card__title">Titre de la carte</h3>
    <p class="card__body">Description...</p>
    <button class="card__button card__button--disabled">
      Non disponible
    </button>
  </div>
</article>

⚠️ Les règles non-dites de BEM

  1. Pas de nesting dans les sélecteurs : .card .card__title est un crime.
  2. Pas de styles globaux dans les éléments : .card__title ne doit pas affecter d'autres .title.
  3. Pas de modifications par contexte : Pas de .sidebar .card. Utilisez un modificateur : .card--sidebar.
  4. Un élément appartient à un seul bloc : Si un élément est réutilisé, c'est peut-être un nouveau bloc.

Le bénéfice : Vous pouvez donner ce CSS à un nouveau développeur, et il comprendra la structure de l'interface sans voir le HTML.


11.2 — ITCSS & OOCSS : LES PLANS D'URBANISME

Du général au spécifique, du structurel au cosmétique

🏛️ ITCSS : La pyramide inversée

Une architecture en 7 couches, de la plus large à la plus spécifique.

📁 styles/
├── 📄 1-settings/          # Variables, configurations globales
│   ├── _colors.scss
│   ├── _typography.scss
│   └── _breakpoints.scss
├── 📄 2-tools/             # Mixins, fonctions
│   ├── _mixins.scss
│   └── _functions.scss
├── 📄 3-generic/           # Reset, Normalize
│   └── _reset.scss
├── 📄 4-elements/          # Styles de base des balises HTML
│   ├── _headings.scss
│   └── _links.scss
├── 📄 5-objects/           # Patterns structurels réutilisables
│   ├── _container.scss
│   └── _grid.scss
├── 📄 6-components/        # Composants UI (BEM)
│   ├── _buttons.scss
│   ├── _cards.scss
│   └── _forms.scss
└── 📄 7-utilities/         # Helpers, trumps, !important autorisé
    ├── _spacing.scss
    └── _visibility.scss

Exemple concret :

// 1-settings/_colors.scss
:root {
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --color-text: #333;
}

// 4-elements/_headings.scss
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  line-height: 1.2;
  margin-bottom: 1rem;
}

// 6-components/_buttons.scss
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

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

.button--primary:hover {
  background-color: darken(var(--color-primary), 10%);
}

// 7-utilities/_spacing.scss
.mt-1 { margin-top: 0.5rem !important; }
.mt-2 { margin-top: 1rem !important; }
.mt-3 { margin-top: 2rem !important; }

🎭 OOCSS : Séparer la peau du squelette

Deux principes simples mais puissants :

  1. Séparer la structure du skin
/* STRUCTURE (le squelette) */
.media {
  display: flex;
  align-items: flex-start;
  margin-bottom: 1rem;
}

.media__image {
  margin-right: 1rem;
  flex-shrink: 0;
}

.media__body {
  flex: 1;
}

/* SKIN (l'apparence) */
.media--bordered {
  border: 1px solid #ddd;
  padding: 1rem;
  border-radius: 4px;
}

.media--reversed .media__image {
  order: 2;
  margin-right: 0;
  margin-left: 1rem;
}
  1. Séparer le conteneur du contenu
/* MAUVAIS : Lié à un contexte spécifique */
.sidebar .widget {
  background: #f5f5f5;
  padding: 1rem;
}

/* BON : Indépendant du contexte */
.widget {
  background: #f5f5f5;
  padding: 1rem;
}

/* Le conteneur ne fait que positionner */
.sidebar {
  /* Styles de layout seulement */
}

11.3 — FICHIERS MODULAIRES : LE DÉCOUPAGE INTELLIGENT

Un fichier, une responsabilité

📦 Avec Sass/SCSS (recommandé)

// main.scss - Le point d'entrée
@import 'abstracts/variables';
@import 'abstracts/mixins';

@import 'base/reset';
@import 'base/typography';

@import 'layout/grid';
@import 'layout/header';
@import 'layout/footer';

@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';

@import 'pages/home';
@import 'pages/contact';

@import 'themes/dark';
@import 'themes/admin';

@import 'utilities/spacing';
@import 'utilities/visibility';

🎯 Structure de dossiers évolutive

src/styles/
├── abstracts/          # Pas de CSS généré
│   ├── _variables.scss
│   ├── _functions.scss
│   └── _mixins.scss
├── base/               # Styles de base
│   ├── _reset.scss
│   ├── _typography.scss
│   └── _base.scss
├── layout/             # Layout majeur
│   ├── _grid.scss
│   ├── _header.scss
│   ├── _sidebar.scss
│   └── _footer.scss
├── components/         # Composants réutilisables
│   ├── _buttons.scss
│   ├── _cards.scss
│   ├── _forms.scss
│   └── _navigation.scss
├── pages/              # Styles spécifiques aux pages
│   ├── _home.scss
│   └── _contact.scss
├── themes/             # Thèmes, variantes
│   ├── _dark.scss
│   └── _admin.scss
└── utilities/          # Helpers, overrides
    ├── _spacing.scss
    ├── _text.scss
    └── _display.scss

Avec CSS natif (import moderne)

/* style.css */
@import './abstracts/variables.css';
@import './base/reset.css' layer(base);
@import './components/buttons.css' layer(components);
@import './utilities/spacing.css' layer(utilities);

/* Les CSS Layers permettent de contrôler la cascade */
@layer base, components, utilities;

11.4 — RESET VS NORMALIZE : LE TERRAIN À BÂTIR

Égaliser le terrain avant de construire

💣 CSS Reset : La table rase

/* Meyer Reset (simplifié) */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  line-height: 1.15;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

⚖️ Normalize.css : L'harmonisation

/* Extrait de Normalize.css */
html {
  line-height: 1.15;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
}

main {
  display: block;
}

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

hr {
  box-sizing: content-box;
  height: 0;
  overflow: visible;
}

/* Normalize préserve les styles utiles tout en corrigeant les bugs */

🎯 Modern CSS Reset (recommandé)

/* 1. Utiliser une meilleure box model */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* 2. Supprimer les marges par défaut */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

/* 3. Set core body defaults */
body {
  min-height: 100vh;
  text-rendering: optimizeSpeed;
  line-height: 1.5;
}

/* 4. Images plus faciles à travailler */
img,
picture {
  max-width: 100%;
  display: block;
}

/* 5. Héritage des polices pour les éléments de formulaire */
input,
button,
textarea,
select {
  font: inherit;
}

/* 6. Éviter les débordements de texte */
p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

/* 7. Réduire les animations si l'utilisateur le préfère */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Choix :

  • Reset si vous voulez tout contrôler depuis zéro
  • Normalize si vous voulez une base cohérente entre navigateurs
  • Modern Reset le meilleur des deux mondes

11.5 — CONVENTIONS DE NOMMAGE : LE LANGAGE COMMUN

Parler la même langue

🔤 Les différentes conventions

/* kebab-case (standard CSS, recommandé) */
.main-navigation {
  /* Lisible, compatible avec tout */
}

/* camelCase (populaire en JS) */
.mainNavigation {
  /* Pratique pour JSX/React */
}

/* PascalCase (composants React) */
.MainNavigation {
  /* Pour différencier des éléments HTML */
}

/* BEM (structuré) */
.main-navigation__item--active {
  /* Explicite mais verbeux */
}

/* Préfixes (organisation sémantique) */
.c-card           /* Composant */
.l-grid           /* Layout */
.t-dark-theme     /* Thème */
.u-mt-2           /* Utilitaire */
.js-modal-trigger /* Hook JavaScript */
.is-active        /* État */
.has-error        /* État */

🏷️ Système de préfixes recommandé

/* o- : Objects (OOCSS) */
.o-media {}
.o-container {}

/* c- : Components */
.c-button {}
.c-card {}

/* l- : Layout */
.l-header {}
.l-grid {}

/* u- : Utilities */
.u-mt-2 {}
.u-text-center {}

/* js- : JavaScript hooks */
.js-modal-trigger {}
.js-accordion {}

/* is-, has- : États */
.is-active {}
.has-error {}

/* t- : Themes */
.t-dark {}
.t-admin {}

/* s- : Scopes */
.s-checkout-page {}

📝 Règles de nommage

  1. Descriptif mais concis : .user-avatar pas .round-image-with-border-inside-profile
  2. Sémantique, pas visuel : .primary-button pas .big-blue-button
  3. Consistent dans tout le projet : Choisissez une convention et tenez-vous y
  4. Évitez les noms génériques : .header est risqué, .main-header est mieux
  5. Pensez à la maintenance : Le nom doit encore avoir du sens dans 6 mois

🎨 Exemple complet d'organisation

<header class="l-header">
  <div class="o-container">
    <nav class="c-main-nav" role="navigation">
      <a href="/" class="c-logo">
        <img src="logo.svg" alt="Acme Corp" class="c-logo__image">
      </a>
      
      <ul class="c-main-nav__list">
        <li class="c-main-nav__item">
          <a href="/products" 
             class="c-main-nav__link js-nav-link"
             data-page="products">
            Products
          </a>
        </li>
        <li class="c-main-nav__item">
          <a href="/about" 
             class="c-main-nav__link c-main-nav__link--active js-nav-link is-active"
             data-page="about">
            About
          </a>
        </li>
      </ul>
      
      <button class="c-button c-button--primary u-ml-auto js-theme-toggle">
        Switch theme
      </button>
    </nav>
  </div>
</header>

11.6 — OUTILS MODERNES : LE FUTUR DE L'ORGANISATION

🎭 CSS Layers (@layer)

@layer base, components, utilities;

@layer base {
  h1 {
    font-size: 2rem;
  }
}

@layer components {
  .card {
    padding: 1rem;
  }
}

@layer utilities {
  .mt-4 {
    margin-top: 2rem !important;
  }
}

/* Les utilitaires gagnent toujours sur les composants,
   peu importe l'ordre dans le CSS */

🎨 CSS Custom Properties (Variables)

/* Fichier : _variables.css */
:root {
  /* Couleurs */
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --color-text: #333;
  
  /* Typographie */
  --font-base: 'Inter', sans-serif;
  --font-heading: 'Playfair Display', serif;
  
  /* Espacements */
  --space-unit: 1rem;
  --space-xs: calc(0.25 * var(--space-unit));
  --space-sm: calc(0.5 * var(--space-unit));
  --space-md: calc(1 * var(--space-unit));
  --space-lg: calc(2 * var(--space-unit));
  
  /* Breakpoints */
  --breakpoint-mobile: 320px;
  --breakpoint-tablet: 768px;
  --breakpoint-desktop: 1024px;
}

/* Utilisation cohérente */
.card {
  padding: var(--space-md);
  margin-bottom: var(--space-lg);
  color: var(--color-text);
  font-family: var(--font-base);
}

🔧 Methodologies modernes

  • CUBE CSS : Composition Utility Block Exception
  • ACSS : Atomic CSS (Tailwind, Tachyons)
  • SMACSS : Scalable Modular Architecture CSS

11.7 — NOTES DE FIN D'ENQUÊTE

  • Commencez simple : Pas besoin de BEM sur un site de 3 pages.
  • Documentez vos conventions : Un fichier CODING_STANDARDS.md sauve des heures.
  • Automatisez : Utilisez des linters (stylelint), des formatters (Prettier).
  • Pensez performance : Trop de spécificité = CSS plus lent.
  • Revisez régulièrement : Une architecture qui ne s'adapte pas est une mauvaise architecture.
  • L'équipe d'abord : Choisissez des conventions que toute l'équipe comprend.

La vérité : La meilleure architecture CSS est celle que vous maintiendrez. Celle qui vous fait gagner du temps, pas en perdre. Celle qui rend le code prévisible, pas magique.


Dernière lumière sur l'écran : 05:42.
Les fichiers sont organisés. Les noms, cohérents. Les sélecteurs, disciplinés.
Le CSS n'est plus une jungle. C'est une ville planifiée. Avec ses quartiers, ses règles, sa logique.
On peut maintenant ajouter des fonctionnalités sans peur. Modifier des styles sans tout casser.
Demain, un nouveau développeur rejoindra l'équipe. Il trouvera le code lisible. Compréhensible.
L'architecture a fait son travail. Elle a transformé le chaos en ordre.
Le projet peut grandir. Sans s'effondrer sous son propre poids.

Fin du dossier Architecture & Organisation — Classé et archivé.