Comment créer un dark mode (mode sombre) en CSS et JavaScript ?
Le “mode sombre”, ou plus communément appelé “dark mode”, est devenu une fonctionnalité courante dans l’univers des sites web. Il consiste à faire passer l’apparence de votre site d’un fond clair à un fond sombre. Les services de Google intègrent cette option (Gmail, Instagram, YouTube…), tout comme Facebook et, bien entendu, vos appareils mobiles. Il est donc légitime que cette fonctionnalité soit également proposée sur un site internet.
Il existe des plugins WordPress qui permettent de mettre en place cet effet. Cependant, nous allons voir aujourd’hui une solution simple pour ajouter une option de dark mode à l’aide de quelques lignes de code HTML, CSS et JavaScript.
Pourquoi ajouter un dark mode à votre site web ?
Plusieurs études, dont une diffusée en 2019, ont montré que le mode sombre est meilleur pour les yeux dans un environnement peu éclairé. Qui ne s’est jamais fait agresser les yeux au réveil en ouvrant un SMS sur une application avec fond blanc ?! Selon cette étude, utiliser un fond noir permet une meilleure lisibilité et une diminution significative de la fatigue oculaire.
Utiliser le mode sombre agit également sur la lumière bleue, responsable de la qualité du sommeil (elle empêche la production de mélatonine). Bien entendu, ce n’est pas une solution miracle ; néanmoins, la lumière plus douce, elle contient moins de lumière bleue.
D’un point de vue environnemental, le dark mode permet d’augmenter l’autonomie de la batterie. Grâce à la technologie OLED, certains pixels peuvent être totalement éteints, ce qui réduit la consommation d’énergie. Pour les sites web, c’est la même chose : un site internet avec un fond blanc sera, par définition, plus énergivore qu’un site avec un fond noir. C’est d’ailleurs un des critères de création de sites internet éco-responsables ; réduire l’empreinte carbone à travers la réduction de la consommation d’énergie.
En revanche, vous devrez faire attention : dans les faits, le dark mode doit être pensé dans sa globalité. Si vous utilisez une police (typographie) trop petite, un contraste insuffisant ou un interlignage trop serré, alors l’utilisateur devra forcer sur ses yeux pour lire votre page. Vous perdrez ainsi tous les bénéfices de ce mode. Comme nous l’avons mentionné, le dark mode est parfait pour les environnements sombres. En revanche, dans un environnement très éclairé, il sera plus facile de lire un texte noir sur fond blanc.
Certaines études montrent également que les personnes myopes rencontrent plus de difficultés à lire sur un écran à fond sombre.
C’est pourquoi grace à option sur votre site internet permettant d’activer ou de désactiver le mode sombre, vous offrez à l’utilisateur la liberté de choisir ce qui lui convient le mieux.
Comment créer un dark mode de base
Passons à présent au tutoriel, dans cette partie, nous allons simplement créer une option qui passera les fonds en noir et tous les textes en blanc (si vous avez des titres en couleurs, on ne les différenciera plus).
Étape 1 : Créer le bouton switch dark mode
Dans un premier temps, nous allons créer une checkbox avec l’apparence d’un bouton switch. Vous pourrez utiliser cette technique aussi bien sur un site WordPress que sur un site from scratch. Je vais donc reprendre des classes souvent utilisées par WordPress (pensez à adapter au besoin).
- 1.On crée le menu html dans une balise “nav” et on y met notre menu principal ainsi que la checkbox :
<nav id="menu-principal">
<ul class="menu">
<li class="menu-item"><a href="#accueil">Accueil</a></li>
<li class="menu-item"><a href="#services">Services</a></li>
<li class="menu-item"><a href="#a-propos">À propos</a></li>
<li class="menu-item"><a href="#contact">Contact</a></li>
</ul>
<label for="darkmode" class="switch">
<input id="darkmode" type="checkbox"><span class="slider"></span>
</label>
</nav>HTML- 2.On stylise notre menu principal.
Ici j’utilise du CSS imbriqué, c’est une norme qui commence a être acceptée par les navigateurs web et qui évite d’utiliser du SASS. Pour une utilisation plus classique, n’oubliez pas d’adapter votre CSS comme vous en avez l’habitude en utilisant la bonne structure.
/* Navigation */
nav {
background: linear-gradient(to bottom, #ffffff, #f5f5f5);
padding: 0.5rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 2rem;
ul {
list-style: none;
display: flex;
justify-content: center;
margin: 0;
padding: 0;
li {
margin: 0 1rem;
a {
color: #2e05b4;
font-weight: bold;
font-size: 1rem;
text-decoration: none;
text-transform: uppercase;
transition: color 0.3s ease;
}
}
}
}style.css- 3.Je complète ensuite avec l’apparence de mon switch.
/* Navigation */
nav {
background: linear-gradient(to bottom, #ffffff, #f5f5f5);
padding: 0.5rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 2rem;
ul {
list-style: none;
display: flex;
justify-content: center;
margin: 0;
padding: 0;
li {
margin: 0 1rem;
a {
color: #2e05b4;
font-weight: bold;
font-size: 1rem;
text-decoration: none;
text-transform: uppercase;
transition: color 0.3s ease;
}
}
}
/* Switch */
.switch {
position: relative;
display: inline-block;
width: 120px;
height: 40px;
input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
background-color: #eeeded;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: background-color 0.4s ease;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
font-family: Arial, sans-serif;
font-size: 0.9rem;
color: #333;
&::before {
content: "";
position: absolute;
height: 1.5rem;
width: 1.5rem;
left: 0.3rem;
bottom: 0.5rem;
background: url('day-icon.svg');
background-size: cover;
border-radius: 50%;
z-index: 1;
transition: left 0.4s ease, right 0.4s ease, background-color 0.4s ease;
}
.label-text {
width: 100%;
text-align: right;
z-index: 2;
padding-left: 0.1rem;
padding-right: 0;
transition: all 0.4s ease;
&::before {
content: "Light mode";
font-size: 0.9rem;
transition: content 0.4s ease;
}
}
}
input:checked + .slider {
background-color: #121212;
flex-direction: row-reverse;
&::before {
left: auto;
right: 0.3rem;
background: url(night_icon.svg);
background-size: cover;
}
.label-text {
text-align: left;
&::before {
content: "Dark mode";
color: white;
}
}
}
}
}
style.css- 4. Vous devriez avoir ce rendu

Étape 2 : Ajouter une classe darkmode à la balise <body>
Pour faire simple, on va attribuer une class à la balise “body” de notre page. L’effet de la checkbox aura pour rôle de changer la classe de cette balise pour passer du darkmode au lightmode.
Ajout d’une classe “lightmode_on” à body sur un site hors WordPress.
Exemple sur une page html classique :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ma page web</title>
<link rel="stylesheet" href="style.css" media="all">
</head>
<body class="lightmode_on">
<nav id="menu-principal">
<ul class="menu">
<li class="menu-item"><a href="#accueil">Accueil</a></li>
<li class="menu-item"><a href="#services">Services</a></li>
<li class="menu-item"><a href="#a-propos">À propos</a></li>
<li class="menu-item"><a href="#contact">Contact</a></li>
</ul>
<label for="darkmode" class="switch">
<input id="darkmode" type="checkbox">
<span class="slider"></span>
</label>
</nav>
<h1>Tutoriel Darkmode</h1>
<section>
<h2>Pellentesque sit amet commodo odio</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris purus turpis, varius nec ante et,
convallis tempus lorem. Praesent faucibus aliquam vehicula. Quisque in laoreet velit. In iaculis risus
ut ipsum hendrerit ultrices. Etiam ultricies sed mi sit amet scelerisque. Duis ultricies ligula leo,
vitae faucibus sem cursus nec. Maecenas a mauris ante. Quisque ac tellus nec nisl vehicula pulvinar.
Integer eget est at magna efficitur eleifend. Fusce pretium vestibulum aliquet. Vivamus ullamcorper
libero vitae lacus pulvinar, sit amet tempor eros condimentum.
</p>
</section>
</body>
</html>
HTMLAjouter une classe à “body” sur un site WordPress :
Les entête WordPress sont quelques peut différentes d’un site statique car elles sontiennent des fonctions dynamiques.
<?php ?>
<!DOCTYPE html>
<html <?php language_attributes(); ?> class="no-js no-svg">
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="http://gmpg.org/xfn/11">
<title><?php wp_title('|', true, 'right'); ?></title>
<?php wp_head(); ?>
</head>
<body>header.phpC’est pourquoi, pour ajouter une classe à la balise body d’un site WordPress, il vous faudra ajouter ces quelques lignes de code dans “functions.php” de votre thème enfant ou de votre thème.
<?php
add_filter('body_class', function ($classes) {
$classes[] = 'lightmode_on';
return $classes;
});
?>
function.phpCe qui vous donnera ceci :

Étape 3 : Activer le dark mode avec JavaScript
A présent, on va venir créer une condition Javascript (JQuery) pour que lorsque l’on active notre checkbox, la classe “lightmode_on” va devenir “darkmode_on”.
Sur un site hors WordPress
En JQuery :
A la ligne 8 on importe la bibliothèque JQuery et à la ligne 29 le script (on l’importe en bas de page afin de ne pas bloquer le chargement)
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ma page web</title>
<link rel="stylesheet" href="style.css" media="all">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body class="lightmode_on">
<nav id="menu-principal">
<ul class="menu">
<li class="menu-item"><a href="#accueil">Accueil</a></li>
<li class="menu-item"><a href="#services">Services</a></li>
<li class="menu-item"><a href="#a-propos">À propos</a></li>
<li class="menu-item"><a href="#contact">Contact</a></li>
</ul>
<label for="darkmode" class="switch">
<input id="darkmode" type="checkbox">
<span class="slider"></span>
</label>
</nav>
<h1>Tutoriel Darkmode</h1>
<section>
<h2>Pellentesque sit amet commodo odio</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris purus turpis, varius nec ante et,
convallis tempus lorem. Praesent faucibus aliquam vehicula. Quisque in laoreet velit. In iaculis risus
ut ipsum hendrerit ultrices. Etiam ultricies sed mi sit amet scelerisque. Duis ultricies ligula leo,
vitae faucibus sem cursus nec. Maecenas a mauris ante. Quisque ac tellus nec nisl vehicula pulvinar.
Integer eget est at magna efficitur eleifend. Fusce pretium vestibulum aliquet. Vivamus ullamcorper
libero vitae lacus pulvinar, sit amet tempor eros condimentum.
</p>
</section>
<script src="chemin/js/darkmode.js" defer></script>
</body>
</html>
HTMLjQuery(function ($) {
$('#darkmode').on('change', function () {
if ($(this).is(':checked')) {
$('body').removeClass('lightmode_on darkmode_on');
$('body').addClass('darkmode_on');
} else {
$('body').removeClass('darkmode_on').addClass('lightmode_on');
}
});
});JQueryEn Javascript vanilla :
Ici on n’a pas besoin d’importer la bibliothèque JQuery.
document.addEventListener('DOMContentLoaded', function () {
const toggle = document.getElementById('darkmode');
if (!toggle) return;
toggle.addEventListener('change', function () {
const body = document.body;
if (toggle.checked) {
body.classList.remove('lightmode_on');
body.classList.add('darkmode_on');
} else {
body.classList.remove('darkmode_on');
body.classList.add('lightmode_on');
}
});
});Javascript VanillaImporter le script dans WordPress :
Si vous voulez appliquer cela à WordPress alors il va falloir importer votre fichier script à votre thème. A noter que dans WordPress, normalement, la bibliothèque JQuery est déjà présente, vous n’avez donc qu’à juste importer votre propre script en, vous assurant bien entendu qu’il sera en “defer” donc qu’il ne bloquera pas le chargement de votre page.
Voici le code à ajouter à function.php de votre thème ou thème enfant :
function inumedia_script_darkmode() {
// jQuery est une dépendance, donc WP le charge si besoin
wp_enqueue_script(
'darkmode-script',
get_template_directory_uri() . '/votre_chemin/js/darkmode.js',
array('jquery'),
null,
true // en pied de page
);
}
add_action('wp_enqueue_scripts', 'inumedia_script_darkmode');function.phpVérifications :
Vérifions à présent que tout fonctionne

Étape 4 : Appliquer les bons styles CSS
Maintenant, il ne nous reste qu’à donner un style à notre page une fois le darkmode actif.
Pour cela on va compléter notre css :
/* Activation / désactivation darkmode */
body {
&.lightmode_on { /* Light mode */
background-color: #ffffff;
color: #333;
& * {
transition: background-color 0.5s ease, color 0.5s ease;
}
nav {
background: linear-gradient(to bottom, #ffffff, #f5f5f5);
a{
color: #2e05b4;
}
}
section {
background-color: #f9f9f9;
div,
article {
background-color: #ffffff;
}
h1, h2, h3, h4, h5, h6 {
color: #222;
}
p {
color: #333;
}
}
}
&.darkmode_on { /* Dark mode */
background-color: #000000;
color: #ffffff;
& * {
transition: background-color 0.5s ease, color 0.5s ease;
}
nav {
background: linear-gradient(to bottom, #444242, #313030);
a{
color:#fff;
}
}
section {
background-color: #000000;
div,
article {
background-color: #000000;
}
h1, h2, h3, h4, h5, h6 {
color: #f5f5f5;
}
p {
color: #ffffff;
}
}
}
}
/* Navigation */
nav {
/* j'ai déplacé la couleur du fond dans la balise body */
padding: 0.5rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 2rem;
ul {
list-style: none;
display: flex;
justify-content: center;
margin: 0;
padding: 0;
li {
margin: 0 1rem;
a {
/* j'ai déplacé la couleur du texte dans la balise body */
font-weight: bold;
font-size: 1rem;
text-decoration: none;
text-transform: uppercase;
transition: color 0.3s ease;
}
}
}
/* Switch */
.switch {
position: relative;
display: inline-block;
width: 120px;
height: 40px;
input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
background-color: #eeeded;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: background-color 0.4s ease;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
font-family: Arial, sans-serif;
font-size: 0.9rem;
color: #333;
&::before {
content: "";
position: absolute;
height: 1.5rem;
width: 1.5rem;
left: 0.3rem;
bottom: 0.5rem;
background: url('day-icon.svg');
background-size: cover;
border-radius: 50%;
z-index: 1;
transition: left 0.4s ease, right 0.4s ease, background-color 0.4s ease;
}
.label-text {
width: 100%;
text-align: right;
z-index: 2;
padding-left: 0.1rem;
padding-right: 0;
transition: all 0.4s ease;
&::before {
content: "Light mode";
font-size: 0.9rem;
transition: content 0.4s ease;
}
}
}
input:checked + .slider {
background-color: #121212;
flex-direction: row-reverse;
&::before {
left: auto;
right: 0.3rem;
background: url(night_icon.svg);
background-size: cover;
}
.label-text {
text-align: left;
&::before {
content: "Dark mode";
color: white;
}
}
}
}
}
style.cssRendu du darkmode :

Aller plus loin : créer un dark mode personnalisé avec des variables CSS
Dans la version simplifiée, tous les textes ont la même couleur (blanc), je n’ai pas programmé non plus les boutons, mais si on ne veut pas trop perdre notre utilisateur et garder une expérience utilisateur, on peut pousser les choses en entrant des variables qui vont changer selon la condition souhaitée.
On va garder exactement le même JS que dans le début du tutoriel.
Je vais ajouter deux boutons dans mon html :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ma page web</title>
<link rel="stylesheet" href="style.css" media="all">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body class="lightmode_on">
<nav id="menu-principal">
<ul class="menu">
<li class="menu-item"><a href="#accueil">Accueil</a></li>
<li class="menu-item"><a href="#services">Services</a></li>
<li class="menu-item"><a href="#a-propos">À propos</a></li>
<li class="menu-item"><a href="#contact">Contact</a></li>
</ul>
<label for="darkmode" class="switch">
<input id="darkmode" type="checkbox">
<span class="slider"></span>
</label>
</nav>
<h1>Tutoriel Darkmode</h1>
<section>
<h2>Pellentesque sit amet commodo odio</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris purus turpis, varius nec ante et,
convallis tempus lorem. Praesent faucibus aliquam vehicula. Quisque in laoreet velit. In iaculis risus
ut ipsum hendrerit ultrices. Etiam ultricies sed mi sit amet scelerisque. Duis ultricies ligula leo,
vitae faucibus sem cursus nec. Maecenas a mauris ante. Quisque ac tellus nec nisl vehicula pulvinar.
Integer eget est at magna efficitur eleifend. Fusce pretium vestibulum aliquet. Vivamus ullamcorper
libero vitae lacus pulvinar, sit amet tempor eros condimentum.
</p>
<div class="wp-block-buttons">
<div class="wp-block-button">Bouton simple</div>
<div class="wp-block-button cta">Call to action</div>
</div>
</section>
<script src="chemin/js/darkmode.js" defer></script>
</body>
</html>
HTMLEt on va améliorer notre CSS :
Pour cela, on va éviter de répéter le même code entre les deux modes et on va utiliser des variables. Leurs valeurs changeront selon si notre checkbox est cochée ou si elle ne l’est pas.
/* Activation / désactivation darkmode */
body {
--texteliens: #2e05b4;
--textebody: #333;
--texteh1: #a3062a;
--textetitres: #063ba3;
--boutoncta: #9606a3;
--degrade1: #ffffff;
--degrade2: #f5f5f5;
--blanccasse: #f5f5f5;
--boutonbg: #333;
--boutontexte: #f5f5f5;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.2;
color: var(--textebody);
& * {
transition: background-color 0.5s ease, color 0.5s ease;
}
nav {
background: linear-gradient(to bottom, var(--degrade1), var(--degrade2));
a {
color: var(--texteliens);
}
}
.wp-block-buttons {
display: flex;
flex-direction: row;
.wp-block-button {
background-color: var(--boutonbg);
color: var(--boutontexte);
margin: 0.5rem;
padding: 0.2rem 0.5rem;
min-height: 34px;
display: flex;
align-items: center;
&.cta {
background-color: var(--boutoncta);
color: white;
}
}
}
h1 {
color: var(--texteh1);
}
section {
background-color: var(--blanccasse);
div,
article {
background-color: var(--blanccasse);
}
h2,
h3,
h4,
h5,
h6 {
color: var(--textetitres);
}
p {
color: var(--textebody);
}
}
&.lightmode_on {
/* Light mode */
--texteliens: #2e05b4;
--textebody: #333;
--texteh1: #a3062a;
--textetitres: #063ba3;
--boutoncta: #9606a3;
--degrade1: #ffffff;
--degrade2: #f5f5f5;
--blanccasse: #f5f5f5;
--boutonbg: #333;
--boutontexte: #f5f5f5;
background-color: white;
}
&.darkmode_on {
--texteliens: #fa8109;
--textebody: #ffffff;
--texteh1: #fb8dff;
--textetitres: #03b5e8;
--boutoncta: #ff0808;
--degrade1: #444242;
--degrade2: #313030;
--blanccasse: #000000;
--boutonbg: #333;
--boutontexte: #f5f5f5;
background-color: #000000;
}
}
/* Navigation */
nav {
/* j'ai déplacé la couleur du fond dans la balise body */
padding: 0.5rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 2rem;
ul {
list-style: none;
display: flex;
justify-content: center;
margin: 0;
padding: 0;
li {
margin: 0 1rem;
a {
/* j'ai déplacé la couleur du texte dans la balise body */
font-weight: bold;
font-size: 1rem;
text-decoration: none;
text-transform: uppercase;
transition: color 0.3s ease;
}
}
}
/* Switch */
.switch {
position: relative;
display: inline-block;
width: 120px;
height: 40px;
input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
background-color: #eeeded;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: background-color 0.4s ease;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
font-family: Arial, sans-serif;
font-size: 0.9rem;
color: #333;
&::before {
content: "";
position: absolute;
height: 1.5rem;
width: 1.5rem;
left: 0.3rem;
bottom: 0.5rem;
background: url('day-icon.svg');
background-size: cover;
border-radius: 50%;
z-index: 1;
transition: left 0.4s ease, right 0.4s ease, background-color 0.4s ease;
}
.label-text {
width: 100%;
text-align: right;
z-index: 2;
padding-left: 0.1rem;
padding-right: 0;
transition: all 0.4s ease;
&::before {
content: "Light mode";
font-size: 0.9rem;
transition: content 0.4s ease;
}
}
}
input:checked + .slider {
background-color: #121212;
flex-direction: row-reverse;
&::before {
left: auto;
right: 0.3rem;
background: url(night_icon.svg);
background-size: cover;
}
.label-text {
text-align: left;
&::before {
content: "Dark mode";
color: white;
}
}
}
}
}
style.cssCe qui nous donne ceci en rendu :

Conclusion : pourquoi (et comment) proposer un mode sombre
Proposer un thème sombre peut apporter une expérience utilisateur non négligeable et cela, peu importe le CMS utilisé, voire même sur un site statique sur un site statique. Il existe bien des manières de le faire mais passer parfois par quelques lignes de code vous permettra de ne pas surcharger votre site.
Pour les utilisateurs de WordPress avancé / développeurs, vous pourrez même proposer à vos clients une interface de personnalisation dans l’administration via des pages d’options réalisées from scratch ou avec le plugin ACF et avec des picker de couleurs.
Intégrez vos designs dans vos pages web