Maison > interface Web > tutoriel CSS > le corps du texte

Créez un mode sombre en quelques minutes (cela fonctionne réellement)

Susan Sarandon
Libérer: 2024-11-10 03:01:02
original
365 Les gens l'ont consulté

Build a Dark Mode Toggle in inutes (That Actually Works)

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 :

  • Se souvient réellement des préférences de votre utilisateur
  • Ne fait pas clignoter le mauvais thème au rechargement
  • Joue bien avec les préférences système
  • Prend littéralement 5 minutes à mettre en œuvre

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.

Conditions préalables (les éléments dont vous aurez besoin)

É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 :

  • HTML de base (comme, vous savez ce qu'est un )
  • Quelques connaissances CSS (notamment les variables CSS - mais j'expliquerai au fur et à mesure)
  • JavaScript Vanilla (rien d'extraordinaire, promis)
  • Votre éditeur de code préféré
  • Environ 5 minutes de votre temps (et peut-être un café ☕)

Ce que nous construisons

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 :

  • Navigateurs modernes (oui, même Safari !)
  • Préférences du mode sombre du système
  • Actualisation de la page (plus de flash d'écran blanc)
  • Zéro dépendance externe

Prêt à vous salir les mains ? Commençons par la fondation !

Mise en place de la Fondation

Très bien, mettons la main à la pâte ! Tout d’abord, nous allons mettre en place la structure de base.

Le HTML : restez simple

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;
}
Copier après la connexion
Copier après la connexion

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'
      );
    }
  });
Copier après la connexion
Copier après la connexion

Décomposons ce qui se passe ici car il se passe en fait des choses plutôt sympas :

  1. Quand quelqu'un clique sur la bascule, nous vérifions le thème actuel et passons au thème opposé
  2. Nous enregistrons leur choix dans localStorage (il persiste donc entre les chargements de pages)
  3. Lorsque la page se charge pour la première fois, nous :
    • Vérifiez s'ils ont une préférence enregistrée
    • Sinon, nous vérifions leur thème système
    • Appliquez le thème approprié
  4. En bonus, nous écoutons les changements de thème du système (comme lorsque quelqu'un active le mode sombre sur son système d'exploitation)

Prévenir le flash d'un mauvais thème

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>
Copier après la connexion
Copier après la connexion

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 :

  • Mémorise les préférences de l'utilisateur
  • Respecte les paramètres du système
  • Ne fait pas clignoter le mauvais thème
  • Fonctionne en douceur avec les transitions

Vous voulez le rendre encore meilleur ? Passons à quelques conseils utiles qui vous feront passer de bon à excellent !

Améliorer les choses (parce que les détails comptent !)

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.

1. Accessibilité du clavier

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();
    }
});
Copier après la connexion
Copier après la connexion

2. Désactivation de la transition

Désactivez les transitions lorsque l'utilisateur préfère un mouvement réduit :

@media (prefers-reduced-motion: reduce) {
  body {
    transition: none;
  }
}
Copier après la connexion

3. Gestion des modifications de contenu

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;
    });
}
Copier après la connexion

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)">
Copier après la connexion

4. Prévenir les inadéquations de thèmes

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;
}
Copier après la connexion
Copier après la connexion

5. Astuce d'optimisation des performances

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'
      );
    }
  });
Copier après la connexion
Copier après la connexion

Liste de contrôle des tests rapides

Avant d'expédier, assurez-vous de tester ces scénarios :

  • ✅ L'actualisation de la page maintient le thème correct
  • ✅ Les changements de thème système sont respectés (si pas de préférence manuelle)
  • ✅ Toggle fonctionne à la fois avec la souris et le clavier
  • ✅ Pas de clignotement d'un mauvais thème au chargement
  • ✅ Les transitions se font en douceur
  • ✅ Fonctionne dans tous les principaux navigateurs (oui, même Safari !)
  • ✅ Le contenu spécifique au thème est correctement mis à jour

Problèmes courants à surveiller

  1. Contenu tiers : Certains contenus intégrés peuvent ne pas respecter votre thème. Gérez-le comme ceci :
<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>
Copier après la connexion
Copier après la connexion
  1. Images transparentes : elles peuvent ne pas apparaître correctement sur différents arrière-plans :
// Add this to your existing JavaScript
themeToggle.addEventListener('keydown', (e) => {
    // Toggle on Enter or Space
    if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        toggleTheme();
    }
});
Copier après la connexion
Copier après la connexion

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.

Conclusion

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 :

  • Une bascule qui mémorise réellement les préférences de vos utilisateurs ?
  • Transitions fluides entre les thèmes sans le redoutable flash ⚡
  • Détection des préférences système qui fonctionne ?
  • Accessibilité intégrée dès le départ ♿
  • Optimisations des performances pour que les choses restent vives ?‍♂️

Où aller à partir d’ici ?

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.

Une dernière chose...

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 !


Restons connectés ! ?

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 :

  • Trucs et astuces de développement Web
  • Bonnes pratiques du frontend
  • Informations UI/UX
  • Et oui, plus de posts d'appréciation du mode sombre ?

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!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal