Normativas · ARIA

Propiedad Relación

aria-activedescendant

En un widget compuesto, señala el ID del descendiente que está activo en ese momento. El foco del DOM permanece en el contenedor mientras un foco virtual se desplaza entre los elementos hijos. Alternativa al roving tabindex para listboxes, comboboxes y grids.

Cuándo utilizarlo

En un widget compuesto donde se desea un único punto de tabulación pero el usuario aún necesita desplazar un resaltado entre múltiples elementos — un campo combobox con un popup de listbox, un listbox con tabulación única, treegrid, datagrid. El foco del DOM permanece en el elemento contenedor (el campo de texto, el listbox, el grid). Cuando el usuario pulsa las teclas de flecha, se actualiza aria-activedescendant con el ID del elemento hijo recién destacado, y las tecnologías de asistencia lo anuncian como si el foco se hubiese desplazado allí.

El patrón alternativo es el roving tabindex: mover el foco del DOM efectivamente y ajustar los valores de tabindex. Se debe elegir aria-activedescendant cuando mantener el foco del navegador en el contenedor simplifica el código — por lo general porque el contenedor es también donde el usuario escribe o donde se asocian los atajos de teclado.

Cómo se comporta

El valor es un único ID de elemento — nunca una lista. El elemento referenciado debe ser descendiente del contenedor que tiene el atributo aria-activedescendant (o estar vinculado mediante aria-owns). Cuando el valor cambia, la posición del «foco virtual» en el árbol de accesibilidad se desplaza a ese elemento y las tecnologías de asistencia anuncian su etiqueta, rol y estado.

Dos aspectos siguen siendo responsabilidad del desarrollador:

  • Estilos visuales. Las tecnologías de asistencia saben dónde está el foco virtual, pero el navegador no dibuja un anillo de foco sobre el descendiente. Es necesario añadir el CSS de resaltado propio, generalmente mediante una clase que se activa de forma sincronizada.
  • Desplazamiento. Si el descendiente activo está fuera del área visible, se debe desplazar la vista mediante programación; el navegador no lo hace automáticamente.

Cuando el popup se cierra o el widget pierde el foco, se debe limpiar aria-activedescendant con una cadena vacía o eliminar el atributo.

Errores frecuentes

  • Apuntar a un ID que no es descendiente del contenedor y no está vinculado mediante aria-owns. La tecnología de asistencia ignora la referencia.
  • Mezclar patrones: aplicar tabindex="0" al descendiente y establecer aria-activedescendant en el contenedor al mismo tiempo. Debe elegirse una única estrategia de foco; usar ambas genera conflictos.
  • Olvidar actualizar el resaltado visual cuando cambia el atributo — los usuarios con visión no perciben el movimiento mientras los usuarios de tecnologías de asistencia sí lo escuchan.
  • Dejar un ID obsoleto después de que la opción se haya eliminado de la lista (por ejemplo, en resultados filtrados de un combobox).
  • Actualizar aria-activedescendant al pasar el ratón. El atributo debe reflejar únicamente el elemento activo mediante teclado.
  • Establecerlo en un elemento cuyo árbol de accesibilidad no contiene al descendiente (se olvidó aria-owns para una lista en un portal).

Ejemplo

<label for="fruit">Fruta</label>
<input
  id="fruit"
  role="combobox"
  type="text"
  aria-controls="fruit-listbox"
  aria-expanded="true"
  aria-activedescendant="fruit-2"
  autocomplete="off"
>
<ul id="fruit-listbox" role="listbox">
  <li id="fruit-1" role="option">Apple</li>
  <li id="fruit-2" role="option" class="is-active">Banana</li>
  <li id="fruit-3" role="option">Cherry</li>
</ul>