El rol img y cuándo aplicarlo
Qué le hace role img al árbol de accesibilidad, por qué colapsa el subárbol, los roles del módulo de gráficos de ARIA, y los tres casos donde no debes ponerlo.
Qué le hace al árbol
El árbol de accesibilidad es la estructura que el navegador construye a partir del DOM y que las tecnologías de asistencia recorren. Sin role="img", un svg en línea aporta al árbol un nodo con el rol graphics-document, y sus descendientes también aparecen: cada path, cada g, cada text es un nodo.
Eso produce dos problemas.
Ruido. Un gráfico con quinientas formas genera quinientos nodos que el usuario tiene que atravesar. Con la navegación por elementos de un lector de pantalla, recorrer un gráfico se convierte en un castigo.
Anuncios sin sentido. Los elementos text de un SVG sí tienen contenido, así que se anuncian. Un gráfico de barras con etiquetas de eje anuncia los números sueltos, sin contexto ni orden. «Cero. Veinte. Cuarenta. Sesenta. Enero. Febrero.» No es una alternativa textual, es un desguace.
role="img" resuelve las dos: declara que el elemento es una imagen, y por las reglas de cálculo del árbol de accesibilidad, los descendientes de un elemento con rol img no se exponen. El nodo es una hoja. Lo único que el usuario percibe es el rol y el nombre accesible.
De ahí sale la regla más importante de este nivel: si pones role="img", tienes que poner un nombre accesible. Un SVG con role="img" y sin nombre es un agujero: se anuncia como «imagen» sin más, y todo lo que había dentro ha desaparecido. Es estrictamente peor que no poner nada.
<!-- Correcto --><svg role="img" aria-labelledby="t" viewBox="0 0 24 24"> <title id="t">Alerta de temperatura alta</title> <path d="..." /></svg><!-- Peor que no hacer nada --><svg role="img" viewBox="0 0 24 24"> <path d="..." /></svg>El módulo de gráficos de ARIA
Existe una especificación, el módulo de gráficos de WAI-ARIA, que define tres roles pensados para esto:
| Rol | Para qué |
|---|---|
graphics-document |
Un gráfico completo con estructura navegable |
graphics-object |
Una parte con significado dentro del gráfico |
graphics-symbol |
Un símbolo que representa un concepto, sin estructura interna |
La idea es buena: un gráfico sería un graphics-document, cada serie un graphics-object, y cada marcador un graphics-symbol. El usuario podría navegar la estructura en lugar de recibir un bloque de texto.
El problema es el soporte. Los lectores de pantalla implementan estos roles de forma parcial e inconsistente, y en muchas combinaciones se comportan como roles genéricos. Construir la accesibilidad de un gráfico sobre ellos es construir sobre algo que en la mayoría de los casos no se anuncia.
Recomendación práctica: usa role="img" con un buen nombre y una alternativa textual completa, y considera los roles de gráficos como una mejora progresiva encima, no como la base. Cuando el soporte madure, el gráfico ya funcionaba.
Los tres casos donde no debes ponerlo
Uno: cuando el SVG es interactivo. Si dentro hay elementos que se pueden enfocar, pulsar o navegar (barras que responden al teclado, una leyenda que filtra), role="img" los borra del árbol de accesibilidad y quedan inalcanzables. Un elemento con rol img no puede tener descendientes interactivos expuestos.
En ese caso el SVG no lleva role="img", y cada elemento interactivo lleva su propio rol (button, checkbox), su nombre y su gestión de foco.
Dos: cuando el SVG contiene texto que debe ser accesible por sí mismo. Un diagrama con etiquetas que forman parte del contenido, no de la decoración. Aquí role="img" con un nombre que resuma sería una pérdida de información. La alternativa es dejar el SVG sin rol y estructurar el contenido con text bien organizado, o mejor, poner el texto en HTML.
Tres: cuando el SVG es decorativo. Entonces no lleva role="img": lleva aria-hidden="true", que es otra cosa. Poner role="img" a un adorno lo convierte en un elemento anunciable que no aporta nada.
Un resumen operativo
Tres preguntas en orden, y la respuesta sale sola.
¿El SVG aporta información que no está en otro sitio? Si no, es decorativo: aria-hidden="true" y punto.
¿Es interactivo por dentro? Si sí, no lleva role="img"; cada parte interactiva lleva su propia semántica.
Si aporta información y no es interactivo: role="img" más un nombre accesible que transmita esa información. Y si la información es densa (un gráfico de datos), además una alternativa textual completa fuera del SVG.