HTML
Tutorial HTML: Atributos de ARIA
Aprende a usar atributos ARIA para hacer tus aplicaciones web accesibles, mejorando la navegación y experiencia de usuarios con discapacidades.
Aprende HTML y certifícatePropósito y concepto de WAI-ARIA
La accesibilidad web es un aspecto fundamental del desarrollo moderno que busca garantizar que todas las personas, independientemente de sus capacidades, puedan percibir, entender, navegar e interactuar con la web. En este contexto surge WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications), una especificación técnica desarrollada por el W3C que proporciona una forma de hacer el contenido web y las aplicaciones más accesibles para personas con discapacidades.
WAI-ARIA aborda una brecha crítica en la accesibilidad: mientras que HTML tradicional funciona bien para estructuras de documentos simples, las aplicaciones web modernas con interfaces dinámicas y componentes interactivos complejos presentan desafíos significativos para los usuarios de tecnologías asistivas. Estas aplicaciones a menudo utilizan JavaScript y actualizaciones de contenido dinámicas que los lectores de pantalla y otras tecnologías asistivas pueden tener dificultades para interpretar correctamente.
¿Qué problemas resuelve WAI-ARIA?
WAI-ARIA soluciona principalmente tres tipos de problemas de accesibilidad:
- Contenido dinámico: Cuando el contenido cambia sin recargar la página completa, los usuarios de lectores de pantalla pueden no ser notificados de estos cambios.
<!-- Sin ARIA -->
<div id="notification">
<!-- El contenido cambia dinámicamente mediante JavaScript -->
</div>
<!-- Con ARIA -->
<div id="notification" aria-live="polite">
<!-- Ahora los cambios serán anunciados por el lector de pantalla -->
</div>
- Widgets personalizados: Los elementos de interfaz creados con HTML genérico (como divs y spans) no transmiten su función a las tecnologías asistivas.
<!-- Un botón creado con un div no es reconocible como botón -->
<div class="button" onclick="doSomething()">Enviar</div>
<!-- Con ARIA, definimos su rol -->
<div class="button" role="button" onclick="doSomething()" tabindex="0">Enviar</div>
- Relaciones entre elementos: Las relaciones entre componentes (como un menú desplegable y sus opciones) no siempre son evidentes para las tecnologías asistivas.
<!-- Sin ARIA, la relación entre el campo y su mensaje de error no es clara -->
<input type="text" id="username">
<span class="error">El nombre de usuario es obligatorio</span>
<!-- Con ARIA, establecemos la relación -->
<input type="text" id="username" aria-describedby="username-error">
<span id="username-error" class="error">El nombre de usuario es obligatorio</span>
Principios fundamentales de WAI-ARIA
WAI-ARIA se basa en tres conceptos principales que trabajan juntos para mejorar la accesibilidad:
Roles: Definen lo que es un elemento o su propósito. Por ejemplo,
role="navigation"
indica que un elemento sirve como navegación principal.Propiedades: Proporcionan información adicional sobre un elemento. Por ejemplo,
aria-required="true"
indica que un campo de formulario es obligatorio.Estados: Comunican las condiciones actuales de un elemento que pueden cambiar. Por ejemplo,
aria-expanded="false"
indica que un menú desplegable está actualmente cerrado.
La regla de oro de ARIA
Es importante entender la primera regla de ARIA, que establece:
No uses ARIA si puedes usar elementos HTML nativos con la semántica y comportamiento incorporados que necesitas.
<!-- Mal uso de ARIA -->
<div role="button" tabindex="0" onclick="submitForm()">Enviar</div>
<!-- Mejor: usar el elemento nativo -->
<button onclick="submitForm()">Enviar</button>
Los elementos HTML nativos ya tienen roles implícitos, estados y propiedades incorporados, además de comportamientos como el enfoque del teclado, que tendrías que implementar manualmente al usar ARIA con elementos genéricos.
Implementación básica de WAI-ARIA
Para implementar WAI-ARIA en un proyecto web, se siguen estos pasos fundamentales:
Identificar los componentes interactivos de la interfaz que podrían presentar problemas de accesibilidad.
Aplicar roles apropiados a los elementos que no comunican claramente su propósito:
<nav role="navigation">
<!-- El rol es redundante aquí porque <nav> ya tiene semántica -->
</nav>
<div role="search">
<!-- Aquí el rol es útil porque <div> no tiene semántica específica -->
<form>
<input type="text" aria-label="Buscar en el sitio">
<button type="submit">Buscar</button>
</form>
</div>
- Añadir propiedades y estados para proporcionar contexto adicional:
<button aria-expanded="false" aria-controls="menu-content">
Menú
</button>
<div id="menu-content" hidden>
<!-- Contenido del menú -->
</div>
- Gestionar actualizaciones dinámicas para notificar a los usuarios de cambios:
<div aria-live="polite">
<p id="status-message">Formulario enviado correctamente</p>
</div>
Beneficios de implementar WAI-ARIA
La implementación adecuada de WAI-ARIA ofrece múltiples ventajas:
- Mejora la experiencia para usuarios de tecnologías asistivas sin afectar a otros usuarios.
- Cumplimiento de estándares como las WCAG (Web Content Accessibility Guidelines).
- Compatibilidad con la mayoría de navegadores y tecnologías asistivas modernas.
- Mantenimiento de la funcionalidad visual mientras se mejora la accesibilidad semántica.
Consideraciones importantes
Al implementar WAI-ARIA, es esencial tener en cuenta estas consideraciones clave:
- No sobreutilizar ARIA: Aplicar atributos ARIA innecesarios puede crear confusión.
- Probar con tecnologías asistivas reales: Verificar que la implementación funciona como se espera.
- Mantener la coherencia: Usar patrones de diseño de ARIA establecidos.
<!-- Ejemplo de un componente de pestañas accesible -->
<div role="tablist">
<button id="tab1" role="tab" aria-selected="true" aria-controls="panel1">Pestaña 1</button>
<button id="tab2" role="tab" aria-selected="false" aria-controls="panel2">Pestaña 2</button>
</div>
<div id="panel1" role="tabpanel" aria-labelledby="tab1">
Contenido de la primera pestaña
</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>
Contenido de la segunda pestaña
</div>
WAI-ARIA representa una herramienta poderosa para mejorar la accesibilidad web, pero debe utilizarse con conocimiento y precisión. Su propósito fundamental es complementar HTML cuando la semántica nativa no es suficiente, creando así experiencias web más inclusivas para todos los usuarios.
Roles, estados y propiedades ARIA básicos
Los roles, estados y propiedades son los tres componentes fundamentales de WAI-ARIA que permiten mejorar la accesibilidad de las aplicaciones web. Estos elementos trabajan en conjunto para proporcionar información semántica adicional a las tecnologías asistivas, como los lectores de pantalla, permitiéndoles interpretar correctamente la interfaz de usuario.
Roles ARIA
Los roles ARIA definen el tipo de elemento o su propósito en la interfaz. Cuando asignamos un rol a un elemento, estamos comunicando a las tecnologías asistivas qué es ese elemento y qué función cumple. Los roles se aplican mediante el atributo role
.
Algunos de los roles ARIA más comunes incluyen:
- Roles de estructura:
<div role="banner">
<!-- Contenido del encabezado principal del sitio -->
</div>
<div role="main">
<!-- Contenido principal de la página -->
</div>
<div role="complementary">
<!-- Información complementaria, como una barra lateral -->
</div>
- Roles de widgets (elementos interactivos):
<div role="button" tabindex="0">Aceptar</div>
<div role="checkbox" tabindex="0" aria-checked="false">Acepto los términos</div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50">
<!-- Representación visual del slider -->
</div>
- Roles de documento:
<div role="article">
<!-- Contenido de un artículo -->
</div>
<div role="heading" aria-level="2">
<!-- Un encabezado de nivel 2 -->
</div>
Estados ARIA
Los estados ARIA comunican las condiciones dinámicas de los elementos. A diferencia de los roles (que generalmente permanecen constantes), los estados cambian con frecuencia durante la interacción del usuario. Los estados se actualizan mediante JavaScript para reflejar el estado actual del componente.
Algunos estados ARIA comunes son:
- aria-checked: Indica si un checkbox o radio button está marcado.
<div role="checkbox" aria-checked="true" tabindex="0">Opción seleccionada</div>
- aria-expanded: Indica si un elemento expandible está abierto o cerrado.
<button aria-expanded="false" aria-controls="menu1">Menú</button>
<ul id="menu1" hidden>
<li>Opción 1</li>
<li>Opción 2</li>
</ul>
- aria-selected: Indica si un elemento seleccionable está actualmente seleccionado.
<div role="tablist">
<div role="tab" aria-selected="true" id="tab1">Pestaña 1</div>
<div role="tab" aria-selected="false" id="tab2">Pestaña 2</div>
</div>
- aria-disabled: Indica si un elemento está deshabilitado.
<div role="button" aria-disabled="true">No disponible</div>
Propiedades ARIA
Las propiedades ARIA proporcionan información adicional sobre un elemento y sus relaciones con otros elementos. A diferencia de los estados, las propiedades suelen ser más estables y describen características permanentes o semipermanentes.
Algunas propiedades ARIA importantes incluyen:
- aria-label: Proporciona una etiqueta accesible cuando no hay texto visible.
<button aria-label="Cerrar ventana">
<span class="icon-close"></span>
</button>
- aria-labelledby: Identifica otro elemento que sirve como etiqueta.
<div id="titulo">Información personal</div>
<div role="form" aria-labelledby="titulo">
<!-- Campos del formulario -->
</div>
- aria-describedby: Identifica otro elemento que proporciona una descripción adicional.
<input type="text" aria-describedby="password-requirements">
<div id="password-requirements">La contraseña debe tener al menos 8 caracteres</div>
- aria-required: Indica que un campo de entrada es obligatorio.
<div role="textbox" aria-required="true" tabindex="0"></div>
Regiones en vivo (Live Regions)
Las regiones en vivo son áreas de la página que se actualizan dinámicamente y necesitan comunicar estos cambios a los usuarios de tecnologías asistivas. Se configuran mediante propiedades específicas:
- aria-live: Define la prioridad de los anuncios.
<!-- Los cambios se anunciarán cuando el usuario esté inactivo -->
<div aria-live="polite">
<p id="status">Formulario guardado correctamente</p>
</div>
<!-- Los cambios se anunciarán inmediatamente, interrumpiendo al usuario -->
<div aria-live="assertive">
<p id="error">Error de conexión</p>
</div>
- aria-atomic: Indica si se debe anunciar todo el contenido o solo los cambios.
<!-- Se anunciará todo el contenido de la región -->
<div aria-live="polite" aria-atomic="true">
<p>Estado: <span id="status-text">Procesando</span></p>
</div>
- aria-relevant: Especifica qué tipos de cambios son relevantes para anunciar.
<!-- Se anunciarán adiciones y modificaciones de texto -->
<div aria-live="polite" aria-relevant="additions text">
<ul id="notification-list">
<!-- Notificaciones se añadirán aquí -->
</ul>
</div>
Implementación de componentes comunes
Veamos cómo implementar algunos componentes interactivos comunes utilizando roles, estados y propiedades ARIA:
Menú desplegable
<button aria-haspopup="true" aria-expanded="false" aria-controls="dropdown-menu">
Opciones
</button>
<ul id="dropdown-menu" role="menu" hidden>
<li role="menuitem" tabindex="-1">Opción 1</li>
<li role="menuitem" tabindex="-1">Opción 2</li>
<li role="menuitem" tabindex="-1">Opción 3</li>
</ul>
En este ejemplo:
aria-haspopup
indica que el botón controla un menú emergentearia-expanded
comunica si el menú está visible u ocultoaria-controls
establece la relación entre el botón y el menú- Los roles
menu
ymenuitem
definen la estructura del menú
Diálogo modal
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true">
<h2 id="dialog-title">Confirmar acción</h2>
<p id="dialog-desc">¿Está seguro de que desea continuar?</p>
<button aria-describedby="dialog-desc">Confirmar</button>
<button>Cancelar</button>
</div>
En este ejemplo:
role="dialog"
identifica el elemento como un diálogoaria-labelledby
asocia el título con el diálogoaria-modal="true"
indica que el diálogo bloquea la interacción con el resto de la página
Acordeón
<div class="accordion">
<h3>
<button aria-expanded="true" aria-controls="section1">
Sección 1
</button>
</h3>
<div id="section1">
<p>Contenido de la sección 1</p>
</div>
<h3>
<button aria-expanded="false" aria-controls="section2">
Sección 2
</button>
</h3>
<div id="section2" hidden>
<p>Contenido de la sección 2</p>
</div>
</div>
En este ejemplo:
aria-expanded
indica si cada sección está expandida o colapsadaaria-controls
establece la relación entre el botón y el contenido que controla
Mejores prácticas para implementar ARIA
Al implementar roles, estados y propiedades ARIA, es importante seguir estas mejores prácticas:
- Usar HTML semántico primero: Siempre que sea posible, utiliza elementos HTML nativos antes de recurrir a ARIA.
<!-- Evitar esto -->
<div role="button" tabindex="0" onclick="handleClick()">Enviar</div>
<!-- Preferir esto -->
<button onclick="handleClick()">Enviar</button>
- Mantener sincronizados los atributos ARIA: Cuando el estado visual cambia, actualiza también los atributos ARIA correspondientes.
// Al abrir un menú desplegable
function openMenu() {
// Cambio visual
document.getElementById('dropdown-menu').hidden = false;
// Actualización de ARIA
document.getElementById('menu-button').setAttribute('aria-expanded', 'true');
}
- No cambiar el significado de los roles nativos: No uses ARIA para cambiar el rol implícito de un elemento HTML.
<!-- Incorrecto: cambiar el rol de un botón -->
<button role="heading">Esto no es un encabezado</button>
<!-- Correcto: usar el elemento apropiado -->
<h2>Este es un encabezado</h2>
<button>Este es un botón</button>
- Asegurar la operabilidad con teclado: Los elementos interactivos deben ser accesibles mediante teclado.
<!-- Añadir tabindex para permitir el enfoque con teclado -->
<div role="button" tabindex="0" onclick="handleClick()" onkeydown="handleKeyDown(event)">
Acción
</div>
<script>
function handleKeyDown(event) {
// Activar con Enter o Space
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleClick();
}
}
</script>
- Probar con tecnologías asistivas reales: Verifica que tu implementación funciona correctamente con lectores de pantalla y otros dispositivos de asistencia.
La implementación adecuada de roles, estados y propiedades ARIA es fundamental para crear interfaces web verdaderamente accesibles. Estos componentes trabajan juntos para proporcionar el contexto necesario a las tecnologías asistivas, permitiendo que todos los usuarios interactúen efectivamente con el contenido web.
Técnicas para mejorar navegación y orientación
La navegación y orientación son aspectos fundamentales para que los usuarios con discapacidades puedan desplazarse eficientemente por una página web. Mientras que los roles, estados y propiedades ARIA proporcionan información semántica sobre los elementos individuales, también necesitamos implementar técnicas específicas que ayuden a los usuarios a entender la estructura general de la página y a navegar por ella con facilidad.
Puntos de referencia (landmarks)
Los puntos de referencia ARIA permiten a los usuarios de lectores de pantalla saltar directamente a secciones específicas de la página. Estos actúan como señalizaciones que dividen la página en regiones funcionales reconocibles.
<header role="banner">
<h1>Nombre del sitio</h1>
</header>
<nav role="navigation">
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/productos">Productos</a></li>
</ul>
</nav>
<main role="main">
<h2>Contenido principal</h2>
<!-- Contenido de la página -->
</main>
<aside role="complementary">
<h2>Información relacionada</h2>
<!-- Contenido complementario -->
</aside>
<footer role="contentinfo">
<p>© 2023 Mi Empresa</p>
</footer>
Los roles de punto de referencia más comunes incluyen:
- banner: Identifica el encabezado principal del sitio
- navigation: Identifica secciones con enlaces de navegación
- main: Marca el contenido principal de la página
- complementary: Contenido que complementa el contenido principal
- contentinfo: Información sobre el documento (pie de página)
- search: Sección que contiene funcionalidad de búsqueda
- form: Sección que contiene un formulario (cuando tiene relevancia por sí mismo)
Estructura jerárquica de encabezados
Una estructura de encabezados clara y jerárquica (h1-h6) proporciona un esquema de la página que los usuarios de lectores de pantalla pueden utilizar para navegar. Es esencial mantener una jerarquía lógica sin saltar niveles.
<h1>Título principal de la página</h1>
<section>
<h2>Sección principal</h2>
<p>Contenido introductorio...</p>
<article>
<h3>Subsección</h3>
<p>Más contenido detallado...</p>
<h4>Detalle específico</h4>
<p>Información muy específica...</p>
</article>
</section>
Para verificar la estructura de encabezados, podemos usar el atributo aria-level
cuando sea necesario ajustar el nivel semántico sin cambiar la apariencia visual:
<!-- Para un elemento que visualmente no parece un encabezado -->
<div role="heading" aria-level="2">Sección importante</div>
Saltos de navegación
Los enlaces de salto (skip links) permiten a los usuarios de teclado y lectores de pantalla saltar directamente al contenido principal, evitando tener que navegar por menús repetitivos.
<body>
<a href="#main-content" class="skip-link">Saltar al contenido principal</a>
<header>
<!-- Navegación y encabezado del sitio -->
</header>
<main id="main-content" tabindex="-1">
<!-- Contenido principal -->
</main>
</body>
El CSS para estos enlaces suele ocultarlos visualmente hasta que reciben el foco:
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: white;
padding: 8px;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
El atributo tabindex="-1"
en el elemento de destino permite que reciba el foco programáticamente cuando se activa el enlace de salto.
Indicadores de ubicación
Los indicadores de ubicación ayudan a los usuarios a entender dónde se encuentran dentro del sitio web. Las migas de pan (breadcrumbs) son un ejemplo común:
<nav aria-label="Migas de pan">
<ol class="breadcrumb">
<li><a href="/">Inicio</a></li>
<li><a href="/productos">Productos</a></li>
<li aria-current="page">Detalles del producto</li>
</ol>
</nav>
El atributo aria-current="page"
indica la página actual en la navegación, lo que ayuda a los usuarios de lectores de pantalla a entender su ubicación.
Mejora de la navegación por tabulación
La navegación por teclado es esencial para muchos usuarios. El atributo tabindex
puede utilizarse para controlar el orden de tabulación:
<!-- Elementos que normalmente no reciben foco -->
<div tabindex="0" role="button">Elemento interactivo personalizado</div>
<!-- Elementos que deben ser enfocables pero no en el flujo normal de tabulación -->
<div tabindex="-1">Solo enfocable programáticamente</div>
<!-- Evitar usar tabindex positivos -->
<div tabindex="1">Este orden de tabulación personalizado puede causar confusión</div>
Algunas recomendaciones para la navegación por teclado:
- Usa
tabindex="0"
para incluir elementos no estándar en el flujo de navegación - Usa
tabindex="-1"
para elementos que solo deben recibir foco programáticamente - Evita usar valores positivos de tabindex, ya que pueden interrumpir el flujo natural de navegación
Agrupación de contenido relacionado
La agrupación lógica de elementos relacionados ayuda a los usuarios a comprender la estructura de la página:
<fieldset>
<legend>Información personal</legend>
<div>
<label for="name">Nombre:</label>
<input type="text" id="name">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email">
</div>
</fieldset>
Para agrupaciones más complejas, podemos usar role="group"
y aria-labelledby
:
<div role="group" aria-labelledby="group-title">
<h3 id="group-title">Configuración de notificaciones</h3>
<div role="checkbox" tabindex="0" aria-checked="true">
Notificaciones por email
</div>
<div role="checkbox" tabindex="0" aria-checked="false">
Notificaciones push
</div>
</div>
Menús de navegación accesibles
Los menús de navegación deben ser accesibles tanto para usuarios de ratón como de teclado:
<nav aria-label="Menú principal">
<ul role="menubar">
<li role="none">
<a role="menuitem" href="/" aria-current="page">Inicio</a>
</li>
<li role="none">
<button role="menuitem" aria-haspopup="true" aria-expanded="false">
Productos
</button>
<ul role="menu" hidden>
<li role="none">
<a role="menuitem" href="/productos/categoria1">Categoría 1</a>
</li>
<li role="none">
<a role="menuitem" href="/productos/categoria2">Categoría 2</a>
</li>
</ul>
</li>
</ul>
</nav>
En este ejemplo:
aria-label
proporciona un nombre accesible al menúrole="menubar"
yrole="menu"
identifican las listas como menúsrole="menuitem"
identifica los elementos del menúrole="none"
evita que los elementos<li>
sean anunciados como elementos de listaaria-haspopup
yaria-expanded
indican la presencia y estado de submenús
Tablas de datos accesibles
Las tablas de datos deben incluir marcado apropiado para ayudar a los usuarios de lectores de pantalla a navegar y comprender la información:
<table>
<caption>Horario de clases</caption>
<thead>
<tr>
<th scope="col">Hora</th>
<th scope="col">Lunes</th>
<th scope="col">Martes</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">9:00</th>
<td>Matemáticas</td>
<td>Historia</td>
</tr>
<tr>
<th scope="row">10:00</th>
<td>Ciencias</td>
<td>Literatura</td>
</tr>
</tbody>
</table>
Los elementos clave para tablas accesibles son:
<caption>
proporciona un título descriptivo<th>
conscope="col"
oscope="row"
identifica encabezados de columna o fila- Estructura adecuada con
<thead>
,<tbody>
y<tfoot>
cuando sea apropiado
Para tablas más complejas, podemos usar id
y headers
:
<table>
<caption>Resultados por trimestre</caption>
<tr>
<th id="empty"></th>
<th id="q1">Q1</th>
<th id="q2">Q2</th>
</tr>
<tr>
<th id="sales">Ventas</th>
<td headers="sales q1">10.000€</td>
<td headers="sales q2">15.000€</td>
</tr>
<tr>
<th id="expenses">Gastos</th>
<td headers="expenses q1">8.000€</td>
<td headers="expenses q2">9.000€</td>
</tr>
</table>
Orientación mediante descripciones contextuales
Las descripciones contextuales ayudan a los usuarios a entender la finalidad y el funcionamiento de los elementos:
<!-- Descripción para un campo de contraseña -->
<label for="password">Contraseña</label>
<input type="password" id="password" aria-describedby="password-requirements">
<p id="password-requirements">
La contraseña debe tener al menos 8 caracteres, incluyendo una letra mayúscula y un número.
</p>
<!-- Descripción para un botón de acción -->
<button aria-describedby="delete-description">Eliminar cuenta</button>
<p id="delete-description" class="visually-hidden">
Esta acción eliminará permanentemente tu cuenta y todos tus datos. No podrá deshacerse.
</p>
La clase visually-hidden
permite ocultar visualmente el texto mientras sigue siendo accesible para lectores de pantalla:
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
Implementación de atajos de teclado personalizados
Los atajos de teclado pueden mejorar significativamente la navegación para usuarios avanzados. Es importante documentarlos claramente:
<div class="keyboard-shortcuts">
<h2 id="shortcuts-title">Atajos de teclado disponibles</h2>
<ul aria-labelledby="shortcuts-title">
<li><kbd>?</kbd> Mostrar esta ayuda</li>
<li><kbd>/</kbd> Ir al buscador</li>
<li><kbd>h</kbd> Ir a inicio</li>
</ul>
</div>
<button aria-keyshortcuts="/" onclick="focusSearch()">Buscar</button>
El atributo aria-keyshortcuts
informa a las tecnologías asistivas sobre los atajos de teclado disponibles para un elemento.
Mejora de la orientación visual
Aunque nos centramos en la accesibilidad para tecnologías asistivas, no debemos olvidar mejorar la orientación visual para usuarios con discapacidades cognitivas o de atención:
<!-- Destacar la sección actual -->
<nav>
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/productos" class="current" aria-current="page">Productos</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav>
<style>
.current {
font-weight: bold;
border-bottom: 2px solid #0066cc;
}
</style>
Otras técnicas de orientación visual incluyen:
- Usar colores contrastantes para elementos activos
- Proporcionar indicadores visuales claros del foco del teclado
- Mantener un diseño coherente en todas las páginas
- Usar iconos junto con texto para reforzar el significado
La implementación de estas técnicas de navegación y orientación, junto con los roles, estados y propiedades ARIA, crea una experiencia web más accesible e intuitiva para todos los usuarios, independientemente de sus capacidades o de las tecnologías que utilicen para acceder al contenido.
Pruebas de accesibilidad con lectores de pantalla
Implementar atributos ARIA en tu código HTML es solo el primer paso para crear sitios web accesibles. Para garantizar que estos atributos realmente mejoran la experiencia de los usuarios con discapacidades, es fundamental realizar pruebas con lectores de pantalla. Estas herramientas son el principal medio por el que muchos usuarios con discapacidad visual interactúan con la web.
Principales lectores de pantalla para pruebas
Para realizar pruebas efectivas, es recomendable familiarizarse con los lectores de pantalla más utilizados:
- NVDA (NonVisual Desktop Access): Lector de pantalla gratuito y de código abierto para Windows.
- JAWS (Job Access With Speech): Uno de los lectores de pantalla comerciales más utilizados en entornos profesionales.
- VoiceOver: Integrado en dispositivos Apple (macOS, iOS, iPadOS).
- TalkBack: El lector de pantalla nativo de Android.
- Narrator: Incluido en Windows 10 y 11.
Cada lector de pantalla tiene sus propias características y comandos, por lo que es importante probar con varios para asegurar una compatibilidad amplia.
<!-- Este botón debe ser anunciado correctamente por todos los lectores de pantalla -->
<button aria-label="Cerrar ventana" aria-describedby="close-description">
<span class="icon-close"></span>
</button>
<div id="close-description" hidden>Cierra el diálogo sin guardar los cambios</div>
Configuración del entorno de pruebas
Antes de comenzar las pruebas, es necesario preparar adecuadamente el entorno:
- Instala al menos dos lectores de pantalla diferentes para comparar resultados.
- Aprende los comandos básicos de navegación de cada lector de pantalla.
- Desactiva el ratón durante las pruebas para experimentar la navegación exclusivamente con teclado.
- Prepara casos de prueba específicos para cada componente de tu interfaz.
Metodología de pruebas sistemáticas
Para realizar pruebas efectivas, sigue una metodología sistemática:
- Prueba la navegación estructural:
- Verifica que los puntos de referencia (landmarks) sean anunciados correctamente.
- Comprueba que la estructura de encabezados sea lógica y navegable.
<header role="banner">
<h1>Tienda en línea</h1>
</header>
<nav role="navigation" aria-label="Menú principal">
<!-- Navegación -->
</nav>
<main role="main">
<h2>Productos destacados</h2>
<!-- Contenido principal -->
</main>
- Evalúa componentes interactivos:
- Verifica que los botones, enlaces y controles de formulario sean anunciados con su función y estado.
- Comprueba que los componentes personalizados (como menús desplegables o pestañas) comuniquen correctamente su estado.
<div role="tablist">
<button role="tab" aria-selected="true" aria-controls="panel1" id="tab1">Información</button>
<button role="tab" aria-selected="false" aria-controls="panel2" id="tab2">Especificaciones</button>
</div>
<div id="panel1" role="tabpanel" aria-labelledby="tab1">
<!-- Contenido del panel 1 -->
</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>
<!-- Contenido del panel 2 -->
</div>
- Prueba las actualizaciones dinámicas:
- Verifica que las regiones en vivo (live regions) anuncien los cambios de contenido.
- Comprueba que los mensajes de error y confirmación sean anunciados apropiadamente.
<form>
<label for="email">Email:</label>
<input type="email" id="email" aria-describedby="email-error">
<div id="email-error" aria-live="assertive" class="error-message"></div>
<button type="submit">Enviar</button>
<div aria-live="polite" class="status-message"></div>
</form>
- Evalúa la orientación y contexto:
- Verifica que los usuarios puedan determinar dónde se encuentran en la página.
- Comprueba que las relaciones entre elementos sean claras (como etiquetas y campos).
<nav aria-label="Migas de pan">
<ol>
<li><a href="/">Inicio</a></li>
<li><a href="/productos">Productos</a></li>
<li aria-current="page">Detalles del producto</li>
</ol>
</nav>
Herramientas complementarias para pruebas
Además de los lectores de pantalla, existen herramientas complementarias que pueden ayudar en el proceso de pruebas:
Extensiones de navegador:
Axe DevTools: Identifica problemas de accesibilidad en tiempo real.
WAVE: Evalúa visualmente la accesibilidad de la página.
Accessibility Insights: Proporciona pruebas automatizadas y manuales detalladas.
Herramientas de inspección:
Árbol de accesibilidad del navegador (Chrome DevTools > Accessibility).
Inspector de accesibilidad de Firefox.
// Ejemplo de código para verificar programáticamente algunos aspectos de accesibilidad
function checkAccessibility() {
// Verificar que todos los elementos interactivos tienen nombres accesibles
const buttons = document.querySelectorAll('button, [role="button"]');
buttons.forEach(button => {
const hasAccessibleName = button.textContent.trim() ||
button.getAttribute('aria-label') ||
button.getAttribute('aria-labelledby');
if (!hasAccessibleName) {
console.error('Botón sin nombre accesible:', button);
}
});
// Verificar que las imágenes tienen texto alternativo
const images = document.querySelectorAll('img');
images.forEach(img => {
if (!img.hasAttribute('alt')) {
console.error('Imagen sin atributo alt:', img);
}
});
}
Pruebas específicas para componentes comunes
A continuación, se presentan pruebas específicas para componentes web comunes:
Pruebas para diálogos modales
- Verifica que el foco se mueva al diálogo cuando se abre.
- Comprueba que el foco quede atrapado dentro del diálogo.
- Asegúrate de que el lector de pantalla anuncie que es un diálogo.
- Verifica que el diálogo se cierre con la tecla Escape.
<button id="open-dialog">Abrir diálogo</button>
<div id="modal" role="dialog" aria-labelledby="dialog-title" aria-modal="true" hidden>
<h2 id="dialog-title">Términos y condiciones</h2>
<div>
<p>Contenido del diálogo...</p>
</div>
<button id="close-dialog">Cerrar</button>
</div>
Pruebas para menús desplegables
- Verifica que el estado expandido/colapsado sea anunciado.
- Comprueba que los elementos del menú sean navegables con teclado.
- Asegúrate de que el menú se cierre al presionar Escape.
<button aria-haspopup="true" aria-expanded="false" aria-controls="menu">
Opciones
</button>
<ul id="menu" role="menu" hidden>
<li role="menuitem" tabindex="-1">Opción 1</li>
<li role="menuitem" tabindex="-1">Opción 2</li>
<li role="menuitem" tabindex="-1">Opción 3</li>
</ul>
Pruebas para formularios
- Verifica que todos los campos tengan etiquetas asociadas.
- Comprueba que los errores de validación sean anunciados.
- Asegúrate de que los campos obligatorios sean identificados como tales.
<form>
<div>
<label for="name">Nombre:</label>
<input type="text" id="name" required aria-required="true">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" required aria-required="true"
aria-describedby="email-format">
<span id="email-format">Formato: ejemplo@dominio.com</span>
</div>
<button type="submit">Enviar</button>
</form>
Documentación de resultados y patrones de prueba
Es importante documentar sistemáticamente los resultados de las pruebas:
- Crea una matriz de pruebas que incluya:
- Componente probado
- Lectores de pantalla utilizados
- Navegadores probados
- Resultados esperados vs. obtenidos
- Problemas encontrados
- Establece patrones de prueba para componentes recurrentes:
Patrón de prueba: Botón con icono
-------------------------
1. Navegar al botón con Tab
2. Verificar que el lector de pantalla anuncia:
- La función del botón
- Cualquier estado relevante
3. Activar el botón con Enter o Espacio
4. Verificar que la acción se ejecuta
5. Verificar que cualquier cambio de estado es anunciado
Pruebas con usuarios reales
Las pruebas con usuarios reales que utilizan tecnologías asistivas proporcionan información invaluable:
- Recluta usuarios con diferentes niveles de experiencia en el uso de lectores de pantalla.
- Prepara escenarios de tareas específicos (por ejemplo, "Completa un formulario de contacto").
- Observa sin intervenir mientras los usuarios intentan completar las tareas.
- Recopila feedback sobre la experiencia general y los obstáculos encontrados.
Ciclo de mejora continua
Las pruebas de accesibilidad deben formar parte de un ciclo de mejora continua:
- Prueba la implementación actual.
- Identifica problemas y obstáculos.
- Implementa soluciones y mejoras.
- Vuelve a probar para verificar las correcciones.
<!-- Antes: Botón sin nombre accesible -->
<button><i class="icon-save"></i></button>
<!-- Después: Botón con nombre accesible -->
<button aria-label="Guardar documento"><i class="icon-save"></i></button>
Errores comunes detectados en pruebas
Durante las pruebas con lectores de pantalla, estos son algunos errores frecuentes que suelen detectarse:
- Falta de nombres accesibles en elementos interactivos.
- Estados no actualizados cuando cambia la interfaz.
- Orden de tabulación ilógico que dificulta la navegación.
- Regiones en vivo que no anuncian actualizaciones importantes.
- Contenido dinámico que aparece sin notificar al usuario.
<!-- Error: Menú que no actualiza su estado -->
<button onclick="toggleMenu()">Menú</button>
<!-- El estado expandido no se actualiza con JavaScript -->
<!-- Corrección -->
<button onclick="toggleMenu()" aria-expanded="false" aria-controls="main-menu">
Menú
</button>
<script>
function toggleMenu() {
const menu = document.getElementById('main-menu');
const button = document.querySelector('[aria-controls="main-menu"]');
const isExpanded = button.getAttribute('aria-expanded') === 'true';
menu.hidden = isExpanded;
button.setAttribute('aria-expanded', !isExpanded);
}
</script>
Lista de verificación para pruebas con lectores de pantalla
Utiliza esta lista de verificación para asegurar pruebas completas:
Navegación estructural:
¿Se anuncian correctamente los puntos de referencia (landmarks)?
¿La estructura de encabezados es lógica y navegable?
¿Los enlaces de salto (skip links) funcionan correctamente?
Componentes interactivos:
¿Todos los controles tienen nombres accesibles?
¿Se anuncian los estados actuales (expandido, seleccionado, etc.)?
¿Los componentes personalizados son operables con teclado?
Contenido dinámico:
¿Las actualizaciones importantes se anuncian mediante regiones en vivo?
¿Los mensajes de error son comunicados inmediatamente?
¿Los cambios de contexto son notificados adecuadamente?
Formularios:
¿Todos los campos tienen etiquetas asociadas?
¿Se anuncian los requisitos y restricciones de los campos?
¿Los errores de validación son claros y específicos?
Las pruebas con lectores de pantalla son una parte esencial del desarrollo web accesible. No solo ayudan a identificar problemas específicos, sino que también proporcionan una comprensión más profunda de cómo los usuarios con discapacidades experimentan tu sitio web. Esta comprensión es invaluable para crear experiencias verdaderamente inclusivas que funcionen para todos los usuarios, independientemente de sus capacidades o las herramientas que utilicen para acceder a la web.
Otras lecciones de HTML
Accede a todas las lecciones de HTML y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Html
Introducción Y Entorno
Doctype
Sintaxis Y Estructura
Elementos Y Etiquetas
Sintaxis Y Estructura
Atributos
Sintaxis Y Estructura
Anidación De Etiquetas
Sintaxis Y Estructura
Comentarios
Sintaxis Y Estructura
Encabezados (H1-h6)
Textos Y Enlaces
Enlace (A)
Textos Y Enlaces
Párrafo (P)
Textos Y Enlaces
Listas (Ul, Ol, Li)
Textos Y Enlaces
Imagen (Img)
Textos Y Enlaces
División (Div)
Organización De Contenido
Etiquetas Semánticas (Article, Section, Header, Footer, Nav, Aside)
Organización De Contenido
Tablas (Table, Tr, Td, Th)
Organización De Contenido
Formularios (Form, Input, Select, Textarea, Button)
Organización De Contenido
Imágenes Vectoriales (Svg)
Elementos Multimedia
Incrustación De Contenido (Iframe)
Elementos Multimedia
Audio (Audio)
Elementos Multimedia
Video (Video)
Elementos Multimedia
Estilo Incorporado (Style)
Metadatos Y Seo
Metadatos (Meta, Title, Link)
Metadatos Y Seo
Atributos De Aria
Metadatos Y Seo
Navegación Por Teclado
Metadatos Y Seo
Contraste Y Legibilidad
Optimización Html
Validación De Html
Optimización Html
Compatibilidad Con Navegadores
Optimización Html
Optimización De La Carga De La Página (Lazy Loading)
Optimización Html
Ejercicios de programación de HTML
Evalúa tus conocimientos de esta lección Atributos de ARIA con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Reto etiquetas semánticas HTML
Divisiones
Reto atributos ARIA en HTML
Reto trabajar con imágenes en HTML
Formularios
Encabezados
Reto metadatos en HTML
Validación de HTML
Navegación por teclado
Párrafos
Uso de DOCTYPE
Etiquetas semánticas
Contraste y legibilidad
Atributos
Reto formatear texto en HTML
Reto crear listas HTML
Metadatos
Comentarios
Incrustación de contenido (iframe)
Uso de elementos y etiquetas
Audio
Proyecto crear páginas HTML
Enlace
Video
Imágenes
DOCTYPE
Compatibilidad con navegadores
Reto crear tablas HTML
Introducción a HTML
Imágenes vectoriales
Anidación de etiquetas
Reto Validación HTML
Optimización de la carga de la página (Lazy loading)
Listas
Estilos
Reto de enlaces HTML
Atributos de ARIA
Reto geolocalización en HTML
Tablas
Reto LocalStorage en HTML
Uso de atributos
Elementos y etiquetas
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el propósito y la importancia de WAI-ARIA en la accesibilidad web.
- Identificar y aplicar roles, estados y propiedades ARIA para mejorar la semántica y funcionalidad de interfaces web.
- Implementar técnicas de navegación y orientación accesibles, como puntos de referencia, saltos de navegación y estructuras jerárquicas.
- Realizar pruebas efectivas con lectores de pantalla para validar la accesibilidad de componentes y páginas web.
- Seguir buenas prácticas y evitar errores comunes en la implementación de ARIA para garantizar una experiencia inclusiva.