Avez-vous déjà passé des heures à mettre en œuvre un mode sombre pour ensuite le faire clignoter d'un blanc aveuglant lors de l'actualisation de la page ? Ou pire, ignore-t-il complètement les préférences système de votre utilisateur ? Ouais, moi aussi. ?
Voici le problème : le mode sombre n'est plus seulement une fonctionnalité à la mode. Avec de plus en plus de personnes codant la nuit (coupables comme accusés) et l'accessibilité devenant de plus en plus importante, un mode sombre bien implémenté est pratiquement indispensable pour les sites Web ou les applications Web modernes. Mais bien faire les choses peut être étonnamment délicat.
La bonne nouvelle ? Après avoir fouillé diverses implémentations et combattu avec localStorage, j'ai finalement déchiffré le code d'un mode sombre qui :
Dans cet article, je vais vous expliquer comment créer un bouton de mode sombre que vous souhaiterez réellement utiliser. Pas de solutions trop compliquées, pas de dépendances inutiles - juste un code propre et fonctionnel que vous pouvez implémenter immédiatement.
Éliminons d'abord la partie ennuyeuse - mais je promets d'être bref !
Vous avez probablement déjà tout ce dont vous avez besoin, mais juste pour vous assurer que nous sommes sur la même longueur d'onde :
Avant de nous lancer, voici un bref aperçu de ce que nous allons obtenir. Pas de bibliothèques d'interface utilisateur sophistiquées ni de configurations compliquées - juste une bascule simple et fluide qui ressemble à ceci :
Ne vous inquiétez pas de le faire ressembler exactement à ceci - l'important est que cela fonctionnera parfaitement. Nous nous concentrerons d'abord sur la fonction, puis vous pourrez le styliser comme vous le souhaitez.
La meilleure partie ? Tout ce que nous sommes sur le point de construire fonctionne avec :
Prêt à vous salir les mains ? Commençons par la fondation !
Très bien, mettons la main à la pâte ! Tout d’abord, nous allons mettre en place la structure de base.
Nous allons commencer avec du HTML très simple. Pas besoin de trop réfléchir à cette partie :
<button> <h3> The CSS </h3> <p>Here's where things get interesting. We'll use CSS variables (aka custom properties) to handle our color scheme. Drop this in your CSS file:<br> </p> <pre class="brush:php;toolbar:false">:root { --background: #ffffff; --text-primary: #222222; --toggle-bg: #e4e4e7; --toggle-hover: #d4d4d8; } [data-theme="dark"] { --background: #121212; --text-primary: #ffffff; --toggle-bg: #3f3f46; --toggle-hover: #52525b; } body { background-color: var(--background); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; height: 100vh; display: flex; align-items: center; justify-content: center; } .theme-toggle { border: none; padding: 0.5rem; border-radius: 9999px; background-color: var(--toggle-bg); cursor: pointer; transition: background-color 0.2s ease; align-self: flex-start; position: absolute; right: 20px; } .theme-toggle:hover { background-color: var(--toggle-hover); } .theme-toggle svg { transform-origin: center; transition: transform 0.3s ease; } .theme-toggle:active svg { transform: rotate(30deg); } h1 { display: flex; } .sun-icon { display: none; width: 24px; height: 24px; } .moon-icon { width: 24px; height: 24px; } [data-theme="dark"] .sun-icon { display: block; } [data-theme="dark"] .moon-icon { display: none; }
Conseil de pro : Remarquez comment nous utilisons le thème de données au lieu des classes ? Cela indique très clairement à quoi sert l'attribut et évite tout conflit de nom de classe potentiel.
Pour les icônes, vous pouvez utiliser vos propres SVG ou en récupérer dans votre bibliothèque d'icônes préférée. J'aime en utiliser des simples, alors j'ai dit à Chatgpt de proposer ceci :
<!-- Replace the empty SVGs with these --> <svg> <p>At this point, your toggle should look pretty decent, but it won't actually do anything yet. Don't worry though - in the next section, we'll add the JavaScript that makes it all work!</p> <p><strong>A quick heads-up:</strong> I've kept the styling minimal on purpose. Feel free to spice it up with your own creative touches. Want a sliding animation? Go for it! Prefer a different icon style? Make it yours!</p> <p>Ready to make this thing actually work? Let's move on to the JavaScript implementation!</p> <h2> The JavaScript Implementation (Where It All Comes Together!) </h2> <p>Alright, this is where we make our toggle actually, you know... toggle. But don't worry - we're keeping it clean and simple.<br> </p> <pre class="brush:php;toolbar:false">const themeToggle = document.querySelector('.theme-toggle'); function toggleTheme() { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', newTheme); localStorage.setItem('theme', newTheme); } // Listen for clicks on our toggle themeToggle.addEventListener('click', toggleTheme); function initializeTheme() { const savedTheme = localStorage.getItem('theme'); if (savedTheme) { document.documentElement.setAttribute('data-theme', savedTheme); } else { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; document.documentElement.setAttribute( 'data-theme', prefersDark ? 'dark' : 'light' ); localStorage.setItem('theme', prefersDark ? 'dark' : 'light'); } } // Run on page load initializeTheme(); // Listen for system theme change window.matchMedia('(prefers-color-scheme: dark)') .addEventListener('change', (e) => { // Only update if user hasn't manually set a preference if (!localStorage.getItem('theme')) { document.documentElement.setAttribute( 'data-theme', e.matches ? 'dark' : 'light' ); } });
Décomposons ce qui se passe ici car il se passe en fait des choses plutôt sympas :
Voici un problème courant : les utilisateurs voient parfois un flash du mauvais thème lors du chargement de la page. Super ennuyeux, non ? Corrigeons cela en ajoutant ce script dans le fichier
de votre HTML :<script> // Add this to your <head> before any style sheets (function() { const savedTheme = localStorage.getItem('theme'); if (savedTheme) { document.documentElement.setAttribute('data-theme', savedTheme); } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) { document.documentElement.setAttribute('data-theme', 'dark'); } })(); </script>
Cela s'exécute immédiatement avant que quoi que ce soit d'autre ne se charge, évitant ainsi ce flash ennuyeux.
Et... c'est tout ! Vous disposez d'un mode sombre fonctionnel qui :
Vous voulez le rendre encore meilleur ? Passons à quelques conseils utiles qui vous feront passer de bon à excellent !
Passons de « ça marche » à « ça marche à merveille » avec quelques améliorations importantes mais souvent négligées. C'est le genre de détails qui séparent une mise en œuvre professionnelle d'un hack rapide.
Tout d'abord, assurons-nous que tout le monde peut utiliser notre bascule, quelle que soit la manière dont il interagit avec son appareil :
// Add this to your existing JavaScript themeToggle.addEventListener('keydown', (e) => { // Toggle on Enter or Space if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleTheme(); } });
Désactivez les transitions lorsque l'utilisateur préfère un mouvement réduit :
@media (prefers-reduced-motion: reduce) { body { transition: none; } }
Voici quelque chose qui échappe à de nombreux développeurs : certains contenus devront peut-être changer en fonction du thème. Pensez aux images avec différentes versions pour les modes clair/sombre :
// Add this to your toggleTheme function function updateThemeSpecificContent(theme) { // Find all theme-aware images const themeImages = document.querySelectorAll('[data-theme-image]'); themeImages.forEach(img => { const lightSrc = img.getAttribute('data-light-src'); const darkSrc = img.getAttribute('data-dark-src'); img.src = theme === 'dark' ? darkSrc : lightSrc; }); }
Utilisez-le dans votre HTML comme ceci :
<img data-theme-image data-light-src="/path/to/light-logo.png" data-dark-src="/path/to/dark-logo.png" alt="Créez un mode sombre en quelques minutes (cela fonctionne réellement)">
Parfois, le thème enregistré peut être désynchronisé avec ce qui est réellement affiché. Ajoutons un contrôle de sécurité :
<button> <h3> The CSS </h3> <p>Here's where things get interesting. We'll use CSS variables (aka custom properties) to handle our color scheme. Drop this in your CSS file:<br> </p> <pre class="brush:php;toolbar:false">:root { --background: #ffffff; --text-primary: #222222; --toggle-bg: #e4e4e7; --toggle-hover: #d4d4d8; } [data-theme="dark"] { --background: #121212; --text-primary: #ffffff; --toggle-bg: #3f3f46; --toggle-hover: #52525b; } body { background-color: var(--background); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; height: 100vh; display: flex; align-items: center; justify-content: center; } .theme-toggle { border: none; padding: 0.5rem; border-radius: 9999px; background-color: var(--toggle-bg); cursor: pointer; transition: background-color 0.2s ease; align-self: flex-start; position: absolute; right: 20px; } .theme-toggle:hover { background-color: var(--toggle-hover); } .theme-toggle svg { transform-origin: center; transition: transform 0.3s ease; } .theme-toggle:active svg { transform: rotate(30deg); } h1 { display: flex; } .sun-icon { display: none; width: 24px; height: 24px; } .moon-icon { width: 24px; height: 24px; } [data-theme="dark"] .sun-icon { display: block; } [data-theme="dark"] .moon-icon { display: none; }
Voici une astuce intéressante pour éviter les changements de disposition lors du chargement de polices personnalisées dans différents thèmes :
<!-- Replace the empty SVGs with these --> <svg> <p>At this point, your toggle should look pretty decent, but it won't actually do anything yet. Don't worry though - in the next section, we'll add the JavaScript that makes it all work!</p> <p><strong>A quick heads-up:</strong> I've kept the styling minimal on purpose. Feel free to spice it up with your own creative touches. Want a sliding animation? Go for it! Prefer a different icon style? Make it yours!</p> <p>Ready to make this thing actually work? Let's move on to the JavaScript implementation!</p> <h2> The JavaScript Implementation (Where It All Comes Together!) </h2> <p>Alright, this is where we make our toggle actually, you know... toggle. But don't worry - we're keeping it clean and simple.<br> </p> <pre class="brush:php;toolbar:false">const themeToggle = document.querySelector('.theme-toggle'); function toggleTheme() { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', newTheme); localStorage.setItem('theme', newTheme); } // Listen for clicks on our toggle themeToggle.addEventListener('click', toggleTheme); function initializeTheme() { const savedTheme = localStorage.getItem('theme'); if (savedTheme) { document.documentElement.setAttribute('data-theme', savedTheme); } else { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; document.documentElement.setAttribute( 'data-theme', prefersDark ? 'dark' : 'light' ); localStorage.setItem('theme', prefersDark ? 'dark' : 'light'); } } // Run on page load initializeTheme(); // Listen for system theme change window.matchMedia('(prefers-color-scheme: dark)') .addEventListener('change', (e) => { // Only update if user hasn't manually set a preference if (!localStorage.getItem('theme')) { document.documentElement.setAttribute( 'data-theme', e.matches ? 'dark' : 'light' ); } });
Avant d'expédier, assurez-vous de tester ces scénarios :
<script> // Add this to your <head> before any style sheets (function() { const savedTheme = localStorage.getItem('theme'); if (savedTheme) { document.documentElement.setAttribute('data-theme', savedTheme); } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) { document.documentElement.setAttribute('data-theme', 'dark'); } })(); </script>
// Add this to your existing JavaScript themeToggle.addEventListener('keydown', (e) => { // Toggle on Enter or Space if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleTheme(); } });
C'est ça ! Vous disposez désormais d'une implémentation de mode sombre robuste, accessible et conviviale qui gère différents scénarios comme un champion.
Eh bien, voilà ! Nous avons créé une bascule en mode sombre qui non seulement fonctionne, mais qui fonctionne très bien.
Récapitulons rapidement ce que nous avons accompli :
N'hésitez pas à prendre ce code et à vous l'approprier. Ajoutez peut-être des animations sophistiquées, essayez différentes combinaisons de couleurs ou intégrez-les à votre conception existante. La base que nous avons construite est suffisamment solide pour gérer toutes les idées créatives que vous lui proposez.
Le mode sombre peut sembler un petit détail, mais ce sont ces petites touches qui montrent que vous vous souciez de l'expérience de vos utilisateurs. En plus, c'est juste cool. Qui n’aime pas un bon mode sombre ?
Si vous avez trouvé cela utile, n'hésitez pas à le partager avec d'autres développeurs. Et si vous proposez des améliorations intéressantes, j'aimerais en entendre parler !
Si vous avez apprécié ce guide et que vous voulez plus de conseils de développement Web, d'astuces et de blagues occasionnelles de papa sur la programmation, venez passer du temps avec moi sur X ! Je partage des conseils rapides, des informations sur le codage et des solutions concrètes issues de mon parcours de développeur.
? Suivez-moi @Peboydcoder
Je publie régulièrement sur :
Passez nous dire bonjour ! Toujours ravi de communiquer avec d'autres développeurs soucieux de créer de meilleures expériences Web.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!