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 meta correspondante permettent aux développeurs d'activer les paramètres par défaut spécifiques au thème de la feuille de style de l'agent utilisateur pour leurs pages.

Arrière-plan

La fonctionnalité média de préférence utilisateur prefers-color-scheme

La fonctionnalité média de préférence utilisateur prefers-color-scheme offre aux développeurs un contrôle total sur l'apparence de leurs pages. Si vous ne le connaissez pas, veuillez lire mon article prefers-color-scheme : Hello darkness, my old friend, dans lequel j'ai documenté tout ce que je sais sur la création d'expériences en mode sombre exceptionnelles.

Un élément qui n'a été que brièvement mentionné dans l'article est la propriété CSS color-scheme et la balise meta correspondante du même nom. Les deux vous facilitent la vie en tant que développeur en vous permettant d'activer les paramètres par défaut spécifiques au thème de la feuille de style de l'agent utilisateur pour votre page, tels que les contrôles 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 eux-mêmes des transformations.

Prise en charge des navigateurs

prefers-color-scheme

Browser Support

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

Source

color-scheme

Browser Support

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

Source

Feuille de style de l'agent utilisateur

Avant de continuer, laissez-moi vous expliquer brièvement ce qu'est une feuille de style d'agent utilisateur. La plupart du temps, vous pouvez considérer le terme agent utilisateur (UA) comme une façon sophistiquée de dire navigateur. La feuille de style de l'agent utilisateur 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 général, les feuilles de style UA sont d'accord sur la majorité des éléments. Par exemple, ils rendent tous les liens bleus, le texte général noir et la couleur d'arrière-plan blanche. Toutefois, il existe également des différences importantes (et parfois ennuyeuses), par exemple la façon dont ils stylisent les contrôles de formulaire.

Examinons de plus près la feuille de style UA de WebKit et ce qu'elle fait concernant le mode sombre. (Effectuez une recherche en texte intégral sur "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 pseudo-classe :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 le CSS a normalisé les couleurs sémantiques du système. Elles sont spécifiées dans le module de couleur CSS de niveau 4. Par exemple, Canvas (à ne pas confondre avec la balise <canvas>) concerne l'arrière-plan du contenu ou des documents de l'application, tandis que CanvasText concerne le texte du contenu ou des documents de l'application. Les deux vont de pair et ne doivent pas être utilisés de manière isolée.

Les feuilles de style UA peuvent utiliser leurs propres couleurs propriétaires ou les couleurs standardisées du système sémantique 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) est défini sur noir. La feuille de style UA attribue ensuite le code CSS suivant une seule fois, et couvre les modes clair et sombre.

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

Propriété CSS color-scheme

La spécification CSS Color Adjustment Module Level 1 introduit un modèle et des contrôles sur l'ajustement automatique des couleurs par l'agent utilisateur dans le but de gérer les préférences de l'utilisateur, telles que le mode sombre, l'ajustement du contraste ou les jeux de couleurs spécifiques souhaités.

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

  • normal Indique que l'élément n'est pas du tout conscient des schémas de couleurs. Il doit donc être affiché avec le schéma de couleurs par défaut du navigateur.

  • [ light | dark ]+ Indique que l'élément connaît les schémas de couleurs listés et peut les gérer, et exprime une préférence ordonnée entre eux.

Dans cette liste, light représente un jeu de couleurs claires, 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'ensemble de l'UI fournie par le navigateur pour l'élément correspondent à l'intention du jeu de couleurs. Exemples : barres de défilement, soulignements de l'orthographe, 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 de la fenêtre d'affichage.

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

Balise Meta color-scheme

Pour respecter la propriété CSS color-scheme, le fichier 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 Meta et la propriété CSS (si elle est appliquée à l'élément :root) entraînent finalement le même comportement, je recommande toujours de spécifier le schéma de couleurs via la balise Meta, afin que le navigateur puisse adopter le schéma préféré plus rapidement.

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

J'ai signalé des bugs pour Chrome, WebKit et Firefox ainsi qu'un problème général dans la norme HTML pour que ce problème soit résolu.

Interplay avec prefers-color-scheme

L'interaction entre la propriété CSS color-scheme et la balise meta correspondante avec la fonctionnalité média de préférence utilisateur prefers-color-scheme peut sembler déroutante au premier abord. En fait, ils jouent très bien ensemble. Il est important de comprendre que color-scheme détermine exclusivement l'apparence par défaut, tandis que prefers-color-scheme détermine l'apparence stylable. Pour plus de clarté, prenons l'exemple de la page suivante :

<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é à la page définit la propriété 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 schéma de couleurs dark selon la fonctionnalité média de préférence utilisateur prefers-color-scheme.

Grâce à l'élément <meta name="color-scheme" content="dark light">, la page indique au navigateur qu'elle est compatible avec un thème sombre et un thème clair, avec une préférence pour le thème sombre.

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

Notez comment le background-color de l'élément <fieldset> change selon que le mode sombre est activé ou non, en suivant les 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 est 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'agent utilisateur. Le texte est blanc et l'arrière-plan est 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 ainsi que 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 computed des commutateurs 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 l'élément <button> dont la propriété color est définie sur la couleur système correspondante ButtonText.

Montre 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'agent utilisateur, sont désormais rgba(0, 0, 0, 0.847).
Montre que les valeurs de couleur calculées correspondent toujours à ButtonFace en mode sombre.
Mode sombre : 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'agent utilisateur, 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émonstration sur Glitch. La démo montre délibérément la violation des critères WCAG AA et WCAG AAA avec les couleurs de lien mentionnées dans l'avertissement ci-dessus.

Démo en mode clair.
La démonstration est définie sur color-scheme: light.
Démonstration en mode sombre.
La démonstration est activée sur color-scheme: dark. Notez la non-conformité WCAG AA et WCAG AAA avec les couleurs des liens.

Remerciements

La propriété CSS color-scheme et la balise meta correspondante ont été implémentées par Rune Lillesveen. Rune est également co-éditeur de la spécification CSS Color Adjustment Module Level 1. Image principale par Philippe Leone sur Unsplash.