Cours JavaScript et React · Module 14: Styles avancés

CSS Modules - Panneaux de contrôle isolés

4 min de lecture
Dans cette leçon8

Les CSS Modules sont l'une des manières les plus populaires de styliser dans React. Ils fonctionnent comme un système de panneaux de contrôle isolés sur un vaisseau spatial -- chaque module a ses propres commandes qui n'interfèrent pas avec les autres.

Que sont les CSS Modules ?

Les CSS Modules sont des fichiers CSS ordinaires avec l'extension .module.css. La différence, c'est que tous les noms de classes sont automatiquement uniques -- React génère des identifiants uniques, de sorte que les styles d'un composant ne remplacent jamais les styles d'un autre.

1/* SpacePanel.module.css */
2.panel {
3  background: #0d1137;
4  border: 2px solid #3949ab;
5  border-radius: 12px;
6  padding: 20px;
7}
8
9.title {
10  color: #7c4dff;
11  font-size: 24px;
12  margin-bottom: 16px;
13}
14
15.statusActive {
16  color: #00e676;
17  font-weight: bold;
18}

Importer et utiliser

On importe un CSS Module comme un objet et on référence les classes comme des propriétés d'objet :

1import styles from './SpacePanel.module.css';
2
3function SpacePanel({ title, status }) {
4  return (
5    <div className={styles.panel}>
6      <h2 className={styles.title}>{title}</h2>
7      <span className={styles.statusActive}>
8        Status: {status}
9      </span>
10    </div>
11  );
12}

Dans le HTML généré, la classe panel devient quelque chose comme SpacePanel_panel_x7k2f -- complètement unique !

Combiner des classes

On a souvent besoin de combiner plusieurs classes CSS. Avec les CSS Modules, on peut le faire de plusieurs façons :

1// Template literal
2<div className={`${styles.panel} ${styles.dark}`}>
3
4// Avec condition
5<div className={`${styles.panel} ${isActive ? styles.active : ''}`}>
6
7// Tableau avec join
8<div className={[styles.panel, styles.dark].join(' ')}>

Compose -- héritage de styles

Les CSS Modules offrent une directive spéciale composes qui permet d'hériter des styles d'autres classes :

1/* base.module.css */
2.baseButton {
3  padding: 10px 20px;
4  border: none;
5  border-radius: 6px;
6  cursor: pointer;
7  font-size: 14px;
8  transition: all 0.3s ease;
9}
10
11/* SpaceButton.module.css */
12.primaryButton {
13  composes: baseButton from './base.module.css';
14  background: #7c4dff;
15  color: white;
16}
17
18.dangerButton {
19  composes: baseButton from './base.module.css';
20  background: #f44336;
21  color: white;
22}

Grâce à composes, on évite de dupliquer les styles tout en conservant l'isolation.

Styles globaux dans les CSS Modules

Si tu as besoin d'une classe globale (par exemple pour des bibliothèques externes), utilise :global :

1/* Layout.module.css */
2:global(.container) {
3  max-width: 1200px;
4  margin: 0 auto;
5}
6
7.localClass {
8  /* Celle-ci est locale */
9  color: #64b5f6;
10}

Classes dynamiques avec les CSS Modules

On a souvent besoin de changer les styles en fonction des props ou de l'état. Voici quelques patterns :

1import styles from './Alert.module.css';
2
3function Alert({ type = 'info', message }) {
4  // Sélection dynamique d'une classe en fonction du prop
5  const alertClass = styles[type]; // styles.info, styles.warning, styles.error
6
7  return (
8    <div className={`${styles.alert} ${alertClass}`}>
9      <p className={styles.message}>{message}</p>
10    </div>
11  );
12}
1/* Alert.module.css */
2.alert {
3  padding: 16px;
4  border-radius: 8px;
5  border-left: 4px solid;
6}
7
8.info {
9  background: #1a237e;
10  border-color: #64b5f6;
11  color: #90caf9;
12}
13
14.warning {
15  background: #4a3800;
16  border-color: #ffa726;
17  color: #ffcc80;
18}
19
20.error {
21  background: #4a0000;
22  border-color: #f44336;
23  color: #ef9a9a;
24}

Remarque que styles[type] te permet de sélectionner dynamiquement une classe en fonction d'une variable -- c'est comme changer de mode sur un panneau de contrôle.

La bibliothèque classnames / clsx

Pour des combinaisons de classes plus complexes, il vaut la peine d'utiliser la bibliothèque clsx ou classnames :

1import clsx from 'clsx';
2import styles from './Button.module.css';
3
4function SpaceButton({ variant, size, disabled }) {
5  return (
6    <button className={clsx(
7      styles.button,
8      styles[variant],     // styles.primary ou styles.secondary
9      styles[size],         // styles.small ou styles.large
10      { [styles.disabled]: disabled }  // conditionnellement
11    )}>
12      Engage!
13    </button>
14  );
15}

Avantages des CSS Modules

  • Isolation des styles -- pas de conflits de noms de classes, chaque composant a sa propre « capsule »
  • CSS pur -- pas besoin d'apprendre une nouvelle syntaxe, tu utilises le même CSS que d'habitude
  • Support natif dans Create React App et Next.js -- zéro configuration
  • Léger -- aucune bibliothèque supplémentaire dans le bundle, zéro JS à l'exécution
  • Migration facile depuis du CSS existant -- il suffit de changer l'extension du fichier et l'import
  • Typage -- tu peux générer des types TypeScript pour les classes CSS (par exemple via typed-css-modules)

Les CSS Modules sont un choix solide et éprouvé pour styliser les composants React. Ils sont comme des panneaux de contrôle fiables sur un vaisseau spatial -- simples, prévisibles et sans conflits.

Code de cette leçon : App.jsx
1import React from 'react';
2import styles from './SpacePanel.module.css';
3
4function StatusIndicator({ label, status }) {
5  const statusClass = status === 'active'
6    ? styles.statusActive
7    : status === 'warning'
8    ? styles.statusWarning
9    : styles.statusCritical;
10
11  return (
12    <div className={styles.statusRow}>
13      <span className={styles.label}>{label}</span>
14      <span className={statusClass}>{status.toUpperCase()}</span>
15    </div>
16  );
17}
18
19function SpacePanel({ title, children }) {
20  return (
21    <div className={styles.panel}>
22      <h2 className={styles.title}>{title}</h2>
23      {children}
24    </div>
25  );
26}
27
28export default function App() {
29  return (
30    <div className={styles.app}>
31      <h1 className={styles.heading}>CSS Modules dans React</h1>
32      <p className={styles.subtitle}>Styles isolés -- chaque composant a ses propres classes uniques</p>
33
34      <SpacePanel title="Système de navigation">
35        <StatusIndicator label="Moteur principal" status="active" />
36        <StatusIndicator label="Bouclier thermique" status="warning" />
37        <StatusIndicator label="Carburant de réserve" status="critical" />
38      </SpacePanel>
39
40      <SpacePanel title="Communication">
41        <StatusIndicator label="Liaison radio" status="active" />
42        <StatusIndicator label="Antenne de secours" status="active" />
43        <StatusIndicator label="Signal SOS" status="active" />
44      </SpacePanel>
45    </div>
46  );
47}

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Quelle est la syntaxe correcte pour référencer une variable CSS dans une feuille de style ?

  2. 2. Quel est le principal avantage des CSS Modules par rapport aux fichiers CSS classiques ?

Tâches pratiques dans le jeu

  • Éditeur de code

    Implémente un composant AlertBox avec les CSS Modules

  • Clique dans l'ordre

    Ordonne la syntaxe d'import d'un CSS Module dans React :

  • Éditeur de code

    Implémente un composant d'onglets avec les CSS Modules et useState

Articles utiles