Se mejoró el estilo predeterminado del modo oscuro con la propiedad CSS de color-scheme y la metaetiqueta correspondiente.

La propiedad color-scheme de CSS y la metaetiqueta correspondiente permiten a los desarrolladores habilitar sus páginas en los valores predeterminados específicos del tema de la hoja de estilo del usuario-agente.

Información general

La función de contenido multimedia de preferencias del usuario de prefers-color-scheme

La función de contenido multimedia de preferencias del usuario prefers-color-scheme les brinda a los desarrolladores control total sobre la apariencia de sus páginas. Si no la conoces, lee el artículo prefers-color-scheme: Hola, oscuridad, mi viejo amigo, en el que documenté todo lo que sé sobre la creación de experiencias asombrosas en modo oscuro.

Una pieza del rompecabezas que se mencionó de forma breve en el artículo es la propiedad color-scheme de CSS y la metaetiqueta correspondiente del mismo nombre. Ambos te facilitan la vida como desarrollador, ya que te permiten habilitar la configuración predeterminada de un tema de la hoja de estilo del usuario-agente en tu página, como los controles de formularios, las barras de desplazamiento y los colores del sistema CSS. Al mismo tiempo, esta función evita que los navegadores apliquen transformaciones por su cuenta.

Navegadores compatibles

prefers-color-scheme

Navegadores compatibles

  • 76
  • 79
  • 67
  • 12.1

Origen

color-scheme

Navegadores compatibles

  • 81
  • 81
  • 96
  • 13

Origen

La hoja de estilo del usuario-agente

Antes de continuar, permítanme describir de forma breve qué es una hoja de estilo de usuario-agente. La mayoría de las veces, se puede pensar en la palabra usuario-agente (UA) como una forma sofisticada de decir navegador. La hoja de estilo de UA determina el aspecto predeterminado de una página. Como su nombre lo indica, una hoja de estilo de UA es algo que depende de la UA en cuestión. Consulta la hoja de estilo de UA de Chrome (y Chromium) y compárala con la de Firefox o Safari (y WebKit). Por lo general, las hojas de estilo de UA coinciden en la mayoría de los aspectos. Por ejemplo, todos hacen que los vínculos sean azules, el texto general es negro y el color de fondo es blanco, pero también hay diferencias importantes (y a veces molestas), por ejemplo, la forma en que diseñan los controles del formulario.

Examina con más detalle la hoja de estilo de UA de WebKit y lo que hace en relación con el modo oscuro. (Busca "oscuro" en el texto completo de la hoja de estilo). El valor predeterminado que proporciona la hoja de estilo cambia en función de si el modo oscuro está activado o desactivado. Para ilustrar esto, a continuación se muestra una de esas reglas de CSS que usa la seudoclase :matches y las variables internas de WebKit, como -apple-system-control-background, así como la directiva de preprocesador interno de 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 */
}

Verás algunos valores no estándar para las propiedades color y background-color anteriores. Ni text ni -apple-system-control-background son colores de CSS válidos. Son colores semánticos internos de WebKit.

Resulta que CSS tiene colores de sistema semántico estandarizados. Se especifican en el nivel de módulo de color CSS 4. Por ejemplo, Canvas (que no debe confundirse con la etiqueta <canvas>) sirve para el fondo del contenido o los documentos de la aplicación, mientras que CanvasText es para texto en el contenido o los documentos de la aplicación. Ambas van juntas y no deben usarse de forma aislada.

Las hojas de estilo de UA pueden usar sus propios colores propios o los colores estandarizados del sistema semántico para determinar cómo se deben renderizar los elementos HTML de forma predeterminada. Si el sistema operativo está configurado en modo oscuro o usa un tema oscuro, CanvasText (o text) se establece de forma condicional en blanco y Canvas (o -apple-system-control-background) se establece en negro. Luego, la hoja de estilo UA asigna el siguiente CSS solo una vez, y abarca el modo claro y el oscuro.

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

La propiedad color-scheme de CSS

La especificación del nivel de módulo de ajuste de color CSS nivel 1 presenta un modelo y controles sobre el ajuste automático de color por parte del usuario-agente con el objetivo de controlar las preferencias del usuario, como el modo oscuro, el ajuste de contraste o esquemas de color deseados.

La propiedad color-scheme que se define allí permite que un elemento indique con qué esquemas de colores le resulta cómodo renderizar. Estos valores se negocian con las preferencias del usuario, lo que genera un esquema de colores elegido que afecta los elementos de la interfaz de usuario (IU), como los colores predeterminados de los controles de formularios y las barras de desplazamiento, así como los valores usados de los colores del sistema CSS. Se admiten los siguientes valores:

  • normal Indica que el elemento no conoce los esquemas de color, por lo que se debe renderizar con el esquema de colores predeterminado del navegador.

  • [ light | dark ]+ Indica que el elemento conoce los esquemas de colores de la lista y puede controlarlos, y expresa una preferencia ordenada entre ellos.

En esta lista, light representa un esquema de colores claros, con colores de fondo claros y colores de primer plano oscuros, mientras que dark representa lo contrario, con colores de fondo oscuros y colores claros de primer plano.

Para todos los elementos, la renderización con un esquema de colores debe hacer que los colores que se usan en toda la IU proporcionada por el navegador coincidan con el intent del esquema de colores. Algunos ejemplos son las barras de desplazamiento, el subrayado del corrector ortográfico, los controles de formularios, etcétera.

En el elemento :root, la renderización con un esquema de colores debe afectar, además, el color de la superficie del lienzo (es decir, el color de fondo global), el valor inicial de la propiedad color y los valores usados de los colores del sistema, y también debe afectar las barras de desplazamiento del viewport.

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

La metaetiqueta color-scheme

Para cumplir con la propiedad color-scheme de CSS, primero se debe descargar el CSS (si se hace referencia a través de <link rel="stylesheet">) y se debe analizar. Para ayudar a los usuarios-agentes a renderizar el fondo de la página con el esquema de colores deseado de inmediato, también se puede proporcionar un valor color-scheme en un elemento <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">

Cómo combinar color-scheme y prefers-color-scheme

Dado que tanto la metaetiqueta como la propiedad de CSS (si se aplica al elemento :root) finalmente generan el mismo comportamiento, siempre recomendamos especificar el esquema de colores a través de la metaetiqueta, de modo que el navegador pueda adoptar el esquema preferido más rápido.

Si bien no se necesitan reglas de CSS adicionales para las páginas de referencia absoluta, en el caso general, siempre debes combinar color-scheme con prefers-color-scheme. Por ejemplo, el color -webkit-link de CSS de WebKit, que usan WebKit y Chrome para el rgb(0,0,238) de color azul clásico, no tiene una proporción de contraste insuficiente de 2.23:1 sobre un fondo negro y no cumple los requisitos de WCAG AA y WCAG AAA.

Abrí errores de Chrome, WebKit y Firefox, así como un metaproblema en HTML estándar para solucionarlo.

Interacción con prefers-color-scheme

La interacción de la propiedad color-scheme de CSS y la metaetiqueta correspondiente con la función de medios de preferencia del usuario prefers-color-scheme puede parecer confusa al principio. De hecho, juegan muy bien juntos. Lo más importante que debes comprender es que color-scheme determina exclusivamente la apariencia predeterminada, mientras que prefers-color-scheme determina la apariencia estilable. Para dejar esto más claro, usa la siguiente página:

<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>

El código CSS intercalado de la página establece el background-color del elemento <fieldset> en gainsboro, en el caso general, y en darkslategray si el usuario prefiere un esquema de colores dark según la función de medios de preferencia del usuario prefers-color-scheme.

Mediante el elemento <meta name="color-scheme" content="dark light">, la página le indica al navegador que admite un tema oscuro y uno claro, con preferencia por un tema oscuro.

En función de si el sistema operativo está configurado en modo oscuro o claro, toda la página se muestra clara en el modo oscuro, o viceversa, según la hoja de estilo del usuario-agente. No se proporciona CSS adicional por el desarrollador para cambiar el texto del párrafo o el color de fondo de la página.

Observa cómo cambia el background-color del elemento <fieldset> en función de si el modo oscuro está habilitado, de acuerdo con las reglas de la hoja de estilo intercalada proporcionada por el desarrollador en la página. Es gainsboro o darkslategray.

Una página en modo claro.
Modo claro: Son los estilos que especifican el desarrollador y el usuario-agente. El texto es negro y el fondo es blanco, según la hoja de estilo del usuario-agente. El background-color del elemento <fieldset> es gainsboro, según la hoja de estilo del desarrollador intercalada.
Una página en modo oscuro.
Modo oscuro: Estilos especificados por el desarrollador y el usuario-agente. El texto es blanco y el fondo es negro, según la hoja de estilo del usuario-agente. El background-color del elemento <fieldset> es darkslategray, según la hoja de estilo del desarrollador intercalada.

La hoja de estilo del usuario-agente controla el aspecto del elemento <button>. Su color está configurado con el color de sistema ButtonText, y su background-color y los cuatro border-color tienen el color del sistema ButtonFace.

Una página de modo claro que usa la propiedad ButtonFace
Modo claro: Los elementos background-color y los diferentes border-color están configurados con el color de sistema ButtonFace.

Ahora, observa cómo cambia el border-color del elemento <button>. El valor calculado para border-top-color y border-bottom-color cambia de rgba(0, 0, 0, 0.847) (negro) a rgba(255, 255, 255, 0.847) (blanco), ya que el usuario-agente actualiza ButtonFace de forma dinámica según el esquema de colores. Lo mismo se aplica al color del elemento <button> configurado con el color del sistema correspondiente ButtonText.

Se muestra que los valores de color calculados coinciden con ButtonFace.
Modo claro: Los valores calculados de border-top-color y border-bottom-color que están configurados en ButtonFace en la hoja de estilo del usuario-agente ahora son rgba(0, 0, 0, 0.847).
Se muestra que los valores de color calculados aún coinciden con ButtonFace en el modo oscuro.
Modo oscuro: Los valores calculados de border-top-color y border-bottom-color que están configurados en ButtonFace en la hoja de estilo del usuario-agente ahora son rgba(255, 255, 255, 0.847).

Demostración

Puedes ver los efectos de color-scheme aplicados a una gran cantidad de elementos HTML en una demostración de Glitch. En la demostración, se muestra deliberadamente el incumplimiento de las WCAG AA y las WCAG AAA con los colores de los vínculos que se mencionaron en la advertencia anterior.

Demostración en el modo claro.
Se activó la demostración en color-scheme: light.
Demostración en modo oscuro.
La demostración se activó como color-scheme: dark. Observa el incumplimiento de las WCAG AA y las WCAG AAA con los colores del vínculo.

Agradecimientos

Rune Lillesveen implementó la propiedad color-scheme de CSS y la metaetiqueta correspondiente. Rune también es coeditor de la especificación de nivel 1 del módulo de ajuste de color de CSS. Imagen hero de Philippe Leone en Unsplash.