Addaw, ir a inicio Donar

Técnica CSS WCAG 2.2

C39Respetar la preferencia de movimiento reducido con CSS

Nombre oficial en el W3C: Usar la consulta de medios prefers-reduced-motion de CSS para evitar el movimiento

En pocas palabras

Los sistemas operativos tienen una opción para reducir el movimiento en pantalla. La consulta CSS prefers-reduced-motion permite saber si la persona la ha activado. En ese caso, la web quita o suaviza las animaciones que aparecen al pulsar, desplazarse o pasar el ratón.

Por qué es importante

A algunas personas el movimiento en pantalla les provoca mareo, náuseas o dolor de cabeza. Les pasa, por ejemplo, a quienes tienen trastornos vestibulares (problemas del equilibrio en el oído interno).

A otras, como personas con déficit de atención, les distrae y les impide concentrarse. Un fondo que se mueve al desplazar o un panel que entra girando puede obligarlas a abandonar la página.

Cómo se hace

  1. Localice las animaciones que se activan al interactuar: paneles que se deslizan, efectos al desplazar, tarjetas que se inclinan, carruseles.
  2. Añada un bloque @media (prefers-reduced-motion: reduce) en el CSS.
  3. Dentro, quite los desplazamientos, giros y zooms. Puede dejar cambios suaves, como un fundido corto.
  4. Otra opción es al revés: estilos sin movimiento por defecto y animaciones solo dentro de @media (prefers-reduced-motion: no-preference).
  5. En animaciones hechas con JavaScript, consulte la misma preferencia con matchMedia.

Ejemplo práctico

Muchas tiendas online usan paneles que entran deslizándose, tarjetas que rebotan o fondos que se mueven al desplazar. Con prefers-reduced-motion, la web respeta el ajuste «reducir movimiento» del sistema (criterio 2.3.3 Animación desde interacciones).

Así no: Panel de ofertas que entra girando y rebotando

Al pulsar el botón, el panel entra desde la izquierda con giro y rebote durante 1,2 segundos. Ocurre aunque la persona haya activado en su sistema la opción de reducir el movimiento. La web no consulta esa preferencia.

Captura de pantalla del ejemplo incorrecto: Panel de ofertas que entra girando y rebotando
Así se ve el ejemplo incorrecto.

La demostración contiene, a propósito, el error de accesibilidad que se explica.

Ver el código del ejemplo incorrecto
<style>
  .panel { margin-top: 12px; padding: 4px 12px; background: #f3eef8; border-left: 4px solid #744E9A; opacity: 0; visibility: hidden; transform: translateX(-120%) rotate(-8deg); transition: transform 1.2s cubic-bezier(.5, 1.8, .5, 1), opacity 1.2s, visibility 1.2s; }
  .panel.abierto { opacity: 1; visibility: visible; transform: none; }
</style>
<button type="button" id="btn-ofertas" aria-expanded="false" aria-controls="ofertas">Ver ofertas de la semana</button>
<div class="panel" id="ofertas">
  <p>Aceite de oliva virgen extra, 5 l: 29,90 €</p>
  <p>Queso manchego curado, 1 kg: 14,50 €</p>
</div>
<script>
  const boton = document.getElementById('btn-ofertas');
  const panel = document.getElementById('ofertas');
  boton.addEventListener('click', () => {
    const abierto = panel.classList.toggle('abierto');
    boton.setAttribute('aria-expanded', abierto);
  });
</script>

Así sí: Sin desplazamiento cuando se pide movimiento reducido

Se añade la consulta @media (prefers-reduced-motion: reduce). Elimina el desplazamiento y el giro, y deja solo un fundido breve. Para ver la diferencia, active «Reducir movimiento» en el sistema o emúlelo en las herramientas del navegador (panel Rendering).

Pruébelo aquí:

Ver el código del ejemplo correcto
<style>
  .panel { margin-top: 12px; padding: 4px 12px; background: #f3eef8; border-left: 4px solid #744E9A; opacity: 0; visibility: hidden; transform: translateX(-120%) rotate(-8deg); transition: transform 1.2s cubic-bezier(.5, 1.8, .5, 1), opacity 1.2s, visibility 1.2s; }
  .panel.abierto { opacity: 1; visibility: visible; transform: none; }
  @media (prefers-reduced-motion: reduce) {
    .panel { transform: none; transition: opacity .2s, visibility .2s; }
  }
</style>
<button type="button" id="btn-ofertas" aria-expanded="false" aria-controls="ofertas">Ver ofertas de la semana</button>
<div class="panel" id="ofertas">
  <p>Aceite de oliva virgen extra, 5 l: 29,90 €</p>
  <p>Queso manchego curado, 1 kg: 14,50 €</p>
</div>
<script>
  const boton = document.getElementById('btn-ofertas');
  const panel = document.getElementById('ofertas');
  boton.addEventListener('click', () => {
    const abierto = panel.classList.toggle('abierto');
    boton.setAttribute('aria-expanded', abierto);
  });
</script>

Cómo comprobarlo

Ajuste del sistema

  1. Active el movimiento reducido. En Windows: Configuración > Accesibilidad > Efectos visuales > Efectos de animación (desactivado). En macOS: Ajustes del Sistema > Accesibilidad > Pantalla > Reducir movimiento. En iOS y Android, busque la opción equivalente en los ajustes de accesibilidad.
  2. Recargue la página y active cada elemento que provoca movimiento: botones, menús, carruseles y efectos al desplazar.
  3. Compruebe que la animación desaparece o se cambia por otra sin desplazamiento. Solo puede quedar el movimiento que sea imprescindible.

Herramientas del navegador

  1. En Chrome o Edge, abra las herramientas de desarrollo (F12). Vaya al menú de los tres puntos > More tools > Rendering.
  2. En «Emulate CSS media feature prefers-reduced-motion», elija «reduce» y repita las interacciones.
  3. En la pestaña Estilos, compruebe que se aplican las reglas de @media (prefers-reduced-motion: reduce) al elemento animado.
  4. Revise también las animaciones hechas con JavaScript. Deben consultar matchMedia('(prefers-reduced-motion: reduce)').

Lector de pantalla (NVDA o VoiceOver)

  1. Llegue al botón con Tab y actívelo con Intro o Espacio.
  2. Compruebe que se anuncia el cambio de estado del botón. La animación no afecta al lector de pantalla, pero el estado debe comunicarse bien.

Debería anunciar: «Ver ofertas de la semana, botón, contraído» y, tras activarlo, «expandido»

Validación automática

  1. axe DevTools, WAVE y Lighthouse no comprueban si las animaciones respetan prefers-reduced-motion. La revisión es manual.
  2. Para saber qué animaciones revisar, busque en el CSS @keyframes, transition y transform.

Errores frecuentes en auditorías

  • Añadir la consulta para las animaciones CSS, pero no para las de JavaScript (efectos de aparición al desplazar, parallax, GSAP). Estas siguen moviéndose.
  • Poner animation: none en la consulta y dejar el elemento en su estado inicial invisible. El contenido desaparece.
  • Aplicar la consulta solo a algunos componentes. Se olvidan efectos al pasar el ratón o al desplazar, como tarjetas que se inclinan o fondos que se mueven.
  • Dejar carruseles que se deslizan aunque se pida movimiento reducido. Deberían cambiar a un fundido o a un cambio directo.
Ver el texto completo del W3C (traducción al español)

Esta es una traducción no oficial al español de la técnica C39 de Techniques for WCAG 2.2, del W3C. Puede contener errores. El único documento oficial y normativo es la versión original en inglés, publicada en el sitio web del W3C.

Aplicabilidad

CSS que provoca movimiento desencadenado por las interacciones del usuario.

Descripción

El objetivo de esta técnica es permitir que los usuarios eviten que se muestren animaciones (incluidas las animaciones con movimiento) en las páginas web, mediante el uso de la consulta de medios (media query) prefers-reduced-motion de CSS.

Algunos usuarios sufren distracción o náuseas con el contenido animado. Por ejemplo, si al desplazar una página los elementos se mueven (más allá del movimiento esencial asociado al desplazamiento del contenido, que está bajo el control del usuario), puede desencadenar trastornos vestibulares.

Las consultas de medios que activan o desactivan de forma selectiva las animaciones basadas en CSS según las preferencias del sistema operativo o del agente de usuario permiten a los usuarios evitar esos desencadenantes.

El documento de comprensión de Animaciones desde interacciones incluye enlaces para cambiar el ajuste de «movimiento reducido».

Ejemplos

Consulta de medios prefers-reduced-motion de CSS

Los usuarios pueden indicar en su sistema su preferencia de movimiento para las interfaces, y la consulta de medios prefers-reduced-motion de CSS respetará esa elección. A continuación puede aplicarse CSS para desactivar ese movimiento para los usuarios que así lo soliciten.

/* CSS for the motion effect */
@media (prefers-reduced-motion: reduce) {
  /* CSS to disable motion goes here */
}

Ejemplo práctico de la consulta de medios «prefers-reduced-motion» de CSS

Como alternativa, es posible seguir el planteamiento inverso: definir estilos estáticos y, después, incluir una consulta de medios que solo se aplique cuando el usuario no haya establecido la preferencia de movimiento reducido.

/* "Static" CSS styles */
@media (prefers-reduced-motion: no-preference) {
  /* CSS for the motion effect goes here */
}

Pruebas

Procedimiento

Para cada elemento interactivo que desencadena una animación con movimiento como resultado de una interacción del usuario:

  1. Activar el ajuste de movimiento reducido en el sistema;
  2. Comprobar que la animación con movimiento es esencial;
  3. Comprobar que la animación con movimiento se suprime.

Resultados esperados

  • La comprobación n.º 2 o la n.º 3 es verdadera.

Cómo lo comprobamos en ADDAW

En cada auditoría de ADDAW revisamos esta técnica página a página y le entregamos los errores con capturas y la forma de corregirlos.

Solicitar una auditoría

Basado en la técnica C39 del W3C (WCAG 2.2). Explicación y ejemplos: ADDAW. Traducción no oficial del texto del W3C © W3C, licencia de documentos del W3C. ¿Ha visto un error? Escríbanos.