Hice una auditoría de accesibilidad en el sitio de marketing de un cliente el año pasado. La puntuación de Lighthouse era de 98. Pero cuando activé VoiceOver y recorrí la navegación con la tecla Tab, todos los iconos eran invisibles. Siete iconos SVG — inicio, buscador, carrito, cuenta, menú, cerrar, flecha — no se anunciaban de ninguna forma. Solo silencio entre los enlaces de texto. Ahí me di cuenta: casi nadie enseña a los diseñadores cómo hacer que los SVG sean accesibles. Esto es lo que he aprendido desde entonces.
De forma predeterminada, los lectores de pantalla tratan de forma inconsistente a los elementos SVG sin atributos de accesibilidad. Algunos lo ignoran por completo. Otros anuncian «imagen» sin ningún contexto. Algunos leen el nombre del archivo si se cargó mediante <img>. Ninguna de estas conductas es útil. Un icono de buscador que se anuncia como «search-icon.svg» podría decirse que es peor que uno que no dice nada: al menos el silencio no interrumpe el flujo de navegación.
La especificación SVG Accessibility API Mappings del W3C define cómo se deben mapear los SVG a las API de accesibilidad de las plataformas, pero su implementación en los navegadores es inconsistente. Depender de los ajustes por defecto significa que probablemente estés lanzando contenido con accesibilidad rota.
Después de hacer pruebas con VoiceOver (macOS), NVDA (Windows) y JAWS (Windows), me quedé con tres patrones que funcionan de forma fiable. Cuál usar depende de la función que cumpla el SVG.
Si el SVG es puramente decorativo — un patrón de fondo, un separador, una ilustración que no aporta información — ocúltalo completamente de los lectores de pantalla:
<svg aria-hidden="true" focusable="false"> <!-- decorative shapes --> </svg>
Cuándo lo uso: Separadores de sección, manchas de fondo, ilustraciones decorativas, iconos repetidos que ya tienen una etiqueta de texto justo al lado.
Si el SVG transmite significado — una gráfica, un diagrama, una ilustración con contenido instructivo — añade un elemento <title> y haz referencia a él con aria-labelledby:
<svg aria-labelledby="chart-title" role="img"> <title id="chart-title">Revenue grew 34% from Q1 to Q4 2025</title> <!-- chart paths --> </svg>
Esto garantiza que el lector de pantalla anuncie el contenido del título en lugar de leer las coordenadas de las rutas o quedarse en silencio.
Si el SVG se puede clicar — un botón con icono, un enlace — usa aria-label en el elemento interactivo, no en el propio SVG:
<button aria-label="Open shopping cart (3 items)">
<svg aria-hidden="true" focusable="false">
<!-- cart icon paths -->
</svg>
<span class="sr-only">3 items in cart</span>
</button>
Uso aria-hidden="true" en el SVG que está dentro de un botón porque el aria-label del botón ya describe la acción. Anunciar ambos sería redundante. El texto con la clase .sr-only proporciona una alternativa visible al enfocar el elemento para usuarios que navegan con teclado pero no usan un lector de pantalla.
Pruebo todos los sistemas de iconos que construyo con tres lectores de pantalla, en este orden:
Si un icono pasa las pruebas en VoiceOver y NVDA, probablemente funcione bien. No tengo JAWS (cuesta 95 dólares al año), pero un cliente probó mi trabajo con él una vez y no informó de ningún error con estos patrones.
aria-hidden="true"<title> + aria-labelledbyaria-label en el botón/enlace, oculta el SVG<img>? → Añade siempre texto alt<use> necesita su propio aria-label¿Necesitas exportar SVGs accesibles? Usa SVG2PNG para convertir SVGs a PNG para clientes de correo electrónico y aplicaciones heredadas que no admiten SVG en línea — y agrega siempre texto alternativo en la etiqueta <img> resultante.