Un visiteur qui a activé le mode sombre sur son téléphone ou son ordinateur s'attend à ce que les sites qu'il visite en tiennent compte, sans avoir à chercher un bouton caché dans un menu. La media query prefers-color-scheme répond exactement à ce besoin : elle permet à une feuille de style de lire la préférence système de l'utilisateur et d'adapter les couleurs en conséquence, sans une seule ligne de JavaScript.
Cette fonctionnalité fait partie des media queries de niveau 5, un ensemble de requêtes dites d'interaction utilisateur qui donnent au CSS un accès direct aux réglages du système d'exploitation. Elle est aujourd'hui prise en charge par tous les navigateurs modernes et constitue la base de la plupart des implémentations de thème sombre sur le web.
Définition
prefers-color-scheme est une media query CSS qui détecte si l'utilisateur a choisi un thème clair ou un thème sombre au niveau de son système d'exploitation ou de son navigateur. Elle accepte deux valeurs principales : light et dark. Une troisième valeur, no-preference, existe dans la spécification mais n'est presque jamais renvoyée par les navigateurs actuels, qui retombent sur light par défaut lorsque l'utilisateur n'a rien réglé.
Concrètement, cette media query s'utilise à l'intérieur d'un bloc @media, exactement comme on le ferait pour cibler une largeur d'écran avec un Breakpoint. La différence est que le critère testé n'est plus une dimension de la fenêtre, mais un réglage système invisible à l'écran.
@media (prefers-color-scheme: dark) {
body {
background-color: #111111;
color: #f5f5f5;
}
}
@media (prefers-color-scheme: light) {
body {
background-color: #ffffff;
color: #111111;
}
}Pourquoi éviter les couleurs codées en dur partout
Écrire une media query par propriété de couleur devient vite ingérable dès qu'un site compte plusieurs dizaines de composants. La pratique recommandée consiste à ne définir la media query qu'une seule fois, au niveau de la racine du document, et à y redéfinir des Variable CSS plutôt que des propriétés directement. Chaque composant consomme ensuite ces variables sans jamais savoir dans quel thème il se trouve.
:root {
--bg-primary: #ffffff;
--text-primary: #111111;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #111111;
--text-primary: #f5f5f5;
}
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}Cette organisation a un avantage supplémentaire : elle prépare naturellement l'ajout d'un interrupteur manuel piloté par JavaScript, en surchargeant les mêmes variables via un attribut ou une classe sur la balise html, sans toucher au reste du code.
Ajouter un interrupteur manuel par-dessus la préférence système
La plupart des sites qui prennent le thème sombre au sérieux ne se contentent pas de suivre le système : ils proposent aussi un bouton pour forcer un thème, que l'utilisateur soit d'accord avec son système ou non. Ce comportement se construit en donnant la priorité à un attribut explicite sur celle de la media query, grâce à l'ordre des règles dans la Cascade.
:root {
--bg-primary: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #111111;
}
}
/* L'attribut choisi manuellement l'emporte sur la préférence système */
:root[data-theme="light"] {
--bg-primary: #ffffff;
}
:root[data-theme="dark"] {
--bg-primary: #111111;
}Un script minimal se charge alors de poser l'attribut data-theme sur html lorsque l'utilisateur clique sur le bouton, et de mémoriser son choix. Tant qu'aucun choix n'a été fait, la media query continue de piloter le rendu.
Un déclencheur du navigateur, pas une intention de design
prefers-color-scheme: dark signifie que l'utilisateur préfère forcément un site tout noir avec des couleurs vives saturées. En réalité, cette media query indique seulement un réglage d'affichage. Un thème sombre bien conçu garde les mêmes règles de lisibilité, de contraste et de hiérarchie visuelle qu'un thème clair : il ne s'agit pas d'inverser mécaniquement les couleurs avec un filtre, mais de redessiner une palette cohérente et testée pour le fond sombre.Interactions avec les images et les médias
Le thème sombre ne concerne pas que les couleurs de fond et de texte. Une image avec un fond blanc peut devenir agressive sur un fond sombre, tout comme un graphique avec des courbes fines et claires peut disparaître sur un fond clair. La media query peut aussi cibler l'attribut src d'une image dans une feuille de style, ou être combinée avec la balise picture pour choisir entre deux versions d'un logo selon le thème actif.
| Valeur | Signification | Cas d'usage typique |
|---|---|---|
light | L'utilisateur préfère un thème clair, ou n'a rien réglé | Palette claire par défaut |
dark | L'utilisateur a activé le mode sombre du système | Palette sombre, images adaptées |
| Absence de correspondance | Navigateur ne prenant pas en charge la media query | Le thème clair s'applique par défaut |
Bonnes pratiques de mise en œuvre
Pour un résultat propre, il est conseillé de tester le rendu dans les deux thèmes dès la conception d'un composant, plutôt que d'ajouter le mode sombre en dernière minute. Les contrastes doivent être vérifiés séparément pour chaque thème, car un rapport de contraste correct en clair ne garantit rien en sombre. Il est également utile de prévoir un délai de transition court sur les propriétés de couleur, pour éviter un changement de thème trop brutal lorsque l'utilisateur bascule son système en cours de navigation.
Foire aux questions
Ce n'est pas obligatoire, mais c'est fortement recommandé dès que l'audience est large. De nombreux utilisateurs activent le mode sombre par confort visuel ou pour économiser la batterie sur un écran OLED, et un site qui reste blanc et éblouissant dans ce contexte peut donner une impression de négligence, même si le contenu est excellent.
Oui, prefers-color-scheme est prise en charge par toutes les versions actuelles de Chrome, Firefox, Safari et Edge, sur ordinateur comme sur mobile. Sur les navigateurs plus anciens qui ne la reconnaissent pas, la règle est simplement ignorée et le thème clair par défaut s'applique, ce qui rend son usage totalement sûr.
Oui, via window.matchMedia('(prefers-color-scheme: dark)'), qui renvoie un objet dont la propriété matches indique le réglage actuel et qui peut aussi écouter les changements en temps réel. Cela reste utile pour synchroniser un composant JavaScript, comme un graphique Canvas, avec le thème choisi par la feuille de style CSS.