1. Livres & vidéos
  2. Next.js pour les développeurs React
  3. Approches de stylisation CSS
Extrait - Next.js pour les développeurs React Le guide complet pour des applications web professionnelles
Extraits du livre
Next.js pour les développeurs React Le guide complet pour des applications web professionnelles Revenir à la page d'achat du livre

Approches de stylisation CSS

Pourquoi le choix de la méthode de stylisation est-il stratégique ?

Le choix de la méthode de stylisation dans une application Next.js ne relève pas du simple goût esthétique ou du confort de développement : il constitue une décision architecturale.

La manière dont les styles sont écrits, appliqués et maintenus influence profondément la structure du code, la cohérence de l’interface, la performance perçue et la productivité des équipes. En somme, le style n’est pas seulement un aspect visuel : c’est un pilier technique du projet.

Dans une application React classique, la stylisation peut être traitée comme une couche séparée. Mais dans un environnement comme Next.js, où le rendu est hybride (statique, serveur, client), chaque approche de stylisation - qu’elle soit globale, scopée ou dynamique - entraîne des conséquences sur :

  • le temps de chargement initial (bundle CSS global vs CSS scindé par composant) ;

  • la taille des fichiers et donc la bande passante ;

  • la cohérence du design system ;

  • la simplicité de maintenance à long terme ;

  • la courbe d’apprentissage pour les nouveaux développeurs.

Next.js offre une flexibilité rare : il prend en charge nativement CSS Modules, accepte les solutions CSS-in-JS comme...

CSS Modules (natif, sans dépendance)

1. Principe et fonctionnement

Les CSS Modules constituent la solution de stylisation native à Next.js. Ils permettent d’écrire du CSS classique tout en garantissant l’encapsulation locale des styles. Chaque fichier .module.css exporte des classes uniques, automatiquement renommées à la compilation, ce qui élimine tout risque de collision entre composants.

L’intégration est transparente :

import styles from './Button.module.css' 
 
export function Button() { 
  return <button className={styles.primary}>Envoyer</button> 
} 

Ici, styles.primary est converti en une classe unique (Button_primary__a1b2c3), isolée du reste du code. Cette approche procure la simplicité du CSS traditionnel tout en offrant la sécurité du scoping local.

2. Avantages et limites

Les CSS Modules sont parfaits pour les projets de petite à moyenne envergure, où la priorité est la clarté du code et la rapidité de mise en place. Leur principal atout est leur simplicité : pas de configuration Babel, pas de surcharge JavaScript, pas de dépendances externes.

Cette simplicité implique toutefois certaines limites :

  • Les CSS Modules ne proposent pas de mécanisme intégré pour gérer...

Styled Components (CSS-in-JS)

1. Le paradigme CSS-in-JS

Styled Components repose sur le concept du CSS-in-JS : les styles sont écrits directement dans les fichiers JavaScript ou TypeScript, et liés au cycle de vie des composants React.

Chaque composant stylisé encapsule son propre comportement et son propre style :

import styled from 'styled-components' 
 
const Button = styled.button' 
  background: ${(props) => (props.primary ? '#0070f3' : '#eaeaea')}; 
  color: ${(props) => (props.primary ? 'white' : '#111')}; 
' 

Cette approche unifie logique et apparence : les styles deviennent contextuels, capables de réagir à des props, des thèmes, ou à l’état global de l’application. Dans un design system avancé, cette intégration est précieuse.

2. Avantages et compromis

Les avantages majeurs de Styled Components sont :

  • La dynamique des styles : tout peut dépendre d’une prop ou d’un thème.

  • L’intégration fluide avec TypeScript, garantissant l’autocomplétion et la cohérence des types.

  • Le theming global via ThemeProvider, pratique pour gérer le mode clair/sombre ou des variantes...

Tailwind CSS (utilitaires atomiques)

1. Une approche pragmatique du design

Tailwind CSS repose sur une idée simple : construire les interfaces directement depuis le JSX en combinant des classes utilitaires préconfigurées. Plutôt que d’écrire des fichiers CSS, on compose des éléments avec des classes comme bg-blue-600 text-white rounded-lg p-4, qui décrivent précisément le rendu visuel.

Cette approche « atomique » élimine la redondance : chaque style est réutilisable à l’infini.

Le moteur JIT (Just-In-Time) compile uniquement les classes réellement utilisées, ce qui produit un fichier CSS minimal.

Exemple

<button className="bg-blue-600 hover:bg-blue-700 text-white 
font-medium py-2 px-4 rounded"> 
  Envoyer 
</button> 

Le résultat est à la fois concis, performant et homogène.

2. Avantages et apprentissage

Les points forts de Tailwind CSS sont nombreux :

  • Rapidité de prototypage : il permet de construire une UI fonctionnelle en quelques minutes.

  • Design system intégré : palette de couleurs, typographies, espacements et breakpoints cohérents.

  • Performance exceptionnelle : grâce à la purge JIT, le CSS final ne contient que ce qui est utilisé.

  • Écosystème riche : thèmes...

Comparaison rapide des trois méthodes

CSS Modules, Styled Components et Tailwind CSS offrent chacun des avantages distincts. CSS Modules et Styled Components assurent un scope local des styles, évitant les collisions grâce à la génération de classes uniques ou à l’encapsulation au niveau du composant. Tailwind CSS adopte une approche différente : il repose sur des classes utilisateurs globales, appliquées directement dans le markup. Bien que ces classes soient globales, leur nature atomique et standardisée réduit fortement les risques de conflit. En matière de dynamisme, Styled Components permet une adaptation directe des styles via les props et le thème. Tailwind, quant à lui, propose une logique conditionnelle basée sur la composition des classes, mais ne génère pas de styles dynamiques au runtime, au sens du « CSS-in-JS ».

Côté configuration, CSS Modules et Tailwind fonctionnent quasiment sans configuration supplémentaire, tandis que Styled Components nécessite une configuration Babel pour être pleinement compatible avec le rendu côté serveur de Next.js.

Sur le plan des performances, Tailwind CSS est le plus efficace grâce à son système de purge et de compilation à la volée. À l’inverse, les deux autres approches peuvent alourdir...

Quelle solution choisir ?

Le choix dépend avant tout du contexte et des objectifs du projet. Pour un projet simple, rapide ou éducatif, CSS Modules constitue une solution fiable et suffisante. En revanche, si l’on vise un design system structuré ou une interface très personnalisée, Styled Components combiné à un ThemeProvider est recommandé.

Pour un SaaS moderne ou toute interface riche et cohérente à grande échelle, Tailwind CSS est souvent la meilleure option grâce à sa rapidité, sa cohérence visuelle et ses performances. Enfin, une approche hybride peut être pertinente : utiliser Tailwind pour la structure et CSS Modules pour des styles plus ciblés ou des besoins spécifiques.

Ce choix stratégique doit être aligné avec les besoins techniques, la culture de l’équipe et les contraintes de long terme (maintenabilité, onboarding, évolutivité).

Exemples de combinaison possible

Il est tout à fait possible de combiner plusieurs approches de stylisation dans un même projet Next.js. Une pratique courante consiste à utiliser Tailwind CSS pour la structure générale de l’interface (typographie, espacements, couleurs) et à réserver les CSS Modules pour des composants spécifiques nécessitant des styles isolés ou plus expressifs.

Par exemple, une section de page peut utiliser Tailwind pour son apparence globale, tandis qu’un composant enfant applique une classe CSS issue d’un fichier .module.css pour un effet particulier ou un surlignage précis.

De même, Tailwind CSS peut être utilisé avec Styled Components dans le cas de composants conditionnels ou fortement dynamiques, où les props contrôlent le style en fonction de la logique métier.

En résumé

Le choix de la méthode de stylisation dans Next.js dépasse la simple préférence technique : c’est un choix stratégique qui conditionne la maintenabilité, la performance et la cohérence du produit final.

  • Tailwind CSS se distingue par sa modernité, sa rapidité et sa compatibilité naturelle avec la philosophie « server-first » de Next.js.

  • Styled Components demeure la solution privilégiée pour les projets où la logique métier et les styles sont étroitement liés.

  • CSS Modules restent une base saine pour les projets modestes, les prototypes et les environnements d’apprentissage.

Quel que soit le choix, l’essentiel est de standardiser les pratiques au sein de l’équipe et de maintenir un design system clair et documenté. C’est cette cohérence, plus que l’outil lui-même, qui garantit une interface durable, performante et agréable à faire évoluer.

Pourquoi thématiser son application ?

La mise en place d’un système de thème dans une application web répond à plusieurs objectifs fonctionnels et ergonomiques.

D’abord, elle améliore l’expérience utilisateur, en permettant d’adapter l’interface aux préférences visuelles de chacun. Le mode sombre, par exemple, offre un meilleur confort visuel dans des environnements peu éclairés, tout en réduisant la fatigue oculaire. Du point de vue de l’accessibilité, cette adaptabilité permet également de prendre en compte certaines situations de handicap visuel ou de sensibilité à la lumière.

Ensuite, la thématisation garantit une cohérence visuelle dans l’ensemble de l’application. Chaque composant, chaque écran, chaque section repose sur une palette et des règles communes. Cette homogénéité visuelle renforce la lisibilité, la hiérarchisation de l’information, et la perception globale de la qualité du produit.

Sur le plan technique, la gestion des thèmes permet de supporter le mode sombre, qu’il soit activé automatiquement (selon les préférences système de l’utilisateur) ou manuellement via une action explicite. Cela devient une exigence courante dans les applications modernes...

Approche recommandée : Tailwind CSS, classes conditionnelles et variables CSS

Next.js ne propose pas de système de thème intégré. Cependant, en combinant Tailwind CSS, l’utilisation de classes conditionnelles, et un ensemble de variables CSS personnalisées, il est possible de mettre en place un système de thème à la fois puissant, simple à maintenir et performant.

Tailwind CSS, en tant que framework utilitaire, offre une grande flexibilité dans la composition visuelle. Il permet d’associer dynamiquement des classes selon le thème actif, notamment via la classe dark ou via l’ajout de classes spécifiques à un thème.

L’approche par variables CSS (définies au niveau du root ou d’une classe thématique comme .dark.theme-a, .theme-b) permet quant à elle de conserver une grande lisibilité dans la configuration des couleurs, des espacements, ou des polices. Ce mécanisme est particulièrement efficace lorsqu’il est couplé à Tailwind via la fonction theme() ou en utilisant des notations telles que bg-[var(--color-bg)].

Cette combinaison (Tailwind + class conditionnelle + variables CSS) constitue une solution moderne, responsive-first, agnostique du framework de thème, et parfaitement compatible avec les Server Components ou les applications hybrides....

Activer le mode sombre dans Tailwind

La première étape pour intégrer un thème clair/sombre dans une application Next.js avec Tailwind CSS consiste à activer le mode sombre dans la configuration Tailwind.

Dans le fichier tailwind.config.js, la propriété darkMode doit être définie à ’class’. Cela indique que l’activation du mode sombre dépendra de la présence explicite d’une classe dark sur l’élément racine (généralement <html> ou <body>), plutôt que des préférences système de l’utilisateur.

Exemple de configuration :

// tailwind.config.js 
module.exports = { 
  darkMode: 'class', // ou 'media' si l'on souhaite détecter 
automatiquement les préférences de l'utilisateur 
  theme: { 
    extend: { 
      colors: { 
        primary: 'var(--color-primary)', 
        background: 'var(--color-bg)', 
        text: 'var(--color-text)', 
      }, 
    }, 
  }, ...

Définir les variables CSS pour chaque thème

Une fois les variables référencées dans Tailwind, il est nécessaire de les définir dans le CSS global, généralement dans un fichier comme globals.css.

Les valeurs par défaut sont définies dans le sélecteur :root, ce qui correspond au thème clair. Le thème sombre, quant à lui, repose sur une classe dark appliquée à l’élément <html> ou <body>. Lorsque cette classe est présente, elle surcharge les variables du thème clair.

/* globals.css */ 
:root { 
  --color-primary: #0d47a1; 
  --color-bg: #ffffff; 
  --color-text: #111111; 
} 
 
.dark { 
  --color-primary: #90caf9; 
  --color-bg: #121212; 
  --color-text: #f5f5f5; 
} 

Ce système présente plusieurs avantages :

  • Il centralise les couleurs et autres tokens design, facilitant leur mise à jour.

  • Il permet une bascule instantanée entre les thèmes, sans rechargement de la page.

  • Il est compatible avec toutes les couches de l’application, y compris les Server Components et les librairies tierces qui n’utilisent pas Tailwind.

Grâce à l’utilisation des variables CSS...

Créer un ThemeProvider dans l’application

Afin de rendre le système de thème pleinement fonctionnel côté client, il est recommandé de créer un composant ThemeProvider personnalisé (ici appelé MyThemeProvider). Celui-ci s’appuie sur la librairie next-themes, qui permet de gérer dynamiquement les thèmes et d’appliquer automatiquement la classe dark à l’élément racine de l’application.

L’objectif du ThemeProvider est double :

  • hydrater le thème au moment du rendu côté client ;

  • éviter tout flash de thème par défaut au chargement (appelé Flash Of Incorrect Theme - FOIT).

Voici un exemple de composant :

'use client'; 
 
import { useEffect, useState } from 'react'; 
import { useTheme } from 'next-themes'; 
 
export function MyThemeProvider({ children }: 
{ children: React.ReactNode }) { 
  const [mounted, setMounted] = useState(false); 
  const { theme, setTheme } = useTheme(); 
 
  useEffect(() => { 
    setMounted(true); 
  }, []); 
 
  // Évite les incohérences entre le rendu SSR et le thème côté client ...

Utiliser next-themes pour gérer la classe dark

La librairie next-themes fournit un mécanisme simple et efficace pour gérer dynamiquement les thèmes dans une application Next.js. Elle applique automatiquement la classe dark sur l’élément HTML, et expose un contexte React permettant de lire ou de modifier le thème actif.

1. Installation

L’installation se fait via npm, yarn, ou pnpm.

npm install next-themes 

2. Intégration dans le layout

L’intégration de next-themes doit se faire au plus haut niveau possible de l’application, généralement dans le fichier layout.tsx situé à la racine du dossier app/.

// app/layout.tsx 
import { ThemeProvider } from 'next-themes'; 
 
export default function RootLayout({ children }: { children: React.ReactNode }) { 
  return ( 
    <html lang="fr" suppressHydrationWarning> 
      <body> 
        <ThemeProvider attribute="class"> 
          {children} 
        </ThemeProvider> 
      </body> 
    </html> ...

Ajouter un bouton de bascule clair/sombre

Pour permettre à l’utilisateur de changer manuellement de thème (clair ou sombre), il suffit d’utiliser le hook useTheme fourni par next-themes. Ce hook expose l’état actuel du thème (theme) ainsi qu’une fonction setTheme pour le modifier dynamiquement.

Le bouton suivant permet de basculer entre les deux modes :

'use client'; 
 
import { useTheme } from 'next-themes'; 
 
export default function ThemeToggle() { 
  const { theme, setTheme } = useTheme(); 
 
  return ( 
    <button 
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} 
      className="px-4 py-2 bg-primary text-white" 
    > 
      {theme === 'dark' ? 'Clair' : 'Sombre'} 
    </button> 
  );
} 

Points importants

  • Le composant est marqué comme ’use client’, car les thèmes ne peuvent être modifiés que côté client.

  • La logique conditionnelle permet d’alterner entre les valeurs ’light’ et ’dark’.

  • Le rendu...

Cas d’usage avancés

1. Thème par défaut basé sur les préférences système

next-themes prend en charge les préférences de thème déclarées au niveau du système d’exploitation. Pour cela, il suffit d’activer cette fonctionnalité lors de l’intégration du ThemeProvider.

<ThemeProvider attribute="class" defaultTheme="system" enableSystem /> 
  • defaultTheme="system" : le thème initial sera déterminé automatiquement selon le réglage clair/sombre du système.

  • enableSystem : active la détection des préférences système (optionnelle mais recommandée).

Cela permet à l’utilisateur de bénéficier immédiatement de son thème préféré, sans configuration manuelle.

2. Forcer un thème sur un layout ou une route

Dans certains cas, il peut être utile d’imposer un thème spécifique pour certaines pages (ex. une interface d’administration toujours en sombre). Il est alors possible de modifier le thème activement en fonction de la route.

Exemple dans un composant client :

'use client'; 
 
import { useEffect } from 'react'; 
import { useTheme } from 'next-themes'; 
import...

Bonnes pratiques

La mise en place d’un système de thème dans une application Next.js repose autant sur les outils que sur la rigueur de leur intégration. Voici quelques bonnes pratiques à respecter pour garantir un fonctionnement fluide, maintenable et cohérent à long terme :

Bonne pratique

Pourquoi

Utiliser des variables CSS

Permet de surcharger les couleurs sans recompilation de Tailwind ou rebuild complet.

Gérer la classe dark sur <html>

Garantit une cascade CSS propre et prévisible avec les sélecteurs Tailwind.

Hydrater proprement le thème

Évite les erreurs d’hydratation grâce à suppressHydrationWarning dans <html>.

Prévoir des tokens design neutres

Standardise la conception (ex. --color-bg, --color-text, --color-primary).

En suivant ces principes, on obtient un thème plus modulaire, évolutif et compatible avec la montée en complexité du projet.

Résumé

Pour mettre en œuvre un système de thème robuste dans une application Next.js avec Tailwind CSS, les éléments suivants constituent la combinaison recommandée :

Élément

Outil/Approche

Mode sombre

next-themes + class="dark" sur l’élément <html>

Variables CSS

Définies globalement via :root et surchargées via .dark

Application des styles

Utilisation de bg-[var(--color-bg)] dans les classes Tailwind

Comportement par défaut

defaultTheme: ’system’ pour respecter les préférences OS

Bascule manuelle

useTheme() + setTheme() dans un composant client

Hydratation fiable

suppressHydrationWarning pour prévenir les incohérences SSR/CSR

En combinant intelligemment next-themes, Tailwind CSS et les variables CSS, on obtient un système de gestion de thème à la fois fluide, performant et maintenable. Cette approche garantit une excellente expérience utilisateur tout en facilitant l’intégration de futurs besoins (multimarques, accessibilité, personnalisation).