← All posts

Avoir le choix d'un thème sombre sur son site (SCSS et JavaScript)

Billet d'archive (2020), rédigé à l'époque du site sous Hugo. Le principe reste valable ; le site actuel (Nuxt) utilise la même mécanique de variables CSS et de préférence système.

Étonnamment, je préfère les thèmes sombres, sûrement une dérive des journées passées sur une flotte de terminaux (et des soirées ?). Du coup, mon site web était aussi en sombre. Mais tout le monde n'est pas fan, et le noir peut être mal perçu. Alors, pourquoi ne pas donner le choix au visiteur ?

Le site avec un thème sombre ou clair

Sur cette piste, il existe plusieurs voies. J'ai choisi de combiner le SCSS déjà inclus dans le thème Hugo, des variables CSS et des attributs de page pour une mise à jour instantanée, du JavaScript et la requête de média CSS prefers-color-scheme. On obtient une solution dont le thème :

  • est adapté aux préférences générales clair/sombre de l'utilisateur, si c'est supporté par le navigateur ;
  • est modifiable localement par l'utilisateur avec un bouton ;
  • dont le choix est stocké pour les visites suivantes.

Concrètement

En gardant la structure de mon site en Hugo, cela donnait :

  • dans /assets/scss/_predefined.scss, on définit les couleurs :
$text: #000000;
$background: #ffffff;
$darkmode-text: #ffffff;
$darkmode-background: #000000;
  • dans /assets/scss/style.scss, on définit les variables CSS et on les applique là où il faut :
[data-theme="light"] {
  --background: #{$background};
  --text: #{$text};
}

[data-theme="dark"] {
  --background: #{$darkmode-background};
  --text: #{$darkmode-text};
}

body {
  color: var(--text);
  background: var(--background);
}
  • la checkbox à insérer où l'on veut :
<div class="theme-switch-wrapper">
  <label class="theme-switch" for="checkbox">
    <input type="checkbox" id="checkbox" />
    <div class="slider round"></div>
  </label>
</div>
  • côté JavaScript, on change le curseur et l'attribut de page data-theme, et on écoute prefers-color-scheme :
const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
const currentTheme = localStorage.getItem('theme');

if (currentTheme) {
  document.documentElement.setAttribute('data-theme', currentTheme);
  toggleSwitch.checked = currentTheme === 'dark';
}

function switchTheme(e) {
  const theme = e.target.checked ? 'dark' : 'light';
  document.documentElement.setAttribute('data-theme', theme);
  localStorage.setItem('theme', theme);
}

toggleSwitch.addEventListener('change', switchTheme, false);

Références