Amélioration du style par défaut du mode sombre avec la propriété CSS color-scheme et la balise Meta correspondante

La propriété CSS color-scheme et la balise méta correspondante permettent aux développeurs d'activer les valeurs par défaut spécifiques au thème de la feuille de style de l'user-agent pour leurs pages.

Contexte

Fonctionnalité multimédia des préférences utilisateur prefers-color-scheme

La fonctionnalité de médias de préférences utilisateur prefers-color-scheme permet aux développeurs de contrôler entièrement l'apparence de leurs pages. Si vous ne connaissez pas ce mode, veuillez lire mon article prefers-color-scheme: Hello darkness, my old friend, dans lequel j'ai décrit tout ce que je sais sur la création d'expériences de mode sombre exceptionnelles.

Un élément de l'article n'a été que brièvement mentionné : la propriété CSS color-scheme et la balise méta correspondante du même nom. Ils facilitent votre travail en tant que développeur en vous permettant d'activer les valeurs par défaut spécifiques au thème de la feuille de style de l'agent utilisateur, telles que les commandes de formulaire, les barres de défilement et les couleurs système CSS. En même temps, cette fonctionnalité empêche les navigateurs d'appliquer des transformations par eux-mêmes.

Prise en charge des navigateurs

prefers-color-scheme

Navigateurs pris en charge

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 67.
  • Safari: 12.1.

Source

color-scheme

Navigateurs pris en charge

  • Chrome: 81.
  • Edge: 81.
  • Firefox: 96.
  • Safari: 13.

Source

Feuille de style de l'user-agent

Avant de continuer, laissez-moi vous expliquer brièvement ce qu'est une feuille de style pour user-agent. La plupart du temps, vous pouvez considérer le mot user-agent (UA) comme une façon élégante de dire navigateur. La feuille de style UA détermine l'apparence par défaut d'une page. Comme son nom l'indique, une feuille de style UA dépend de l'UA en question. Vous pouvez consulter la feuille de style UA de Chrome (et de Chromium) et la comparer à celle de Firefox ou de Safari (et de WebKit). En règle générale, les feuilles de style UA sont d'accord sur la plupart des éléments. Par exemple, ils utilisent tous le bleu pour les liens, le noir pour le texte général et le blanc pour l'arrière-plan. Toutefois, il existe également des différences importantes (et parfois gênantes), par exemple dans la façon dont ils stylisent les commandes de formulaire.

Découvrez plus en détail la feuille de style UA de WebKit et son rôle concernant le mode sombre. (Effectuez une recherche en texte intégral pour "dark" dans la feuille de style.) La valeur par défaut fournie par la feuille de style change selon que le mode sombre est activé ou non. Pour illustrer cela, voici une règle CSS utilisant la classe pseudo :matches et les variables internes à WebKit telles que -apple-system-control-background, ainsi que la directive de préprocesseur interne à WebKit #if defined:

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

Vous remarquerez des valeurs non standards pour les propriétés color et background-color ci-dessus. Ni text, ni -apple-system-control-background ne sont des couleurs CSS valides. Il s'agit de couleurs sémantiques internes à WebKit.

Il s'avère que CSS a standardisé les couleurs système sémantiques. Elles sont spécifiées dans le niveau 4 du module de couleurs CSS. Par exemple, Canvas (à ne pas confondre avec la balise <canvas>) est destiné à l'arrière-plan du contenu ou des documents de l'application, tandis que CanvasText est destiné au texte du contenu ou des documents de l'application. Les deux vont de pair et ne doivent pas être utilisés séparément.

Les feuilles de style UA peuvent utiliser leurs propres couleurs propriétaires ou les couleurs du système sémantique standardisées pour déterminer comment les éléments HTML doivent être affichés par défaut. Si le système d'exploitation est défini sur le mode sombre ou utilise un thème sombre, CanvasText (ou text) est défini de manière conditionnelle sur blanc, et Canvas (ou -apple-system-control-background) sur noir. La feuille de style UA n'attribue ensuite le CSS suivant qu'une seule fois et couvre à la fois le mode clair et le mode sombre.

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

Propriété CSS color-scheme

La spécification du module CSS d'ajustement des couleurs de niveau 1 introduit un modèle et des commandes pour l'ajustement automatique des couleurs par l'agent utilisateur dans le but de gérer les préférences des utilisateurs, telles que le mode sombre, l'ajustement du contraste ou les jeux de couleurs souhaités spécifiques.

La propriété color-scheme définie dans celle-ci permet à un élément d'indiquer les combinaisons de couleurs avec lesquelles il peut être affiché. Ces valeurs sont négociées avec les préférences de l'utilisateur, ce qui permet de choisir un jeu de couleurs qui affecte des éléments de l'interface utilisateur (UI), tels que les couleurs par défaut des commandes de formulaire et des barres de défilement, ainsi que les valeurs utilisées des couleurs du système CSS. Les valeurs suivantes sont actuellement prises en charge :

  • normal : indique que l'élément n'est pas du tout conscient des jeux de couleurs et qu'il doit donc être affiché avec le jeu de couleurs par défaut du navigateur.

  • [ light | dark ]+ : indique que l'élément est conscient des jeux de couleurs listés et qu'il peut les gérer, et exprime une préférence ordonnée entre eux.

Dans cette liste, light représente un jeu de couleurs clair, avec des couleurs d'arrière-plan claires et des couleurs de premier plan sombres, tandis que dark représente l'inverse, avec des couleurs d'arrière-plan sombres et des couleurs de premier plan claires.

Pour tous les éléments, le rendu avec un jeu de couleurs doit faire en sorte que les couleurs utilisées dans l'UI fournie par le navigateur pour l'élément correspondent à l'intention du jeu de couleurs. Il peut s'agir, par exemple, de barres de défilement, de soulignements de correction orthographique, de commandes de formulaire, etc.

Sur l'élément :root, le rendu avec un jeu de couleurs doit également affecter la couleur de surface du canevas (c'est-à-dire la couleur d'arrière-plan globale), la valeur initiale de la propriété color et les valeurs utilisées des couleurs système, et doit également affecter les barres de défilement du viewport.

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

La balise Meta color-scheme

Pour respecter la propriété CSS color-scheme, le CSS doit d'abord être téléchargé (s'il est référencé via <link rel="stylesheet">) et analysé. Pour aider les agents utilisateur à afficher l'arrière-plan de la page avec le jeu de couleurs souhaité immédiatement, une valeur color-scheme peut également être fournie dans un élément <meta name="color-scheme">.

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

Combiner color-scheme et prefers-color-scheme

Étant donné que la balise méta et la propriété CSS (si appliquée à l'élément :root) finissent par entraîner le même comportement, je recommande toujours de spécifier le jeu de couleurs via la balise méta afin que le navigateur puisse s'adapter plus rapidement au jeu de couleurs préféré.

Bien qu'aucune règle CSS supplémentaire ne soit nécessaire pour les pages de référence absolues, dans le cas général, vous devez toujours combiner color-scheme avec prefers-color-scheme. Par exemple, la couleur CSS propriétaire -webkit-link de WebKit, utilisée par WebKit et Chrome pour le bleu de lien classique rgb(0,0,238), a un rapport de contraste insuffisant de 2,23:1 sur un arrière-plan noir et ne répond pas aux exigences des WCAG AA et WCAG AAA.

J'ai ouvert des bugs pour Chrome, WebKit et Firefox, ainsi qu'un problème méta dans la norme HTML pour résoudre ce problème.

Interagir avec prefers-color-scheme

L'interaction entre la propriété CSS color-scheme et la balise méta correspondante avec la fonctionnalité multimédia de préférences utilisateur prefers-color-scheme peut sembler déroutante au premier abord. En fait, ils fonctionnent très bien ensemble. Le plus important à comprendre est que color-scheme détermine exclusivement l'apparence par défaut, tandis que prefers-color-scheme détermine l'apparence stylable. Pour clarifier ce point, supposons que la page suivante s'affiche:

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

Le code CSS intégré sur la page définit le background-color de l'élément <fieldset> sur gainsboro dans le cas général et sur darkslategray si l'utilisateur préfère un jeu de couleurs dark conformément à la fonctionnalité multimédia de préférences utilisateur prefers-color-scheme.

Via l'élément <meta name="color-scheme" content="dark light">, la page indique au navigateur qu'elle prend en charge un thème sombre et un thème clair, avec une préférence pour un thème sombre.

Selon que le système d'exploitation est défini en mode sombre ou clair, l'ensemble de la page s'affiche en clair sur sombre ou inversement, en fonction de la feuille de style de l'agent utilisateur. Aucun CSS supplémentaire fourni par le développeur n'est impliqué pour modifier le texte du paragraphe ou la couleur d'arrière-plan de la page.

Notez que le background-color de l'élément <fieldset> change en fonction de l'activation du mode sombre, conformément aux règles de la feuille de style intégrée fournie par le développeur sur la page. Il s'agit de gainsboro ou de darkslategray.

Page en mode clair.
Mode clair:styles spécifiés par le développeur et l'agent utilisateur. Le texte est noir et l'arrière-plan blanc, conformément à la feuille de style de l'agent utilisateur. Le background-color de l'élément <fieldset> est gainsboro, conformément à la feuille de style du développeur intégrée.
Page en mode sombre.
Mode sombre:styles spécifiés par le développeur et l'user-agent. Le texte est blanc et l'arrière-plan noir, conformément à la feuille de style de l'agent utilisateur. Le background-color de l'élément <fieldset> est darkslategray, conformément à la feuille de style du développeur intégrée.

L'apparence de l'élément <button> est contrôlée par la feuille de style de l'agent utilisateur. Son color est défini sur la couleur système ButtonText, et son background-color et les quatre border-color sont définis sur la couleur système ButtonFace.

Page en mode clair qui utilise la propriété ButtonFace.
Mode clair:background-color et les différents border-color sont définis sur la couleur système ButtonFace.

Notez maintenant comment le border-color de l'élément <button> change. La valeur calculée pour border-top-color et border-bottom-color passe de rgba(0, 0, 0, 0.847) (noirâtre) à rgba(255, 255, 255, 0.847) (blanchâtre), car l'agent utilisateur met à jour ButtonFace de manière dynamique en fonction du jeu de couleurs. Il en va de même pour le color de l'élément <button>, qui est défini sur la couleur système ButtonText correspondante.

Indique que les valeurs de couleur calculées correspondent à ButtonFace.
Mode clair:les valeurs calculées de border-top-color et de border-bottom-color, qui sont toutes deux définies sur ButtonFace dans la feuille de style de l'user-agent, sont désormais rgba(0, 0, 0, 0.847).
Indique que les valeurs de couleur calculées correspondent toujours à ButtonFace en mode sombre.
Mode sombre:les valeurs calculées de border-top-color et border-bottom-color, qui sont toutes deux définies sur ButtonFace dans la feuille de style de l'user-agent, sont désormais rgba(255, 255, 255, 0.847).

Démo

Vous pouvez voir les effets de color-scheme appliqués à un grand nombre d'éléments HTML dans une démo sur Glitch. La démonstration délibérément montre la non-conformité aux WCAG AA et WCAG AAA avec les couleurs de lien mentionnées dans l'avertissement ci-dessus.

Démo en mode clair.
La démo est activée sur color-scheme: light.
Démo en mode sombre.
La démo est activée sur color-scheme: dark. Notez le non-respect des WCAG AA et WCAG AAA concernant les couleurs des liens.

Remerciements

La propriété CSS color-scheme et la balise méta correspondante ont été implémentées par Rune Lillesveen. Rune est également co-rédacteur de la spécification du module de réglage des couleurs CSS au niveau 1. Image principale par Philippe Leone sur Unsplash.