prefers-color-scheme: Hola, oscuridad, mi viejo amigo

¿Por necesidad o sobrepasado? Aprende todo sobre el modo oscuro y cómo brindar asistencia para el beneficio de tus usuarios.

Introducción

El modo oscuro antes del modo oscuro

Monitor de computadora de pantalla verde
Pantalla verde (fuente)

Ya completamos el modo oscuro. En los comienzos de la computación personal, el modo oscuro no era una elección, sino una cuestión de hecho: los monitores de computadora CRT monocromáticos trabajaban con la activación de haces de electrones en una pantalla fosforescente, y el fósforo utilizado en las primeras CRT era verde. Debido a que el texto se mostraba en verde y el resto de la pantalla era negro, estos modelos a menudo se denominaban pantallas verdes.

Procesamiento de texto en blanco y oscuro
Oscuro sobre blanco (Fuente)

Las CRT de color que se introdujeron posteriormente mostraban varios colores mediante el uso de fósforos rojos, verdes y azules. Crearon el blanco activando los tres fósforos simultáneamente. Con la llegada de la publicación de escritorio WYSIWYG más sofisticada, la idea de hacer que el documento virtual se asemeje a una hoja de papel física se hizo popular.

Página web en blanco y oscuro en el navegador WorldWide
El navegador WorldWideWeb (fuente)

Aquí es donde comenzó el color oscuro sobre blanco como tendencia de diseño, y esta tendencia se trasladó a la versión web temprana basada en documentos. El primer navegador, WorldWideWeb (recuerda que Aún no se inventó CSS), mostró páginas web de esta manera. Dato curioso: El segundo navegador, el Navegador de modo de línea, un navegador basado en la terminal, era verde sobre oscuro. Hoy en día, las páginas y apps web suelen diseñarse con texto oscuro sobre un fondo claro, una suposición de referencia que también está codificada en las hojas de estilo del usuario-agente, incluida la de Chrome.

Smartphone usado mientras se está acostado
Se usó un smartphone en la cama (fuente: Unsplash)

Los días de las CRT se terminaron. El consumo y la creación de contenido cambiaron a los dispositivos móviles que usan pantallas LCD retroiluminadas o pantallas AMOLED de ahorro de energía. Las computadoras, las tabletas y los smartphones más pequeños y transportables dieron lugar a nuevos patrones de uso. Las tareas recreativas, como la navegación web, la programación por diversión y los videojuegos de alta gama, suelen realizarse después del horario de atención en entornos con poca luz. Las personas incluso disfrutan de sus dispositivos en sus camas durante la noche. Cuantas más personas usen sus dispositivos en la oscuridad, más popular se volverá la idea de volver a las raíces de lo claro sobre la oscuridad.

Por qué el modo oscuro

El modo oscuro por motivos estéticos

Cuando se pregunta a las personas por qué les gusta o quieren el modo oscuro, la respuesta más popular es que “es más fácil para la vista” seguida de “es elegante y hermoso”. En su documentación para desarrolladores sobre el modo oscuro, Apple escribe explícitamente lo siguiente: “La elección de habilitar una apariencia clara u oscura es una estética para la mayoría de los usuarios y podría no relacionarse con las condiciones de iluminación ambiental”.

Cerrar la vista en el sistema Mac OS 7 con
System 7 CloseView (fuente)

El modo oscuro como herramienta de accesibilidad

También hay personas que necesitan el modo oscuro y lo usan como otra herramienta de accesibilidad, por ejemplo, usuarios con baja visión. La primera instancia de esta herramienta de accesibilidad que pude encontrar fue la función CloseView de System 7, que tenía un botón de activación para Black on White y White on Black. Si bien System 7 admitía colores, la interfaz de usuario predeterminada seguía en blanco y negro.

Estas implementaciones basadas en inversión demostraron sus debilidades una vez que se introdujo el color. La investigación sobre usuarios de Szpiro y otros sobre cómo las personas con problemas de visión acceden a dispositivos informáticos demostró que a todos los usuarios entrevistados no les gustaban las imágenes invertidas, pero muchos preferían el texto claro sobre un fondo oscuro. Apple se adapta a esta preferencia del usuario con una función llamada Smart Invert, que invierte los colores en la pantalla, excepto las imágenes, el contenido multimedia y algunas apps que usan estilos de colores oscuros.

Una forma especial de visión reducida es el síndrome de visión artificial, también conocido como el desgaste del ojo digital, que se define como “la combinación de problemas oculares y de visión asociados con el uso de computadoras (incluidas computadoras de escritorio, laptops y tablets) y otras pantallas electrónicas (p.ej., smartphones y dispositivos de lectura electrónica”). Se propuso que el uso de dispositivos electrónicos por parte de los adolescentes, especialmente durante la noche, aumentará el riesgo de que el sueño tenga una duración más corta, una mayor latencia de inicio del sueño y un aumento de la deficiencia del sueño. Además, se informa que la exposición a la luz azul está involucrada en la regulación del ritmo circadiano y el ciclo de sueño, y los ambientes de luz irregular pueden provocar la privación del sueño, lo que puede afectar el estado de ánimo y el rendimiento de las tareas, según una investigación de Rosenfield. Para limitar estos efectos negativos, puedes reducir la luz azul ajustando la temperatura de color de la pantalla con funciones como Cambio nocturno de iOS o Luz nocturna de Android, además de evitar luces brillantes o irregulares en general a través de temas oscuros o modos oscuros.

Ahorro de energía con modo oscuro en pantallas AMOLED

Por último, se sabe que el modo oscuro ahorra muchísima energía en las pantallas AMOLED. Los casos de éxito de Android que se enfocaron en apps populares de Google, como YouTube, demostraron que el ahorro de energía puede ser de hasta un 60%. El siguiente video tiene más detalles sobre estos casos de éxito y el ahorro de energía por app.

Activa el modo oscuro en el sistema operativo

Ahora que analizamos por qué el modo oscuro es tan importante para muchos usuarios, revisemos cómo puedes admitirlo.

Configuración del modo oscuro de Android Q
Configuración del tema oscuro de Android Q

Los sistemas operativos que admiten un modo o un tema oscuros suelen tener la opción de activarlo en algún lugar de la configuración. En macOS X, se encuentra en la sección General de las preferencias del sistema y se llama Appearance (captura de pantalla). En Windows 10, está en la sección Colors y se llama Choose your color (captura de pantalla). En Android Q, puedes encontrarlo en Display como un interruptor de activación de Tema oscuro (captura de pantalla). En iOS 13, puedes cambiar la Appearance en la sección Display & Brightness de la configuración (captura de pantalla).

La consulta de medios prefers-color-scheme

Quiero comenzar la teoría antes de empezar. Las consultas de medios permiten que los autores prueben y consulten valores o funciones del usuario-agente o del dispositivo de visualización, independientemente del documento que se renderice. Se usan en la regla @media de CSS para aplicar diseños condicionalmente a un documento y en varios otros contextos y lenguajes, como HTML y JavaScript. El nivel de consultas de medios 5 presenta las denominadas funciones multimedia de preferencias del usuario, es decir, una forma en que los sitios detectan la forma que prefiere el usuario de mostrar contenido.

La función multimedia prefers-color-scheme se usa para detectar si el usuario solicitó que la página use un tema de color oscuro o claro. Funciona con los siguientes valores:

  • light: Indica que el usuario notificó al sistema que prefiere una página con un tema claro (texto oscuro sobre fondo claro).
  • dark: Indica que el usuario notificó al sistema que prefiere una página con un tema oscuro (texto claro sobre fondo oscuro).

Compatibilidad con el modo oscuro

Cómo comprobar si el navegador admite el modo oscuro

Dado que el modo oscuro se informa a través de una consulta de medios, puedes verificar fácilmente si el navegador actual admite el modo oscuro. Para ello, verifica si el prefers-color-scheme de la consulta de medios coincide en absoluto. Observa que no incluyo ningún valor, pero verifica si solo coincide la consulta de medios.

if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('🎉 Dark mode is supported');
}

Al momento de la redacción, prefers-color-scheme es compatible con computadoras de escritorio y dispositivos móviles (cuando estén disponibles) con Chrome y Edge a partir de la versión 76, Firefox a partir de la versión 67, y Safari a partir de la versión 12.1 en macOS y a partir de la versión 13 en iOS. Para todos los demás navegadores, puedes consultar las ¿Puedo usar tablas de asistencia?

Obtener información sobre las preferencias del usuario en el momento de la solicitud

El encabezado de la sugerencia del cliente Sec-CH-Prefers-Color-Scheme permite que los sitios obtengan las preferencias de esquema de colores del usuario de forma opcional en el momento de la solicitud, lo que permite a los servidores intercalar el CSS correcto y, por lo tanto, evitar un destello de tema de color incorrecto.

El modo oscuro en la práctica

Por fin, veamos cómo se ve la compatibilidad con el modo oscuro en la práctica. Al igual que con Highlander, con el modo oscuro solo puede haber uno: oscuro o claro, pero nunca ambos. ¿Por qué menciono esto? Porque esto debería tener un impacto en la estrategia de carga No obligues a los usuarios a descargar CSS en la ruta de renderización crítica para un modo que no usan actualmente. Por lo tanto, con el objetivo de optimizar la velocidad de carga, dividí el CSS de la app de ejemplo que muestra las siguientes recomendaciones en la práctica en tres partes para diferir las CSS no críticas:

  • style.css que contiene reglas genéricas que se usan universalmente en el sitio.
  • dark.css que contiene solo las reglas necesarias para el modo oscuro.
  • light.css que contiene solo las reglas necesarias para el modo claro.

Estrategia de carga

Los dos últimos, light.css y dark.css, se cargan de forma condicional con una consulta <link media>. Inicialmente, no todos los navegadores admitirán prefers-color-scheme (detectable con el patrón anterior), con el que me encargaré de forma dinámica cargando el archivo light.css predeterminado a través de un elemento <link rel="stylesheet"> insertado de forma condicional en una secuencia de comandos intercalada minúscula (la luz es una opción arbitraria, también podría haber oscurecido la experiencia de resguardo predeterminada). Para evitar un flash de contenido sin estilo, oculto el contenido de la página hasta que se cargue light.css.

<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
      'beforeend',
      '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
  rel="stylesheet"
  href="/light.css"
  media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />

Arquitectura de la hoja de estilo

Uso al máximo las variables de CSS, lo que permite que mi style.css genérica sea, bueno, genérica, y toda la personalización del modo oscuro o claro ocurre en los otros dos archivos dark.css y light.css. A continuación, puedes ver un extracto de los estilos reales, pero debería ser suficiente para transmitir la idea general. Declaro dos variables, -⁠-⁠color y -⁠-⁠background-color, que, en esencia, crean un tema de referencia oscuro con la luz y un tema de referencia claro sobre la oscuridad.

/* light.css: 👉 dark-on-light */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

En mi style.css, uso estas variables en la regla body { … }. Como se definen en la seudoclase de CSS :root, un selector que en HTML representa el elemento <html> y es idéntico al selector html, con la excepción de que su especificidad es mayor, se transmiten en cascada, lo que me sirve para declarar variables de CSS globales.

/* style.css */
:root {
  color-scheme: light dark;
}

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

En la muestra de código anterior, es probable que hayas notado una propiedad color-scheme con el valor light dark separado por espacios.

Esto le indica al navegador qué temas de color admite mi app y le permite activar variantes especiales de la hoja de estilo del usuario-agente, lo que es útil, por ejemplo, para permitir que el navegador renderice campos de formulario con un fondo oscuro y texto claro, ajustar las barras de desplazamiento o habilitar un color de resaltado que reconozca el tema. Los detalles exactos de color-scheme se especifican en el nivel 1 del módulo de ajuste de color de CSS.

Todo lo demás es solo cuestión de definir variables de CSS para los aspectos importantes de mi sitio. La organización semántica de los estilos es muy útil cuando se trabaja con el modo oscuro. Por ejemplo, en lugar de -⁠-⁠highlight-yellow, considera llamar a la variable -⁠-⁠accent-color, ya que "amarillo" puede no ser amarillo en modo oscuro o viceversa. A continuación, se muestra un ejemplo de algunas variables más que uso en mi ejemplo.

/* dark.css */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
  --link-color: rgb(0, 188, 212);
  --main-headline-color: rgb(233, 30, 99);
  --accent-background-color: rgb(0, 188, 212);
  --accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
  --link-color: rgb(0, 0, 238);
  --main-headline-color: rgb(0, 0, 192);
  --accent-background-color: rgb(0, 0, 238);
  --accent-color: rgb(250, 250, 250);
}

Ejemplo completo

En la siguiente incorporación de Glitch, puedes ver el ejemplo completo que pone en práctica los conceptos anteriores. Intenta activar o desactivar el modo oscuro en la configuración de tu sistema operativo particular y observa cómo reacciona la página.

Cargando impacto

Cuando juegas con este ejemplo, puedes ver por qué carga mi dark.css y light.css a través de consultas de medios. Intenta activar o desactivar el modo oscuro y vuelve a cargar la página: las hojas de estilo particulares que actualmente no coinciden están cargadas, pero con la prioridad más baja, para que nunca compitan con los recursos que el sitio necesita en este momento.

Diagrama de carga de red que muestra cómo en el modo claro se carga el CSS en modo oscuro con la prioridad más baja
El sitio en modo claro carga el CSS en modo oscuro con la prioridad más baja.
Diagrama de carga de red que muestra cómo en el modo oscuro el CSS en modo claro se carga con la prioridad más baja
El sitio en modo oscuro carga el CSS en modo claro con la prioridad más baja.
Diagrama de carga de la red que muestra cómo, en el modo claro predeterminado, el CSS en modo oscuro se carga con la prioridad más baja
El sitio en modo claro predeterminado en un navegador que no admite prefers-color-scheme carga el CSS en modo oscuro con la prioridad más baja.

Cómo reaccionar ante los cambios en el modo oscuro

Como ocurre con cualquier otro cambio en las consultas de medios, se puede realizar una suscripción a los cambios del modo oscuro a través de JavaScript. Puedes usarlo para, por ejemplo, cambiar de forma dinámica el ícono de página de una página o el <meta name="theme-color"> que determina el color de la barra de URL en Chrome. En el ejemplo completo anterior, se muestra esto en acción. Para ver los cambios en el color del tema y el ícono de página, abre la demostración en una pestaña separada.

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
  const darkModeOn = e.matches;
  console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});

A partir de Chromium 93 y Safari 15, puedes ajustar el color en función de una consulta de contenido multimedia con el atributo media del elemento de color del tema meta. Se elegirá la primera que coincida. Por ejemplo, puedes tener un color para el modo claro y otro para el modo oscuro. Al momento de escribir, no puedes definir esos elementos en tu manifiesto. Consulta el problema de GitHub w3c/manifest#975.

<meta
  name="theme-color"
  media="(prefers-color-scheme: light)"
  content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

Cómo depurar y probar el modo oscuro

Emular prefers-color-scheme en Herramientas para desarrolladores

Cambiar el esquema de colores de todo el sistema operativo puede ser muy molesto, por lo que las Herramientas para desarrolladores de Chrome ahora te permiten emular el esquema de colores preferido del usuario de una manera que solo afecte a la pestaña que está visible en ese momento. Abre el Menú de comandos, comienza a escribir Rendering, ejecuta el comando Show Rendering y, luego, cambia la opción Emular CSS media feature prefers-color-scheme.

Captura de pantalla de la opción &quot;Emulate CSS media feature prefers-color-scheme&quot; que se encuentra en la pestaña Renderización de las Herramientas para desarrolladores de Chrome

Captura de pantalla de prefers-color-scheme con Puppeteer

Puppeteer es una biblioteca de Node.js que proporciona una API de alto nivel para controlar Chrome o Chromium a través del protocolo de Herramientas para desarrolladores. Con dark-mode-screenshot, proporcionamos una secuencia de comandos de Puppeteer que te permite crear capturas de pantalla de tus páginas en modo oscuro y claro. Puedes ejecutar esta secuencia de comandos por única vez o, de manera alternativa, incluirla en el paquete de pruebas de integración continua (CI).

npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750

Prácticas recomendadas para el modo oscuro

Evita el blanco puro

Un pequeño detalle que tal vez notaste es que no uso blanco puro. En cambio, para evitar el resplandor y el sangrado contra el contenido oscuro que lo rodea, elijo un blanco ligeramente más oscuro. Uno como rgb(250, 250, 250) funciona bien.

Volver a colorear y oscurecer imágenes fotográficas

Si comparas las dos capturas de pantalla que aparecen a continuación, notarás que no solo el tema principal cambió de oscuro con luz a claro sobre oscuro, sino que también la imagen principal se ve ligeramente diferente. Mi investigación sobre usuarios demostró que la mayoría de los usuarios encuestados prefieren imágenes un poco menos vibrantes y brillantes cuando el modo oscuro está activo. Esto se conoce como recolorización.

Hero image ligeramente oscurecida en modo oscuro.
Imagen hero ligeramente oscurecida en modo oscuro.
Imagen principal normal en modo claro.
Imagen hero normal en modo claro.

La recoloración puede lograrse a través de un filtro CSS en mis imágenes. Uso un selector CSS que coincide con todas las imágenes que no tienen .svg en su URL. La idea es que puedo darles a los gráficos vectoriales (íconos) un tratamiento de recoloración diferente al de mis imágenes (fotos). Obtén más información sobre esto en el próximo párrafo. Observa que utilizo de nuevo una variable de CSS para poder cambiar el filtro más adelante de manera flexible.

Como la recoloración solo es necesaria en el modo oscuro, es decir, cuando dark.css está activo, no hay reglas correspondientes en light.css.

/* dark.css */
--image-filter: grayscale(50%);

img:not([src*='.svg']) {
  filter: var(--image-filter);
}

Personaliza las intensidades de recoloración del modo oscuro con JavaScript

No todos son iguales, y cada persona tiene necesidades diferentes en cuanto al modo oscuro. Si cedo el método de recoloración descrito anteriormente, puedo hacer que la intensidad de la escala de grises sea una preferencia del usuario que puedo cambiar a través de JavaScript y, si estableces un valor de 0%, también puedo inhabilitar la recoloración por completo. Ten en cuenta que document.documentElement proporciona una referencia al elemento raíz del documento, es decir, el mismo elemento al que puedo hacer referencia con la pseudoclase de CSS :root.

const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);

Invertir gráficos e íconos vectoriales

En el caso de los gráficos vectoriales, que en mi caso se usan como íconos a los que hago referencia mediante elementos <img>, utilizo un método de recoloración diferente. Si bien la investigación demostró que a las personas no les gusta la inversión de las fotos, funciona muy bien para la mayoría de los íconos. Nuevamente, utilizo variables de CSS para determinar el importe de la inversión en el estado normal y en el estado :hover.

Los íconos se invierten en modo oscuro.
Los íconos se invierten en modo oscuro.
Íconos regulares en modo claro.
Íconos regulares en modo claro.

Observa que, una vez más, solo invierto los íconos en dark.css, pero no en light.css, y cómo :hover obtiene una intensidad de inversión diferente en los dos casos para que el ícono se vea un poco más oscuro o un poco más brillante, según el modo que haya seleccionado el usuario.

/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);

img[src*='.svg'] {
  filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
  filter: var(--icon-filter_hover);
}

Usa currentColor para SVG intercalados

Para las imágenes SVG intercaladas, en lugar de usar filtros de inversión, puedes aprovechar la palabra clave de CSS currentColor que representa el valor de la propiedad color de un elemento. Esto te permite usar el valor color en propiedades que no lo reciben de forma predeterminada. Convenientemente, si currentColor se usa como el valor de los atributos fill o stroke de SVG, este toma su valor del valor heredado de la propiedad de color. Mejor aún, esto también funciona para <svg><use href="…"></svg>, por lo que puedes tener recursos separados, y currentColor se seguirá aplicando en contexto. Ten en cuenta que esto solo funciona para los SVG intercalados o <use href="…">, pero no para los SVG a los que se hace referencia como src de una imagen o de alguna manera a través de CSS. Puedes ver esto aplicado en la siguiente demostración.

<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
    stroke="currentColor"
>
  […]
</svg>

Transiciones fluidas entre modos

El cambio del modo oscuro al modo claro o viceversa se puede suavizar, ya que tanto color como background-color son propiedades de CSS animadas. Crear la animación es tan fácil como declarar dos transition para las dos propiedades. En el siguiente ejemplo, se muestra la idea general. Puedes experimentarla en vivo en la demostración.

body {
  --duration: 0.5s;
  --timing: ease;

  color: var(--color);
  background-color: var(--background-color);

  transition: color var(--duration) var(--timing), background-color var(
        --duration
      ) var(--timing);
}

Dirección artística con el modo oscuro

Si bien por motivos de carga de rendimiento en general, te recomendamos trabajar de forma exclusiva con prefers-color-scheme en el atributo media de los elementos <link> (en lugar de hacerlo intercalado en las hojas de estilo), hay situaciones en las que es posible que quieras trabajar con prefers-color-scheme directamente intercalado en tu código HTML. La dirección artística es una situación así. En la Web, la dirección de arte se ocupa de la apariencia visual general de una página y de cómo se comunica visualmente, estimula los estados de ánimo, contrasta las características y atrae psicológicamente a un público objetivo.

Con el modo oscuro, depende del juicio del diseñador decidir cuál es la mejor imagen en un modo en particular y si la recoloración de imágenes no es lo suficientemente buena. Si se usa con el elemento <picture>, el <source> de la imagen que se mostrará puede depender del atributo media. En el siguiente ejemplo, se muestra el hemisferio occidental para el modo oscuro y el hemisferio oriental para el modo claro, o bien cuando no hay preferencia, y se establece de forma predeterminada el hemisferio oriental en todos los demás casos. Por supuesto, esto se usa exclusivamente con fines ilustrativos. Activa el modo oscuro en tu dispositivo para ver la diferencia.

<picture>
  <source srcset="western.webp" media="(prefers-color-scheme: dark)" />
  <source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
  <img src="eastern.webp" />
</picture>

Modo oscuro, pero agregar una inhabilitación

Como se mencionó anteriormente en la sección Por qué el modo oscuro, el modo oscuro es una opción estética para la mayoría de los usuarios. Como consecuencia, es posible que algunos usuarios deseen tener la IU del sistema operativo en la oscuridad, pero igualmente prefieran ver sus páginas web como están acostumbradas a verlas. Un excelente patrón consiste en cumplir inicialmente con el indicador que envía el navegador a través de prefers-color-scheme, pero luego, opcionalmente, permitir que los usuarios anulen su configuración a nivel del sistema.

El elemento personalizado <dark-mode-toggle>

Puedes crear el código para esto por tu cuenta, pero también puedes usar un elemento personalizado listo para usar (componente web) que creé para este propósito. Se llama <dark-mode-toggle> y agrega un botón de activación (modo oscuro: activado/desactivado) o un selector de temas (tema: claro/oscuro) a tu página que puedes personalizar por completo. En la siguiente demostración, se muestra el elemento en acción (Ah, y también 🤫 lo recogí en silencio en todos los otros ejemplos arriba).

<dark-mode-toggle
  legend="Theme Switcher"
  appearance="switch"
  dark="Dark"
  light="Light"
  remember="Remember this"
></dark-mode-toggle>
botón de activación del modo oscuro en el modo claro.
<dark-mode-toggle> en modo claro.
botón de activación del modo oscuro en el modo claro.
<dark-mode-toggle> en modo oscuro.

Prueba hacer clic o presionar los controles de modo oscuro en la esquina superior derecha en la siguiente demostración. Si marcas la casilla de verificación en el tercer y el cuarto control, observa cómo se recuerda la selección del modo incluso cuando vuelves a cargar la página. Esto permite que los visitantes mantengan su sistema operativo en modo oscuro, pero que disfruten de tu sitio en modo claro o viceversa.

Conclusiones

Trabajar con el modo oscuro y admitirlo es divertido y abre nuevos caminos de diseño. Para algunos de sus visitantes, puede ser la diferencia entre no poder manejar su sitio y ser un usuario feliz. Existen algunos errores y debes realizar pruebas cuidadosas, pero el modo oscuro es, sin dudas, una gran oportunidad para demostrar que te importan todos los usuarios. Las prácticas recomendadas mencionadas en esta publicación y los asistentes como el elemento personalizado <dark-mode-toggle> deberían darte confianza en tu capacidad para crear una increíble experiencia de modo oscuro. Cuéntanos en Twitter qué creaste y si esta publicación te resultó útil, o bien obtén sugerencias para mejorarla. ¡Gracias por leer esta información! 🌒

Recursos para la consulta de medios prefers-color-scheme:

Recursos para la metaetiqueta color-scheme y la propiedad CSS:

Vínculos del modo oscuro general:

Artículos de investigación de fondo para esta publicación:

Agradecimientos

La función de medios prefers-color-scheme, la propiedad de CSS color-scheme y la metaetiqueta relacionada son el trabajo de implementación de 👏 Rune Lillesveen. Rune también es coeditor de la especificación del nivel 1 del módulo de ajuste de color de CSS. 🙏 Agradezco 🙏 a Lukasz Zbylut, Rowan Merewood, Chirag Desai y Rob Dodson por sus revisiones exhaustivas de este artículo. La estrategia de carga es idea de Jake Archibald. Emilio Cobos Álvarez me indicó el método de detección prefers-color-scheme correcto. La sugerencia con los SVG y currentColor a los que se hace referencia provino de Timothy Hatcher. Por último, agradezco a los participantes anónimos de los diversos estudios de usuarios que ayudaron a dar forma a las recomendaciones de este artículo. Hero image de Nathan Anderson.