Entendiendo los Roles de Accesibilidad en HTML
Los roles de accesibilidad indican a las tecnologías de asistencia qué es un elemento, no cómo se ve. Cuando un lector de pantalla encuentra un botón, necesita saber que es un botón, ya sea un elemento nativo <button> o un componente personalizado con role="button". Si esto se hace incorrectamente, millones de usuarios no podrán navegar tu interfaz de manera efectiva.
Esta guía explica cómo encajan los roles de accesibilidad en el árbol de accesibilidad más amplio, cuándo usar roles ARIA versus HTML semántico, y las mejores prácticas que mantienen tu código accesible y mantenible.
Puntos Clave
- Los roles de accesibilidad definen qué es un elemento para las tecnologías de asistencia, no su apariencia visual
- El árbol de accesibilidad contiene nombre, rol y valor/estado para cada elemento
- El HTML semántico proporciona roles implícitos—usa ARIA solo cuando HTML no sea suficiente
- Probar con tecnologías de asistencia reales asegura que tu implementación funcione para usuarios reales
Cómo Funcionan los Roles en el Árbol de Accesibilidad
Cada página web tiene dos árboles: el árbol DOM con el que estás familiarizado, y el árbol de accesibilidad que las tecnologías de asistencia realmente leen. El árbol de accesibilidad sigue un modelo simple: cada elemento tiene un nombre, rol y valor/estado.
<!-- DOM element -->
<button aria-pressed="true">Mute</button>
<!-- Accessibility tree representation -->
Name: "Mute"
Role: button
Value/State: pressed=true
El navegador construye automáticamente este árbol de accesibilidad desde tu HTML, mapeando elementos semánticos a sus roles implícitos. Un elemento <nav> se convierte en un landmark de navegación, un <button> se convierte en un widget de botón. Los roles ARIA te permiten modificar este árbol cuando el HTML nativo no es suficiente—pero deben ser tu último recurso, no tu primera opción.
Las Cuatro Categorías Principales de Roles
Roles Landmark (Puntos de Referencia)
Los roles landmark definen regiones de página para navegación. HTML5 moderno proporciona la mayoría de estos de forma nativa:
<header>→ rol banner (cuando no está dentro de<article>o<section>)<nav>→ rol navigation<main>→ rol main<aside>→ rol complementary<footer>→ rol contentinfo (cuando no está dentro de<article>o<section>)
Mejor práctica: Usa elementos HTML semánticos en lugar de <div role="navigation">. La redundancia de <nav role="navigation"> no añade valor—el elemento ya tiene ese rol implícitamente.
Roles Widget
Los roles widget describen controles interactivos. Estos son cruciales para componentes personalizados que no pueden usar elementos nativos:
<!-- Good: Custom tab interface -->
<div role="tablist">
<button role="tab" aria-selected="true">Settings</button>
<button role="tab" aria-selected="false">Profile</button>
</div>
<!-- Bad: Unnecessary ARIA -->
<button role="button">Click me</button> <!-- Redundant -->
Roles de Estructura de Documento
Estos roles describen la organización del contenido: encabezados, listas, artículos y separadores. Nuevamente, prefiere HTML semántico:
<!-- Prefer this -->
<article>
<h2>Article Title</h2>
</article>
<!-- Over this -->
<div role="article">
<div role="heading" aria-level="2">Article Title</div>
</div>
Roles Abstractos
Los roles abstractos como command o composite son plantillas fundamentales en WAI-ARIA. Nunca uses estos directamente—existen solo para que la especificación defina otros roles.
Discover how at OpenReplay.com.
Mejores Prácticas Modernas para Roles ARIA
Prefiere HTML Semántico Primero
La primera regla de ARIA es no usar ARIA. Los elementos HTML nativos vienen con soporte de teclado integrado, gestión de foco y semántica de accesibilidad:
<!-- Always prefer this -->
<button onclick="submit()">Submit</button>
<!-- Over this anti-pattern -->
<div role="button" tabindex="0" onclick="submit()">Submit</div>
La versión con <div> requiere JavaScript adicional para el soporte de teclado, estilo de foco y activación adecuada—trabajo que el botón nativo hace automáticamente.
Evita Roles Landmark Redundantes
Desde HTML5, añadir roles explícitos a elementos semánticos es innecesario y puede causar confusión:
<!-- Don't do this -->
<main role="main">
<nav role="navigation">
<header role="banner">
<!-- These elements already have implicit roles -->
<main>
<nav>
<header>
Nunca Sobrescribas Roles Interactivos Nativos
Cambiar el rol de un botón rompe su comportamiento esperado:
<!-- Never do this -->
<button role="heading">Section Title</button>
<!-- This breaks keyboard interaction and screen reader expectations -->
Cuándo Tienen Sentido los Roles Personalizados
Los componentes personalizados a veces genuinamente necesitan roles ARIA. Aquí hay casos de uso válidos:
Patrón de Diálogo Personalizado
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true">
<h2 id="dialog-title">Confirm Action</h2>
<button>Cancel</button>
<button>Confirm</button>
</div>
Interfaz de Pestañas Personalizada
<div role="tablist" aria-label="User settings">
<button role="tab" aria-selected="true" aria-controls="panel-1">General</button>
<button role="tab" aria-selected="false" aria-controls="panel-2">Privacy</button>
</div>
<div role="tabpanel" id="panel-1">General settings content</div>
Manejando Descripciones y Etiquetas
Para nombres y descripciones accesibles, sigue esta jerarquía:
- Texto visible (mejor para todos los usuarios)
aria-labelledby(referencia texto visible en otro lugar)aria-describedby(añade información suplementaria)aria-label(cuando el texto visible no es posible)
<button aria-describedby="help-text">Delete</button>
<span id="help-text">This action cannot be undone</span>
Nota: aria-description está emergiendo en WAI-ARIA 1.3 pero tiene soporte limitado. Mantente con aria-describedby para código en producción.
Anti-Patrones Comunes a Evitar
Botones basados en div: Crear <div role="button"> cuando <button> funciona perfectamente
Sopa de roles: Añadir roles a cada elemento “por si acaso”
Semántica conflictiva: <h2 role="button"> mezcla estructura e interacción
Roles redundantes: <nav role="navigation"> no añade valor
Probando tu Implementación
Siempre verifica los roles con tecnologías de asistencia reales. Las DevTools de los navegadores ahora incluyen inspectores del árbol de accesibilidad—úsalos para ver exactamente qué perciben los lectores de pantalla. Prueba con NVDA en Windows o VoiceOver en macOS para asegurar que tus roles se traduzcan en una experiencia utilizable.
Conclusión
Los roles de accesibilidad existen para describir qué es algo, no cómo se ve. El HTML semántico nativo proporciona la mayoría de los roles implícitamente—úsalo primero. Reserva los roles ARIA para componentes genuinamente personalizados donde HTML se queda corto. Cuando uses ARIA, asegúrate de que se alinee con las directrices WCAG y prueba con tecnologías de asistencia reales. Recuerda: ningún ARIA es mejor que un ARIA mal implementado.
Preguntas Frecuentes
No, cada elemento solo puede tener un atributo role. Si necesitas múltiples significados semánticos, considera reestructurar tu HTML para usar elementos anidados o elegir el rol único más apropiado que represente el propósito principal del elemento.
Absolutamente no. La mayoría de los elementos HTML tienen roles implícitos que funcionan perfectamente sin ARIA. Solo añade roles cuando crees widgets personalizados o cuando el HTML semántico no pueda expresar la funcionalidad necesaria. El uso excesivo de ARIA a menudo crea más problemas de accesibilidad de los que resuelve.
ARIA siempre gana sobre la semántica HTML nativa, lo que puede romper el comportamiento esperado. Por ejemplo, añadir role='heading' a un botón elimina toda la funcionalidad de botón para los lectores de pantalla. Por eso nunca debes sobrescribir roles de elementos interactivos nativos.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.