Cuando CSS no es suficiente: requisitos de JavaScript para componentes accesibles

Publicado: 2022-03-10
Resumen rápido ↬ Alerta de spoiler: información sobre herramientas, modales, pestañas, carruseles y menús desplegables son algunos de los componentes de la interfaz de usuario que requieren más que CSS. Para garantizar la accesibilidad de su interfaz, JavaScript es una adición necesaria para lograr la gestión del enfoque, responder a los eventos del teclado y alternar los atributos de ARIA.

Como autor de ModernCSS.dev, soy un gran defensor de las soluciones CSS. ¡Y me encanta ver las formas inteligentes en que las personas usan CSS para diseños e interactividad realmente listos para usar! Sin embargo, he notado una tendencia hacia la promoción de componentes "solo CSS" utilizando métodos como el "truco de casilla de verificación". Desafortunadamente, hacks como estos dejan a una cantidad significativa de usuarios sin poder usar su interfaz.

Este artículo cubre varios componentes comunes y por qué CSS no es suficiente para cubrir la accesibilidad al detallar los requisitos de JavaScript. Estos requisitos se basan en las Pautas de accesibilidad al contenido web (WCAG) y en investigaciones adicionales de expertos en accesibilidad. No prescribiré soluciones de JavaScript o CSS de demostración, sino que examinaré lo que se debe tener en cuenta al crear cada componente. Sin duda, se puede usar un marco de JavaScript, pero no es necesario para agregar los eventos y las características discutidas.

Los requisitos enumerados son, en general, no opcionales; son necesarios para ayudar a garantizar la accesibilidad de sus componentes.

Si usa un marco o una biblioteca de componentes, puede usar este artículo para ayudar a evaluar si los componentes provistos cumplen con los requisitos de accesibilidad . Es importante saber que muchos de los elementos anotados no serán completamente cubiertos por herramientas de prueba de accesibilidad automatizadas como aXe y, por lo tanto, necesitan algunas pruebas manuales. O bien, puede usar un marco de prueba como Cypress para crear pruebas para la funcionalidad requerida.

Tenga en cuenta que este artículo se centra en informarle sobre las consideraciones de JavaScript para cada componente de la interfaz. Este no es un recurso completo para todos los detalles de implementación para crear componentes totalmente accesibles, como el aria necesario o incluso el marcado. Se incluyen recursos para cada tipo para ayudarlo a aprender más sobre las consideraciones más amplias para cada componente.

¡Más después del salto! Continúe leyendo a continuación ↓

Determinar si solo CSS es una solución adecuada

Aquí hay algunas preguntas que debe hacer antes de continuar con una solución solo de CSS. Cubriremos algunos de los términos presentados aquí en más contexto junto con sus componentes relacionados.

  • ¿Es esto para su propio disfrute?
    ¡Entonces, apuesta por CSS, empuja los límites y aprende lo que el lenguaje puede hacer!
  • ¿La función incluye mostrar y ocultar contenido?
    Luego, necesita JS para, como mínimo, alternar aria y habilitar el cierre en Esc . Para ciertos tipos de componentes que también cambian de estado, es posible que también deba comunicar los cambios activando actualizaciones dentro de una región en vivo de ARIA.
  • ¿Es el orden de enfoque natural el más ideal?
    Si el orden natural pierde la relación entre un disparador y el elemento que activó, o si un usuario del teclado ni siquiera puede acceder al contenido a través del orden de tabulación natural, entonces necesita JS para ayudar en la gestión del enfoque.
  • ¿El control estilizado ofrece la información correcta sobre la funcionalidad?
    Los usuarios de tecnología de asistencia, como los lectores de pantalla, reciben información basada en la semántica y ARIA que les ayuda a determinar qué hace un control. Y los usuarios de reconocimiento de voz deben poder identificar la etiqueta o el tipo del componente para determinar la frase que se usará para operar los controles. Por ejemplo, si su componente tiene el estilo de pestañas pero usa botones de opción para "funcionar" como pestañas, un lector de pantalla puede escuchar "botón de opción" y un usuario de voz puede intentar usar la palabra "pestaña" para operarlos. En estos casos, necesitará JS para habilitar el uso de los controles y la semántica apropiados para lograr la funcionalidad deseada.
  • ¿El efecto se basa en el desplazamiento y/o el enfoque?
    Entonces, es posible que necesite JS para ayudar en una solución alternativa para proporcionar acceso equitativo o acceso persistente al contenido, especialmente para usuarios de pantalla táctil y aquellos que usan un zoom de escritorio de más del 200% o software de ampliación.

Sugerencia rápida : otra referencia al crear cualquier tipo de control personalizado es la Lista de verificación de desarrollo accesible de control personalizado de la guía W3 "Uso de ARIA". Esto menciona varios puntos anteriores, con algunas consideraciones adicionales de diseño y semánticas.

Información sobre herramientas

Limitar la definición de una información sobre herramientas es un poco complicado, pero para esta sección estamos hablando de pequeñas etiquetas de texto que aparecen al pasar el mouse cerca de un elemento desencadenante. Se superponen a otro contenido, no requieren interacción y desaparecen cuando un usuario quita el cursor o el foco.

Ejemplos de información sobre herramientas de GitHub, Whimsical y Notion
Información sobre herramientas de ejemplo de GitHub, Whimsical y Notion. (Vista previa grande)

La solución de solo CSS aquí puede parecer completamente correcta y se puede lograr con algo como:

 <button class="tooltip-trigger">I have a tooltip</button> <span class="tooltip">Tooltip</span> .tooltip { display: none; } .tooltip-trigger:hover + .tooltip, .tooltip-trigger:focus + .tooltip { display: block; }

Sin embargo, esto ignora una gran lista de problemas de accesibilidad y excluye a muchos usuarios del acceso al contenido de información sobre herramientas.

Un gran grupo de usuarios excluidos son aquellos que usan pantallas táctiles donde :hover posiblemente no se activará ya que en las pantallas táctiles, un evento :hover se activa en sincronización con un evento :focus . Esto significa que cualquier acción relacionada conectada con el elemento desencadenante, como un botón o un enlace, se activará junto con la información sobre herramientas que se revela. Esto significa que el usuario puede perder la información sobre herramientas o no tener tiempo para leer su contenido.

En el caso de que la información sobre herramientas se adjunte a un elemento interactivo sin eventos, la información sobre herramientas se puede mostrar pero no se puede descartar hasta que otro elemento obtenga el foco y, mientras tanto, puede bloquear el contenido y evitar que un usuario realice una tarea.

Además, los usuarios que necesitan usar un software de zoom o ampliación para navegar también experimentan una gran barrera para usar la información sobre herramientas. Dado que la información sobre herramientas se revela al pasar el mouse, si estos usuarios necesitan cambiar su campo de visión desplazando la pantalla para leer la información sobre herramientas, es posible que desaparezca. La información sobre herramientas también elimina el control del usuario, ya que a menudo no hay nada que le diga al usuario que aparecerá una información sobre herramientas antes de tiempo. La superposición de contenido puede impedirles realizar una tarea. En algunas circunstancias, como una información sobre herramientas vinculada a un campo de formulario, el dispositivo móvil u otros teclados en pantalla pueden ocultar el contenido de la información sobre herramientas. Y, si no están correctamente conectados al elemento de activación, es posible que algunos usuarios de tecnología de asistencia ni siquiera sepan que apareció una información sobre herramientas.

La orientación para el comportamiento de la información sobre herramientas proviene del Criterio de Conformidad 1.4.13 de las WCAG: Contenido al pasar el mouse o enfocar. Este criterio está destinado a ayudar a los usuarios con baja visión y a aquellos que utilizan software de zoom y ampliación. Los principios rectores de la información sobre herramientas (y otro contenido que aparece al pasar el mouse y enfocar) incluyen:

  • descartable
    La información sobre herramientas se puede descartar sin mover el cursor o el enfoque
  • Hoverable
    El contenido de información sobre herramientas revelado se puede desplazar sin que desaparezca
  • Persistente
    El contenido adicional no desaparece en función de un tiempo de espera, sino que espera a que un usuario elimine el cursor o el foco o lo descarte de otro modo.

Para cumplir completamente con estas pautas, se requiere cierta asistencia de JavaScript, en particular para permitir descartar el contenido.

  • Los usuarios de tecnología de asistencia supondrán que el comportamiento de desestimación está vinculado a la tecla Esc , que requiere un oyente de JavaScript.
  • De acuerdo con la investigación de Sarah Higley descrita en la siguiente sección, agregar un botón de "cerrar" visible dentro de la información sobre herramientas también requeriría JavaScript para manejar su evento de cierre.
  • Es posible que JavaScript necesite aumentar su solución de estilo para garantizar que un usuario pueda pasar el cursor sobre el contenido de información sobre herramientas sin que se descarte mientras el usuario mueve el mouse.

Alternativas a la información sobre herramientas

La información sobre herramientas debe ser el último recurso. Sarah Higley, una experta en accesibilidad que tiene una pasión particular por disuadir el uso de información sobre herramientas, ofrece esta prueba simple:

“¿Por qué estoy agregando este texto a la interfaz de usuario? ¿Adónde más podría ir?

— Sarah Higley de la presentación "Información sobre herramientas: investigación en cuatro partes"

Según la investigación en la que participó Sarah por su puesto en Microsoft, una solución alternativa es un "toggletip" dedicado. Esencialmente, esto significa proporcionar un elemento adicional para permitir que un usuario active intencionalmente la visualización y ocultación de contenido adicional . A diferencia de la información sobre herramientas, la información de alternancia puede retener la semántica de los elementos dentro del contenido revelado. También le devuelven al usuario el control de alternarlos y conservan la capacidad de detección y operabilidad por parte de más usuarios y, en particular, usuarios de pantalla táctil.

Si ha recordado que existe el atributo de title , sepa que sufre los mismos problemas que notamos en nuestra solución de solo CSS. En otras palabras, no use el title bajo el supuesto de que es una solución de información sobre herramientas aceptable.

Para obtener más información, consulte la presentación de Sarah en YouTube, así como su extenso artículo sobre información sobre herramientas. Para obtener más información sobre la información sobre herramientas frente a la información sobre alternancia y un poco más de información sobre por qué no usar title , consulte el artículo de Heydon Pickering de Inclusive Components: Tooltips and Toggletips.

modales

Los modales, también conocidos como cajas de luz o cuadros de diálogo, son ventanas en la página que aparecen después de una acción desencadenante. Se superponen a otro contenido de la página, pueden contener información estructurada que incluye acciones adicionales y, a menudo, tienen un fondo semitransparente para ayudar a distinguir la ventana modal del resto de la página.

Modales de ejemplo de GitHub y Material Design
Modales de ejemplo de GitHub y Material Design. (Vista previa grande)

He visto algunas variaciones de un modal de solo CSS (y soy culpable de hacer uno para una versión anterior de mi cartera). Pueden usar el "truco de la casilla de verificación", hacer uso del comportamiento de :target , o tratar de modificarlo fuera de :focus (lo que probablemente sea en realidad una información sobre herramientas demasiado grande disfrazada).

En cuanto al elemento de dialog HTML, tenga en cuenta que no se considera que sea completamente accesible. Entonces, aunque animo absolutamente a la gente a usar HTML nativo antes que las soluciones personalizadas, desafortunadamente esta rompe esa idea. Puede obtener más información sobre por qué no se puede acceder al cuadro de dialog HTML.

A diferencia de la información sobre herramientas, los modales están destinados a permitir contenido estructurado. Esto significa potencialmente un encabezado, algún contenido de párrafo y elementos interactivos como enlaces, botones o incluso formularios. Para que la mayoría de los usuarios accedan a ese contenido, deben poder usar eventos de teclado , en particular tabulación. Para contenido modal más largo, las teclas de flecha también deben conservar la capacidad de desplazarse. Y al igual que la información sobre herramientas, deben descartarse con la tecla Esc , y no hay forma de habilitar eso solo con CSS.

Se requiere JavaScript para la gestión de enfoque dentro de los modales. Los modales deben atrapar el foco, lo que significa que una vez que el foco está dentro del modal, un usuario no debería poder salir de él al contenido de la página detrás de él. Pero primero, el enfoque debe entrar en el modal, que también requiere JavaScript para una solución modal completamente accesible.

Aquí está la secuencia de eventos modales relacionados que deben administrarse con JavaScript:

  1. El detector de eventos en un botón abre el modal
  2. El foco se coloca dentro del modal; qué elemento varía según el contenido modal (ver árbol de decisiones)
  3. El foco queda atrapado dentro del modal hasta que se descarta
  4. Preferiblemente, un usuario puede cerrar un modal con la tecla Esc además de un botón de cierre dedicado o una acción de botón destructiva como "Cancelar" si se requiere el reconocimiento del contenido modal.
    1. Si se permite Esc , los clics en el fondo modal también deberían descartar el modal
  5. Al descartar, si no se produjo la navegación, el foco se vuelve a colocar en el elemento del botón de activación

Árbol de decisión de enfoque modal

Basado en el ejemplo de diálogo modal de prácticas de creación de WAI-ARIA, aquí hay un árbol de decisión simplificado sobre dónde colocar el foco una vez que se abre un modal. El contexto siempre dictará la elección aquí, e idealmente el enfoque se maneja más allá de simplemente "el primer elemento enfocable". De hecho, a veces es necesario seleccionar elementos no enfocables.

  • El sujeto principal del modal es una forma.
    Centrarse en el primer campo de formulario.
  • El contenido modal es significativo en longitud y empuja las acciones modales fuera de la vista.
    Enfocar un encabezado si está presente, o el primer párrafo.
  • El propósito del modal es procedimental (ejemplo: confirmación de acción) con múltiples acciones disponibles.
    Concéntrese en la acción "menos destructiva" según el contexto (ejemplo: "OK").
  • El propósito del modal es procesal con una acción.
    Centrarse en el primer elemento enfocable

Sugerencia rápida : en el caso de que necesite enfocar un elemento no enfocable, como un encabezado o un párrafo, agregue tabindex="-1" que permite que el elemento se enfoca mediante programación con JS pero no lo agrega al orden de tabulación DOM .

Consulte la demostración modal de WAI-ARIA para obtener más información sobre otros requisitos para configurar ARIA y detalles adicionales sobre cómo seleccionar a qué elemento agregar el foco. La demostración también incluye JavaScript para ejemplificar cómo administrar el enfoque.

Para una solución lista para usar, Kitty Giraudel ha creado a11y-dialog que incluye los requisitos de características que discutimos. Adrian Roselli también investigó la gestión del enfoque de los diálogos modales y creó una demostración y recopiló información sobre cómo las diferentes combinaciones de navegador y lector de pantalla comunicarán el elemento enfocado.

Pestañas

Las interfaces con pestañas implican una serie de disparadores que muestran los paneles de contenido correspondientes uno a la vez. Los "hacks" de CSS que puede encontrar para estos implican el uso de botones de opción estilizados, o :target , que permiten revelar solo un panel a la vez.

Pestañas de ejemplo de Shopify Polaris e IBM Carbon
Pestañas de ejemplo de Shopify Polaris e IBM Carbon. (Vista previa grande)

Estas son las características de la pestaña que requieren JavaScript:

  1. Cambiar el atributo aria-selected a verdadero para la pestaña actual y falso para las pestañas no seleccionadas
  2. Creación de un tabindex itinerante para distinguir la selección de pestañas del enfoque
  3. Mueva el foco entre las pestañas respondiendo a los eventos de las teclas de flecha (y, opcionalmente, Home y End )

Opcionalmente, puede hacer que la selección de pestañas siga el enfoque, lo que significa que cuando una pestaña está enfocada, también se selecciona y muestra su panel de pestañas asociado. Las prácticas de creación de WAI-ARIA ofrecen esta guía para decidir si la selección debe seguir el enfoque.

Ya sea que elija o no que la selección siga el enfoque, también usará JavaScript para escuchar eventos de teclas de flecha para mover el enfoque entre los elementos de la pestaña. Este es un patrón alternativo para permitir la navegación por las opciones de pestañas, ya que el uso de un índice de tabulación itinerante (que se describe a continuación) altera el orden natural de enfoque de las pestañas del teclado.

Acerca de Roving tabindex

El concepto de un tabindex itinerante es que el valor del tabindex se controla mediante programación para administrar el orden de enfoque de los elementos. Con respecto a las pestañas, esto significa que solo la pestaña seleccionada es parte del orden de enfoque mediante la configuración de tabindex="0" y las pestañas no seleccionadas se establecen en tabindex="-1" lo que las elimina del orden de enfoque natural del teclado.

La razón de esto es que cuando se selecciona una pestaña, la siguiente pestaña hará que el usuario se enfoque dentro del panel de pestañas asociado. Puede optar por hacer que el elemento que es el panel de pestañas sea enfocable asignándole tabindex="0" , o puede que no sea necesario si hay una garantía de un elemento enfocable dentro del panel de pestañas . Si el contenido de su panel de pestañas será más variable o complejo, puede considerar administrar el enfoque de acuerdo con el árbol de decisiones que revisamos para los modales.

Ejemplos de patrones de pestañas

Aquí hay algunos patrones de referencia para crear pestañas:

  • Demostración de Tabpanel de la Universidad de Deque
  • Pruebas de widgets de pestañas de Scott O'Hara (prueba varios patrones funcionales)
  • Interfaces con pestañas de Inclusive Components de Heydon Pickering, que demuestra cómo las pestañas pueden ser una mejora progresiva de una tabla de contenido

Carruseles

También llamados presentaciones de diapositivas o controles deslizantes, los carruseles involucran una serie de paneles de contenido giratorios (también conocidos como "diapositivas") que incluyen mecanismos de control. Los encontrará en muchas configuraciones con una amplia gama de contenido. Son notoriamente considerados un mal patrón de diseño.

Una demostración de carrusel de ejemplo creada con bxSlider
Una demostración de carrusel de ejemplo creada con bxSlider. (Vista previa grande)

La parte complicada de los carruseles de solo CSS es que es posible que no ofrezcan controles o que usen controles inesperados para manipular el movimiento del carrusel. Por ejemplo, puede volver a usar el "truco de casilla de verificación" para hacer que el carrusel haga la transición, pero las casillas de verificación imparten el tipo incorrecto de información sobre la interacción a los usuarios de tecnología de asistencia. Además, si diseña las etiquetas de las casillas de verificación para que aparezcan visualmente como flechas hacia adelante y hacia atrás, es probable que dé a los usuarios del software de reconocimiento de voz una impresión equivocada de lo que deben decir para controlar el carrusel.

Más recientemente, ha aterrizado la compatibilidad nativa con CSS para desplazamiento rápido. Al principio, esta parece la solución perfecta solo para CSS. Pero, incluso la verificación de accesibilidad automatizada los marcará como no navegables por los usuarios del teclado en caso de que no haya forma de navegar por ellos a través de elementos interactivos. Existen otros problemas de accesibilidad y experiencia del usuario con el comportamiento predeterminado de esta función, algunos de los cuales he incluido en mi demostración de ajuste de desplazamiento en SmolCSS.

A pesar de la amplia gama de apariencia de los carruseles, hay algunos rasgos comunes. Una opción es crear un carrusel usando el marcado de pestañas, ya que efectivamente es la misma interfaz subyacente con una presentación visual alterada. En comparación con las pestañas, los carruseles pueden ofrecer controles adicionales para el anterior y el siguiente, y también pausar si el carrusel se reproduce automáticamente.

Las siguientes son consideraciones de JavaScript según las características de su carrusel:

  • Uso de controles paginados
    Tras la selección de un elemento numerado, enfoque mediante programación la diapositiva del carrusel asociada. Esto implicará configurar contenedores de diapositivas utilizando tabindex itinerante para que pueda enfocar la diapositiva actual, pero evitar el acceso a las diapositivas fuera de la pantalla.
  • Uso de la reproducción automática
    Incluya un control de pausa y también habilite la pausa cuando se desplaza la diapositiva o se enfoca un elemento interactivo dentro de ella. Además, puede verificar si prefers-reduced-motion dentro de JavaScript para cargar la presentación de diapositivas en un estado de pausa para respetar las preferencias del usuario.
  • Uso de los controles Anterior/Siguiente
    Incluya un elemento visualmente oculto marcado como aria-live="polite" y, una vez activados estos controles, complete la región en vivo con una indicación de la posición actual, como "Diapositiva 2 de 4".

Recursos para construir carruseles accesibles

  • Detalles completos de implementación y consideraciones, así como un ejemplo de código completo del tutorial de accesibilidad web W3C en carruseles
  • El ejemplo de Deque University de mejorar una interfaz de pestañas en un carrusel
  • El ejemplo de prácticas de creación de WAI-ARIA de un carrusel de imágenes que gira automáticamente
  • Una selección de recursos de carrusel en el resumen de componentes accesibles de Smashing

Menús desplegables

Esto se refiere a un componente en el que un botón abre una lista de enlaces, que normalmente se usa para los menús de navegación. Las implementaciones de CSS que se limitan a mostrar el menú en :hover o :focus solo pierden algunos detalles importantes.

Ejemplos de menús desplegables de Dribbble, búsqueda de Google y GitHub
Ejemplos de menús desplegables de Dribbble, búsqueda de Google y GitHub. (Vista previa grande)

Lo admito, incluso pensé que al usar la nueva propiedad :focus-within podríamos implementar de manera segura una solución solo de CSS. Verá que mi artículo sobre los menús desplegables de CSS se modificó para incluir notas y recursos sobre el JavaScript necesario (mantuve el título para que otros que busquen esa solución también completen la implementación de JS). Específicamente, confiar solo en CSS significa violar el Criterio de Conformidad 1.4.13 de las WCAG: Contenido al pasar el mouse o enfocar, que aprendimos con la información sobre herramientas.

Necesitamos agregar JavaScript para algunas técnicas que deberían sonar familiares en este punto:

  • Alternar aria-expanded en el botón de menú entre true y false escuchando eventos de click
  • Cerrar un menú abierto al usar la tecla Esc y volver a enfocar el botón de cambio de menú
  • Preferiblemente, cerrar los menús abiertos cuando el foco se mueve fuera del menú
  • Opcional : implemente teclas de flecha, así como End de Home y finalización para la navegación con el teclado entre los botones de alternancia del menú y los enlaces dentro de los menús desplegables.

Sugerencia rápida : asegure la implementación correcta del menú desplegable asociando la visualización del menú al selector de .dropdown-toggle[aria-expanded= " true " ] + .dropdown en lugar de basar la visualización del menú en la presencia de un JS- adicional. clase agregada como active . ¡Esto también elimina cierta complejidad de su solución JS!

Esto también se denomina "patrón de divulgación" y puede encontrar más detalles en el menú de navegación de divulgación de ejemplos de WAI-ARIA Authoring Practices.

Recursos adicionales sobre la creación de componentes accesibles

  • Guía completa de Smashing sobre componentes front-end accesibles
  • Artículo de Carie Fisher Good, Better, Best: Desenredando el complejo mundo de los patrones accesibles
  • Demostraciones e información sobre patrones de diseño comunes y widgets disponibles en WAI-ARIA Authoring Practices 1.2
  • Biblioteca de códigos de la Universidad de Deque
  • Componentes accesibles de Scott O'Hara
  • Componentes inclusivos de Heydon Pickering