Valentin Dupas

💡 If this is the first course you read from me, please read this small thing : about my courses

Thème

J'ai mentionné très très vite le concept de dark mode mais c'était juste pour vous demander de changer les couleurs de la page pour la mettre blanc sur noir. Maintenant on va voir comment faire ça correctement.

prefers-color-scheme

Et pour continuer dans mon délire de vous montrer ce qui est populaire d'abord et moderne ensuite, je vais commencer par prefers-color-scheme.

Il s'agit d'une media query qui s'écrit comme ceci

@media (prefers-color-scheme: dark) {
  body {
    background: black;
    color: white;
  }
}

Cette media query n'applique sont style que si le thème configuré sur la machine de l'utilisateur est sombre. On peut aussi utiliser light à la place de dark.

On notera que l'utilisation classique reste celle montrée ci-dessus, parcequ'elle s'appuie sur le style par défaut des navigateurs. Le thème par défaut est light on n'as pas besoin d'écrire ceci au dessus de la media query:

body {
  background-color: white;
  color: black;
}

... mais c'est l'idée. "Ma page est noir sur blanc (par défaut), mais si mon utilisateur à configuré sa machine sur le thème sombre, alors ma page est blanc sur noir".

"Jour, nuit, jour, nuit..."

Plutôt que d'aller changer les paramètres de votre système toutes les 5min, sachez qu'il est possible de forcer votre navigateur à simuler ce paramètre.

Firefox:



Chrome:

color-scheme

Par défaut, si on n'utilise pas prefers-color-scheme, les navigateurs afficheront les pages en light mode ... efin, pas vraiment. Il les affichera "normalement" ce qui ressemble fortement au light mode, mais qui n'est pas explicitement le light mode, on pourrait imaginer un navigateur qui deciderait d'avoir un mode normal, un mode light, et un dark mode tous les 3 différents, mais en pratique j'en connais aucun.

On peut prendre le contrôle de ça via la propriété color-scheme comme ceci:

:root {
  color-scheme: dark;
}

Dans cet exemple on spécifie que la page sera en dark mode, peu importe la configuration de la machine.

Voici la liste des valeurs que l'on peut fournir:

  • normal: la valeur par défaut. On utilisera le color-scheme du parent, ou la config par défaut de la page sinon.
  • light : on utilise le mode light
  • dark : on utilise le mode dark
  • light dark : on laisse le navigateur s'adapter à la configuration de la machine
  • only light : on utilise le mode light et aucune extension du navigateur peut écraser ça
  • only dark : on utilise le mode dark et aucune extension du navigateur peut écraser ça

On pourrait croire que light dark n'est pas nécessaire, après tout on pouvait déjà s'adapter à la config de l'utilisateur avec prefers-color-scheme, mais pas vraiment. color-scheme contrôle la mise en style par défaut du navigateur, si vous ne mettez rien dans votre CSS à part la declaration ci-dessus, vous remarquerez que votre page sera blanc sur noir, que vos scrollbars seront sombres, le style par défaut de vos boutons aussi etc...

Donc, prefers-color-scheme nous permet d'injecter du style si l'utilisateur configure sa machine en dark mode. Tandis que color-scheme nous permet de contrôler, et d'adapter, le style par défaut des navigateurs.

System-colors

D'ailleurs, on peut acceder aux couleurs par défaut des navigateurs via des variables spéciales.

Les voici: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/system-color

C'est sympa si on veux faire des pages minimalistes et étoffer le style par défaut plutôt que de tout écraser/refaire.

Mais c'est aussi sympa comme valeurs de secours, valeurs dites "fallback". Quand on utilise les variables avec var() on peut fournir plusieurs variables qui seront essayées dans l'ordre, le navigateur gardant la première qui marche, comme les polices.

a {
  color: var(--link-color, LinkText);
}

Autrement dit, dans cet exemple, je vais utiliser ma variable --link-color mais si elle n'existe pas (ou n'est pas encore chargée) alors on utilisera la couleur que le navigateur associe aux liens.

... mmmmh, je sens que ce n'est pas clair, et en même temps c'est normal. C'est une technique qui va avec les webcomponent (qu'on a pas encore vu), quand on essaye de créer des éléments qui on un comportement et une mise en forme custom, ça nous permet qu'au pire ils aient un comportement proche des éléments de base pour ne pas faire tâche.

light-dark()

Aussi, quand vous fournissez un color-scheme, vous pouvez utiliser light-dark() pour fournir deux valeurs à une propriétés. La propriété prendra la valeur du thème actif, donc la première valeur si le thème est light, la deuxième si c'est dark.

:root {
  color-scheme: light dark;
}

body {
  color: light-dark(brown, beige);
  backgroud-color: light-dark(beige, brown);
}

Donc, si la machine de l'utilisateur est configurée pour le thème light, mon texte sera marron et mon fond beige, et si elle est configurée pour le dark mode alors le texte de ma page sera beige sur un fond marron.

MORE!!!

Personnellement je n'aime pas light-dark(), je préfère créer une collection de variables qui correspondent au mode light puis de mettre une media query prefers-color-scheme:dark pour toutes les ramplacer si l'utilisateur veux le dark mode, ce qui fait que dans tout le reste du CSS je n'ai plus à m'en soucier, j'utilise juste ma collection de variables et c'est tout.

:root {
  --text: #222323;
  --bg: #f0f6f0;
  --link: #1b4699;
}

@media (prefers-color-scheme: dark) {
  :root {
    --text: #f0f6f0;
    --bg: #222323;
    --link: #7eb0f0;
  }
}

body {
  color: var(--text);
  background-color: var(--bg);
}

a {
  color: var(--link);
}

Ce qui est cool parce que je peux aller plus loin et créer une classe que je peux mettre sur mon <html> comme ceci

.minty {
  --text: #ffffff;
  --bg: #201b1b;
  --link: #96fbc7;
}

Classe que je peux accrocher et retirer de mon <html> quand l'utilsateur clique sur un bouton, permettant donc un proposition de thèmes plus large que juste "light ou dark". Rien ne me limite, ce genre de "classe en tant que thème" je peux en avoir autant que je veux.

Exemple, le sélecteur de thème dans le configurateur fournit dans la doc de R.css : https://zhakk-harn.github.io/Rcss/

Tout ceci étant dit, je me rend compte que je peux écrire ceci:

:root {
  color-scheme: light dark;
  --text: light-dark(#222323, #f0f6f0);
  --bg: light-dark(#f0f6f0, #222323);
}

Je ne trouve pas qu'une solution soit meilleure que l'autre. Ma vieille méthode me parait plus claire à la lecture, parce qu'il n'y a pas plein de "light-dark" qui polluent visuellement l'espace et parce que je n'ai pas à garder en tête que light = gauche et dark = droite. D'un autre côté, cette solution est verticalement plus compacte et surtout elle garantie que je vais forcément avoir le même nombre de variables avec les même noms puisqu'on a pas à garder deux blocs à jour, ce qui est plutôt pas mal.

J'ai probablement un a priori trop négatif sur light-dark() parce que j'ai essentiellement vu des gens en parsemer partout dans leur feuilles de style plutôt que pour créer un bloc de thème, et ça par contre c'est pas ouf.

À méditer.