Qué son y cómo usar las Preference Queries en CSS

Las Preference Queries son un tipo de media queries de CSS que nos permite obtener y detectar las preferencias de usuario del navegador de nuestro visitante.
Qué son y cómo usar las Preference Queries en CSS

Las Preferences Queries o consultas de preferencia son un tipo especial de media queries de CSS que nos permite obtener información del navegador del usuario que nos está visitando. Tanto por cuestiones de gusto (como es el asunto del tema claro/tema oscuro) o por cuestiones de accesibilidad (animaciones reducidas). En este artículo te voy a mostrar cómo usar las Preference Queries para personalizar más la experiencia del usuario en tu proyecto y cómo hacer más accesible su navegación.

Seguramente estarás cansado de ver sentencias que empiezan con @media en tus ficheros CSS. Y como bien sabrás, vienen a decir cómo tiene que mostrarse la página según el navegador del usuario, generalmente el tamaño de su viewport o pantalla. Pero, ¿sabías que hay más de 20 tipos de media-queries en el estándar de CSS? Te recomiento echarle un ojo a todas las posibles, aunque hoy me gustaría hablarte de dos preference queries: prefers-color-scheme y prefers-reduced-motion.

Cómo hacer un tema oscuro con CSS y prefers-color-scheme

Últimamente está muy de moda lo que llaman el "tema oscuro", que no es más que un juego de colores que tiende al negro, lo que (teóricamente) hace menos daño a nuestros ojos o nos beneficia a última hora de la tarde o noche, cuando consultamos nuestro móvil antes de dormir. Pues, ¿sabías que podemos hacer un tema oscuro para nuestro sitio web usando tan solo CSS?

Todo se basa en la instrucción prefers-color-scheme, que permite definir unas reglas CSS solo si el navegador del usuario está configurado en ese modo o esquema de color. Los posibles valores que devuelve es "dark" (es decir, el usuario prefiere el modo oscuro) o "light" (es decir, el usuario prefiere el tema claro):

@media (prefers-color-scheme: dark|light)

El código CSS básico para que nuestro proyecto tenga un tema claro y otro oscuro es el que se muestra a continuación. Te recomiendo conocer las Variables CSS o Custom Properties si no las conocías de antes.

:root {  
  --theme-background: white; 
  --theme-text: #222;
}
@media (prefers-color-scheme: dark) {
  :root {
    --theme-background: #222;
    --theme-text: white;
  }
}
body {
  background-color: var(--theme-background);
  color: var(--theme-text);
}

De esta forma, se establece según comienza el código CSS que la variable theme_background será blanca y el texto tiende a negro. Sin embargo, si el usuario tiene activada la opción de tema oscuro, estas variables serán sustituidas en el bloque @media. Así, y de forma automática, tu página se verá en modo claro o en modo oscuro según haya configurado el navegador.

Puedes configurar la herramienta devtools de tu navegador para probar los dos modos. Está muy bien explicado en esta página de Google

Cabe mencionar que también es posible detectar qué preferencia tiene el usuario configurada mediante Javascript. El código es, básicamente, un observador que se activa cada vez que cambia. El código para reconocer en Javascript qué prefers-color-scheme tiene el usuario es:

const themeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const updateTheme = (dark) => {  
  if (dark) {
    //tema oscuro activo
  } else {
    //tema claro activo
  }

updateTheme(themeMQ.matches);// Activar la primera vez que carga la página

//Y posteriormente... si cambia...
themeMediaQuery.addEventListener('change', () => {  
  updateTheme(themeMQ.matches);
});

Accesibilidad con prefers-reduced-motion

La mayoría de interfaces modernas tienen un montón de animaciones y efectos que, generalmente, a todos nos gustan porque le da dinamismo. Sin embargo, hay personas que puede no gustarles o incluso dificultarles la experiencia cuando visitan nuestro portal web. Por cuestiones de accesibilidad se ha creado la media query prefers-reduced-motion, que describe si un usuario ha solicitado la reducción de movimiento dentro de nuestra web.

El valor que devuelve prefers-reduced-motion puede ser no-preference o reduce:

  • no-preference si el usuario no tiene ninguna preferencia o no ha configurado su navegador (mayoría)
  • reduce si desea reducir las animaciones de nuestro sitio web (accesibilidad).

Para las animaciones que no aportan más valor que el méramente estético, se puede crear un código CSS que, en caso de que prefers-reduced-motion tenga un valor "reduce", no defina las animaciones.

@media (prefers-reduced-motion: no-preference) {  
  .agitar {
      animation: animationname 400ms ease-in-out;
  }
}
@media (prefers-reduced-motion: reduce) {
  .agitar {   
    /*Deshabilitar animation*/
  }
}

Igual que con prefers-color-scheme, Javascript también puede acceder al valor de estas instrucciones y controlar de forma dinámica las acciones de la página. El código en Javascript que detecta si el usuario quiere desactivar las animaciones es el que sigue:

const motionMediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
const updateMotion = (reduced) => {  
  if (reduced) {
    //movimiento reducido
  } else {
    //movimiento normal
  }

updateMotion(motionMediaQuery.matches);// Activar la primera vez que carga la página

//Y posteriormente... si cambia...
motionMediaQuery.addEventListener('change', () => {  
  updateTheme(motionMediaQuery.matches);
});

Conclusión

Ya conoces cómo funcionan las preferencias del usuario en CSS, también llamadas Preference Queries. Estas permiten conocer en CSS o en Javascript si el usuario prefiere un juego de colores oscuro o claro, así como saber si desea reducir la cantidad de animaciones por cuestiones de accesibilidad.

Así que ya no tienes excusa para no usar las Preference Queries en tu próximo proyecto y mejorar así la experiencia de usuario y la accesibilidad.

¡Qué tengas un feliz coding!