Acerca de esta regla de accesibilidad
La especificación WAI-ARIA define una jerarquía estricta para muchos roles. Algunos roles solo tienen significado cuando aparecen como hijos de roles padre específicos. Por ejemplo, un tab debe pertenecer a un tablist, un listitem debe pertenecer a un list o group, y un menuitem debe pertenecer a un menu o menubar. Cuando faltan estas relaciones padre-hijo, el role se convierte en semánticamente huérfano — las tecnologías de asistencia como los lectores de pantalla no pueden comunicar el contexto, posición o propósito del elemento al usuario.
Por qué esto importa
Esta regla se relaciona con el Criterio de Conformidad 1.3.1 de WCAG 2.0/2.1/2.2: Información y Relaciones (Nivel A), que requiere que la información, estructura y relaciones transmitidas visualmente también estén disponibles programáticamente. Cuando un role ARIA carece de su padre requerido, la relación estructural se pierde en el árbol de accesibilidad.
Los usuarios más afectados incluyen:
- Usuarios ciegos y sordociegos que dependen de lectores de pantalla. Sin el role padre correcto, los lectores de pantalla no pueden anunciar contexto como “elemento 3 de 5 en una lista” o “pestaña 2 de 4”.
- Usuarios con discapacidades motoras que dependen de tecnologías de asistencia para la navegación. Los roles padre faltantes pueden romper los patrones de interacción por teclado esperados para widgets compuestos como menús, listas de pestañas y árboles.
El impacto en el usuario es crítico — un role huérfano puede hacer que todo un widget sea inutilizable para usuarios de tecnologías de asistencia.
Roles padre requeridos comunes
Aquí tienes algunos roles usados frecuentemente y sus padres requeridos:
| Role Hijo | Role(s) Padre Requerido(s) |
|---|---|
listitem |
list o group |
tab |
tablist |
tabpanel |
(asociado a través del patrón tablist) |
menuitem, menuitemcheckbox, menuitemradio |
menu, menubar, o group |
treeitem |
tree o group |
row |
table, grid, rowgroup, o treegrid |
cell, gridcell |
row |
columnheader, rowheader |
row |
option |
listbox o group |
Cómo solucionar el problema
-
Envuelve el elemento en su role padre requerido. La solución más simple es asegurar que la estructura DOM refleje la jerarquía requerida. Coloca el elemento dentro de un contenedor que tenga el role padre correcto.
-
Usa
aria-ownscuando la estructura DOM no coincida. Si el elemento hijo no puede ser un descendiente DOM del padre (p. ej., debido a limitaciones de diseño), puedes usararia-ownsen el elemento padre para establecer la relación programáticamente. El atributoaria-ownsle dice a las tecnologías de asistencia que el elemento referenciado debe tratarse como un hijo, independientemente de su posición en el DOM. -
Consulta la especificación WAI-ARIA para el role específico que estés usando para confirmar qué roles padre son requeridos.
Ejemplos
Incorrecto: listitem Sin un padre list
El role listitem requiere un padre con role="list" o role="group", pero aquí está directamente dentro de un div simple:
<div>
<div role="listitem">Manzanas</div>
<div role="listitem">Plátanos</div>
<div role="listitem">Cerezas</div>
</div>
Correcto: listitem Dentro de un padre list
<div role="list">
<div role="listitem">Manzanas</div>
<div role="listitem">Plátanos</div>
<div role="listitem">Cerezas</div>
</div>
Incorrecto: tab Sin un padre tablist
<div>
<button role="tab" aria-selected="true">Pestaña 1</button>
<button role="tab" aria-selected="false">Pestaña 2</button>
</div>
Correcto: tab Dentro de un padre tablist
<div role="tablist">
<button role="tab" aria-selected="true">Pestaña 1</button>
<button role="tab" aria-selected="false">Pestaña 2</button>
</div>
Correcto: Usando aria-owns cuando la estructura DOM difiere
Cuando las limitaciones de diseño previenen anidar el hijo dentro del padre en el DOM, usa aria-owns para establecer la relación:
<div role="tablist" aria-owns="tab1 tab2">
<!-- Las pestañas están en otra parte del DOM debido a necesidades de diseño -->
</div>
<div id="tab1" role="tab" aria-selected="true">Pestaña 1</div>
<div id="tab2" role="tab" aria-selected="false">Pestaña 2</div>
Incorrecto: menuitem Fuera de un menu
<div>
<button role="menuitem">Cortar</button>
<button role="menuitem">Copiar</button>
<button role="menuitem">Pegar</button>
</div>
Correcto: menuitem Dentro de un menu
<div role="menu">
<button role="menuitem">Cortar</button>
<button role="menuitem">Copiar</button>
<button role="menuitem">Pegar</button>
</div>
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.