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 ?

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/sombrede 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 écouteprefers-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);