Comment créer un bouton de basculement Dark Mode avec CSS et JavaScript
Le mode sombre est devenu essentiel pour les sites web modernes. Les utilisateurs s’attendent à pouvoir changer de thème en fonction de leur environnement, de l’heure de la journée ou de leurs préférences personnelles. Ce tutoriel vous montre comment créer un bouton de basculement de mode sombre robuste qui respecte les préférences système, mémorise les choix de l’utilisateur et exploite les fonctionnalités CSS modernes pour des performances optimales.
Points clés à retenir
- Créer un bouton de basculement de mode sombre qui respecte les préférences système et conserve les choix de l’utilisateur
- Utiliser les propriétés personnalisées CSS et la propriété color-scheme pour un thème efficace
- Implémenter du JavaScript qui empêche le flash de contenu non stylisé au chargement de la page
- Appliquer les bonnes pratiques d’accessibilité pour la navigation au clavier et les lecteurs d’écran
Mise en place de la structure HTML
Commencez avec du HTML sémantique qui inclut un bouton de basculement et déclare le thème initial :
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>Dark Mode Toggle Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<button type="button" id="theme-toggle" aria-label="Toggle dark mode">
<span class="toggle-text">Dark</span>
</button>
<!-- Your content here -->
</body>
</html>
L’attribut data-theme sur l’élément HTML contrôle notre thème. La balise meta color-scheme indique au navigateur d’adapter les éléments d’interface natifs comme les barres de défilement et les contrôles de formulaire.
Implémentation du CSS avec les fonctionnalités modernes
Utilisation des propriétés personnalisées CSS et de color-scheme
Définissez vos jetons de couleur en utilisant les propriétés personnalisées CSS, puis exploitez la propriété CSS color-scheme pour le thème des éléments natifs :
:root {
color-scheme: light dark;
/* Light theme colors (default) */
--bg-color: #ffffff;
--text-color: #213547;
--accent-color: #0066cc;
}
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--accent-color: #66b3ff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
Respect des préférences système avec prefers-color-scheme
Ajoutez la prise en charge de prefers-color-scheme pour correspondre automatiquement aux paramètres système :
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--accent-color: #66b3ff;
}
}
La fonction moderne light-dark()
Pour les navigateurs prenant en charge la fonction light-dark(), vous pouvez simplifier les définitions de couleurs :
:root {
color-scheme: light dark;
}
body {
background-color: light-dark(#ffffff, #1a1a1a);
color: light-dark(#213547, #e0e0e0);
}
Cette fonction sélectionne automatiquement la couleur appropriée en fonction du schéma de couleurs actif, réduisant ainsi la duplication de code.
Discover how at OpenReplay.com.
JavaScript pour le basculement et la persistance
Prévention du flash de thème au chargement
Placez ce script immédiatement après la balise d’ouverture <body> pour empêcher le flash de contenu non stylisé :
<script>
// Apply saved theme immediately to prevent flash
(function() {
const saved = localStorage.getItem('theme');
if (saved) {
document.documentElement.setAttribute('data-theme', saved);
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-theme', 'dark');
}
})();
</script>
Implémentation complète du mode sombre
Ajoutez ce JavaScript pour la fonctionnalité de basculement :
const toggle = document.getElementById('theme-toggle');
const html = document.documentElement;
// Get current theme
function getTheme() {
return html.getAttribute('data-theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
}
// Set theme and update UI
function setTheme(theme) {
html.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
updateToggleText(theme);
}
// Update button text
function updateToggleText(theme) {
const text = toggle.querySelector('.toggle-text');
text.textContent = theme === 'dark' ? 'Light' : 'Dark';
toggle.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`);
}
// Initialize
updateToggleText(getTheme());
// Handle toggle click
toggle.addEventListener('click', () => {
const current = getTheme();
setTheme(current === 'dark' ? 'light' : 'dark');
});
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light');
}
});
Accessibilité et bonnes pratiques
Fonctionnalités d’accessibilité essentielles
Votre bouton de basculement de mode sombre doit être accessible au clavier et correctement étiqueté :
#theme-toggle:focus-visible {
outline: 2px solid var(--accent-color);
outline-offset: 2px;
}
Assurez un contraste de couleur suffisant dans les deux thèmes. Le mode sombre ne signifie pas un faible contraste — maintenez au moins les normes WCAG AA (4,5:1 pour le texte normal).
Ce qu’il faut éviter
N’utilisez pas filter: invert(1) sur la page entière — cela inverse inutilement les images et les médias. Évitez les arrière-plans noirs purs (#000000) en mode sombre. Utilisez des gris foncés (#1a1a1a) pour une meilleure lisibilité. Ne comptez jamais uniquement sur JavaScript sans solutions de repli CSS.
Test de votre implémentation
Testez votre bouton de basculement de mode sombre dans différents scénarios :
- Effacez localStorage et vérifiez que la détection des préférences système fonctionne
- Basculez le thème et actualisez pour confirmer la persistance
- Modifiez les préférences système pendant que le site est ouvert
- Vérifiez les ratios de contraste à l’aide des DevTools du navigateur
- Testez la navigation au clavier et les annonces du lecteur d’écran
Conclusion
Une solution de mode sombre bien implémentée respecte les préférences de l’utilisateur, conserve les choix et exploite les fonctionnalités CSS modernes. En combinant la propriété color-scheme, les propriétés personnalisées et un JavaScript minimal, vous créez un sélecteur de thème performant, accessible et convivial. La fonction light-dark() simplifie la gestion des couleurs pour les navigateurs modernes tandis que les solutions de repli assurent la compatibilité.
Rappelez-vous : la meilleure implémentation de mode sombre est invisible pour les utilisateurs — elle fonctionne exactement comme ils s’y attendent.
FAQ
Oui, vous pouvez utiliser les media queries CSS avec prefers-color-scheme pour détecter les préférences système. Cependant, JavaScript est nécessaire pour enregistrer les préférences de l'utilisateur et fournir un bouton de basculement manuel qui remplace les paramètres système.
Cela se produit lorsque JavaScript s'exécute après le rendu de la page. Placez un script immédiatement après la balise body qui vérifie localStorage et applique le thème enregistré avant que la page ne s'affiche pour éviter ce flash.
Non, le noir pur peut causer une fatigue oculaire et rendre le texte plus difficile à lire. Utilisez plutôt des gris foncés comme #1a1a1a ou #121212. Ces couleurs réduisent la fatigue tout en maintenant de bons ratios de contraste pour l'accessibilité.
Évitez d'utiliser filter invert sur les images. Fournissez plutôt des versions alternatives en mode sombre des images ou utilisez des PNG transparents avec des couleurs qui fonctionnent sur les deux arrière-plans. Pour les graphiques complexes, envisagez d'utiliser des masques CSS ou des SVG avec currentColor.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..