Acerca de esta regla de accesibilidad
Cuando los usuarios navegan por una página web usando un teclado o lector de pantalla, se mueven a través de lo que se llama el “orden de foco” — la secuencia de elementos interactivos que reciben foco. Cada vez que un elemento recibe foco, un lector de pantalla anuncia su rol (por ejemplo, “button,” “link,” “checkbox”) junto con su nombre y estado. Este rol es la forma en que los usuarios entienden qué tipo de control han encontrado y qué acciones pueden realizar.
Si un elemento enfocable no tiene rol — por ejemplo, un <div> hecho enfocable con tabindex="0" — el lector de pantalla puede leer el contenido de texto del elemento pero no proporcionará contexto sobre qué es el elemento. El usuario escucha texto pero no tiene idea de si debe presionar Enter, escribir entrada, o alternar un estado. De manera similar, si un elemento tiene un rol inapropiado como presentation o un rol abstracto como widget, las tecnologías de asistencia no pueden transmitir patrones de interacción significativos.
Este problema afecta principalmente a usuarios ciegos y sordociegos que dependen de lectores de pantalla, y usuarios con discapacidades motoras que navegan exclusivamente con un teclado. Sin información adecuada del rol, estos usuarios no pueden interactuar de manera eficiente o precisa con los controles de la página.
Por qué importan los roles
Esta regla se alinea con las mejores prácticas de accesibilidad recomendadas por Deque y RGAA. Aunque no se mapea a un solo criterio de éxito de WCAG, apoya varios principios:
- WCAG 4.1.2 (Name, Role, Value): Todos los componentes de la interfaz de usuario deben exponer su rol, nombre y estado a las tecnologías de asistencia.
- WCAG 2.1.1 (Keyboard): Toda funcionalidad debe ser operable a través de un teclado. La información significativa del rol es esencial para que los usuarios de teclado entiendan qué pueden hacer con un elemento enfocado.
Cuando un elemento en el orden de foco tiene un rol válido y apropiado, los lectores de pantalla pueden:
- Anunciar el tipo de control (por ejemplo, “button,” “textbox,” “menu item”).
- Informar a los usuarios de las interacciones disponibles (por ejemplo, “press Enter to activate,” “use arrow keys to navigate”).
- Comunicar cambios de estado (por ejemplo, “checked,” “expanded”).
Cómo solucionar el problema
Usa elementos HTML nativos primero
La solución más simple y confiable es usar el elemento HTML nativo correcto. Los elementos nativos como <button>, <a>, <input> y <select> vienen con roles integrados, comportamiento de teclado y soporte de accesibilidad — no se necesitan atributos adicionales.
Agrega roles ARIA a widgets personalizados
Si debes usar un elemento no semántico (como <div> o <span>) como un control interactivo, necesitas:
-
Agregar un atributo
roleapropiado (por ejemplo,role="button",role="checkbox",role="tab"). - Asegurar que todas las interacciones de teclado requeridas estén implementadas.
-
Gestionar estados y propiedades ARIA (por ejemplo,
aria-checked,aria-expanded).
Evita roles abstractos
ARIA define roles abstractos como command, input, landmark, range, section, sectionhead, select, structure y widget. Estos existen solo como parte de la taxonomía de roles y nunca deben usarse directamente en elementos. Siempre usa un rol concreto en su lugar.
Elimina tabindex de elementos no interactivos cuando sea posible
Si un elemento no necesita ser interactivo, considera eliminar su atributo tabindex completamente para que no aparezca en el orden de foco.
Roles apropiados para contenido interactivo
Aquí hay algunas categorías comunes de roles válidos para elementos enfocables:
-
Roles de widget:
button,checkbox,combobox,link,listbox,menu,menuitem,menuitemcheckbox,menuitemradio,option,radio,scrollbar,slider,spinbutton,switch,tab,textbox,treeitem -
Roles de widget compuesto:
grid,menubar,radiogroup,tablist,toolbar,tree,treegrid -
Roles de landmark:
banner,complementary,contentinfo,main,navigation,region,search -
Roles de estructura de documento:
dialog,alertdialog,application,document,log,status,timer,tooltip
Ejemplos
Incorrecto: elemento enfocable sin rol
Este <div> puede recibir foco, pero un lector de pantalla no anunciará qué es:
<div tabindex="0" onclick="submitForm()">
Submit
</div>
Un usuario de lector de pantalla escuchará “Submit” pero no sabrá que está destinado a ser un botón.
Correcto: usar un botón HTML nativo
<button type="button" onclick="submitForm()">
Submit
</button>
El elemento <button> tiene un rol button integrado. El lector de pantalla anuncia “Submit, button.”
Correcto: agregar un rol ARIA a un widget personalizado
Si no puedes usar un <button> nativo, agrega el rol apropiado y soporte de teclado:
<div role="button" tabindex="0" onclick="submitForm()" onkeydown="handleKeydown(event)">
Submit
</div>
Ahora el lector de pantalla anuncia “Submit, button.” También debes implementar onkeydown para manejar las pulsaciones de teclas Enter y Space, ya que un <div> no soporta nativamente esas interacciones.
Incorrecto: usar un rol abstracto
<div role="command" tabindex="0">
Save
</div>
El rol command es abstracto y no debe usarse en elementos. Las tecnologías de asistencia no lo reconocerán como un rol válido.
Correcto: reemplazar el rol abstracto
<div role="button" tabindex="0" onkeydown="handleKeydown(event)">
Save
</div>
Incorrecto: rol no interactivo en un elemento enfocable
<span role="paragraph" tabindex="0" onclick="openMenu()">
Options
</span>
El rol paragraph no es interactivo. El elemento no se comportará como se espera para los usuarios de tecnología de asistencia, y puede que ni siquiera reciba foco en algunos lectores de pantalla.
Correcto: usar un rol de widget apropiado
<span role="button" tabindex="0" onclick="openMenu()" onkeydown="handleKeydown(event)">
Options
</span>
Incorrecto: checkbox personalizado enfocable sin rol
<div tabindex="0" class="custom-checkbox" onclick="toggleCheck(this)">
Accept terms
</div>
Correcto: checkbox personalizado con rol y estado apropiados
<div role="checkbox" tabindex="0" aria-checked="false" onclick="toggleCheck(this)" onkeydown="handleKeydown(event)">
Accept terms
</div>
El role="checkbox" le dice al lector de pantalla que esto es un checkbox, y aria-checked comunica su estado actual. Recuerda actualizar aria-checked en tu JavaScript cuando el estado cambie.
Ayúdanos a mejorar nuestras guías
Detecta problemas de accesibilidad automáticamente
Rocket Validator escanea miles de páginas con Axe Core y el W3C Validator, encontrando problemas de accesibilidad en todo tu sitio web.