Best Practices

Accesibilidad en Angular

La web es utilizada por una amplia variedad de personas, incluidas aquellas que tienen deficiencias visuales o motoras. Existen diversas tecnologías de asistencia disponibles que facilitan mucho la interacción de estos grupos con aplicaciones de software basadas en la web. Además, diseñar una aplicación para que sea más accesible generalmente mejora la experiencia del usuario para todos los usuarios.

Para una introducción en profundidad sobre los problemas y técnicas para diseñar aplicaciones accesibles, consulta el curso Learn Accessibility de web.dev de Google.

Esta página aborda las mejores prácticas para diseñar aplicaciones Angular que funcionen bien para todos los usuarios, incluidos aquellos que dependen de tecnologías de asistencia.

Atributos de accesibilidad

Construir experiencias web accesibles a menudo implica establecer atributos de Aplicaciones de Internet Enriquecidas Accesibles (ARIA) para proporcionar significado semántico donde de otro modo podría faltar. Usa la sintaxis de plantilla de enlace de atributo para controlar los valores de los atributos relacionados con la accesibilidad.

Al enlazar a atributos ARIA en Angular, debes usar el prefijo attr.. La especificación ARIA depende específicamente de atributos HTML en lugar de propiedades de elementos DOM.

<!-- Usa attr. al enlazar a un atributo ARIA --><button [attr.aria-label]="myActionLabel">…</button>

NOTA: Esta sintaxis solo es necesaria para enlaces de atributo. Los atributos ARIA estáticos no requieren sintaxis adicional.

<!-- Los atributos ARIA estáticos no requieren sintaxis adicional --><button aria-label="Save document">…</button>

ÚTIL: Por convención, los atributos HTML usan nombres en minúsculas (tabindex), mientras que las propiedades usan nombres en camelCase (tabIndex).

Consulta la guía de sintaxis de enlace para más información sobre la diferencia entre atributos y propiedades.

Componentes UI de Angular

La biblioteca Angular Material, que es mantenida por el equipo de Angular, es un conjunto de componentes UI reutilizables que busca ser completamente accesible. El Component Development Kit (CDK) incluye el paquete a11y que proporciona herramientas para soportar diversas áreas de accesibilidad. Por ejemplo:

  • LiveAnnouncer se usa para anunciar mensajes para usuarios de lectores de pantalla usando una región aria-live. Consulta la documentación de W3C para más información sobre regiones aria-live.

  • La directiva cdkTrapFocus atrapa el foco de la tecla Tab dentro de un elemento. Úsala para crear experiencias accesibles para componentes como diálogos modales, donde el foco debe estar restringido.

Para detalles completos de estas y otras herramientas, consulta la visión general de accesibilidad de Angular CDK.

Aumentando elementos nativos

Los elementos HTML nativos capturan varios patrones de interacción estándar que son importantes para la accesibilidad. Al crear componentes de Angular, debes reutilizar estos elementos nativos directamente cuando sea posible, en lugar de reimplementar comportamientos bien soportados.

Por ejemplo, en lugar de crear un elemento personalizado para una nueva variedad de botón, crea un componente que use un selector de atributo con un elemento <button> nativo. Esto se aplica más comúnmente a <button> y <a>, pero puede usarse con muchos otros tipos de elementos.

Puedes ver ejemplos de este patrón en Angular Material: MatButton, MatTabNav, y MatTable.

Usando contenedores para elementos nativos

A veces, usar el elemento nativo apropiado requiere un elemento contenedor. Por ejemplo, el elemento nativo <input> no puede tener hijos, por lo que cualquier componente personalizado de entrada de texto necesita envolver un <input> con elementos adicionales. Al simplemente incluir <input> en la plantilla de tu componente personalizado, es imposible para los usuarios de tu componente establecer propiedades y atributos arbitrarios al elemento <input>. En su lugar, crea un componente contenedor que use proyección de contenido para incluir el control nativo en la API del componente.

Puedes ver MatFormField como ejemplo de este patrón.

Caso de estudio: Construyendo una barra de progreso personalizada

El siguiente ejemplo muestra cómo hacer accesible una barra de progreso usando host binding para controlar atributos relacionados con la accesibilidad.

  • El componente define un elemento habilitado para accesibilidad con tanto el atributo HTML estándar role, como atributos ARIA. El atributo ARIA aria-valuenow está enlazado a la entrada del usuario.
  • En la plantilla, el atributo aria-label asegura que el control sea accesible para lectores de pantalla.
1import {Component, input} from '@angular/core';23/**4 * Example progressbar component.5 */6@Component({7  selector: 'app-example-progressbar',8  template: '<div class="bar" [style.width.%]="value()"></div>',9  styleUrls: ['./progress-bar.component.css'],10  host: {11    // Sets the role for this component to "progressbar"12    role: 'progressbar',1314    // Sets the minimum and maximum values for the progressbar role.15    'aria-valuemin': '0',16    'aria-valuemax': '100',1718    // Binding that updates the current value of the progressbar.19    '[attr.aria-valuenow]': 'value',20  },21})22export class ExampleProgressbarComponent {23  /** Current value of the progressbar. */24  value = input(0);25}2627
1<h1>Accessibility Example</h1>2<label for="progress-value">3  Enter an example progress value4  <input id="progress-value" type="number" min="0" max="100"5      [value]="progress" (input)="setProgress($event)">6</label>78<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->9<app-example-progressbar [value]="progress" aria-label="Example of a progress bar">10</app-example-progressbar>1112

Enrutamiento

Gestión del foco después de la navegación

Rastrear y controlar el foco en una UI es una consideración importante al diseñar para accesibilidad. Al usar el enrutamiento de Angular, debes decidir dónde va el foco de la página al navegar.

Para evitar depender únicamente de señales visuales, necesitas asegurarte de que tu código de enrutamiento actualice el foco después de la navegación de la página. Usa el evento NavigationEnd del servicio Router para saber cuándo actualizar el foco.

El siguiente ejemplo muestra cómo encontrar y enfocar el encabezado de contenido principal en el DOM después de la navegación.

router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {  const mainHeader = document.querySelector('#main-content-header')  if (mainHeader) {    mainHeader.focus();  }});

En una aplicación real, el elemento que recibe el foco depende de la estructura y diseño específicos de tu aplicación. El elemento enfocado debe poner a los usuarios en una posición para moverse inmediatamente al contenido principal que acaba de ser enrutado a la vista. Debes evitar situaciones donde el foco regresa al elemento body después de un cambio de ruta.

Identificación de enlaces activos

Las clases CSS aplicadas a elementos RouterLink activos, como RouterLinkActive, proporcionan una señal visual para identificar el enlace activo. Desafortunadamente, una señal visual no ayuda a usuarios ciegos o con deficiencia visual. Aplicar el atributo aria-current al elemento puede ayudar a identificar el enlace activo. Para más información, consulta Mozilla Developer Network (MDN) aria-current).

La directiva RouterLinkActive proporciona la entrada ariaCurrentWhenActive que establece el aria-current a un valor especificado cuando el enlace se vuelve activo.

El siguiente ejemplo muestra cómo aplicar la clase active-page a los enlaces activos así como establecer su atributo aria-current a "page" cuando están activos:

<nav>  <a routerLink="home"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    Home  </a>  <a routerLink="about"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    About  </a>  <a routerLink="shop"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    Shop  </a></nav>

Más información

Libros

  • "A Web for Everyone: Designing Accessible User Experiences," Sarah Horton and Whitney Quesenbery
  • "Inclusive Design Patterns," Heydon Pickering