Semántica HTML nativa antes de ARIA | Nicolás Garzón
HTML
Copiar < button type = " button" > Guardar</ button> HTML
Copiar < div role = " button" tabindex = " 0" > Guardar</ div> Cuando existe un elemento nativo con la semántica y comportamiento necesarios, utilízalo.
Texto
Copiar acción → button
navegación → a con href
encabezado → h1–h6
lista → ul/ol + li
campo → input/select/textarea + label
tabla → table/th/tdMuchos elementos ya exponen roles:
HTML
Copiar < nav> ...</ nav>
< main> ...</ main>
< button> ...</ button> Añadir roles redundantes no suele aportar:
HTML
Copiar < nav role = " navigation" > ...</ nav>
< button role = " button" > ...</ button> Puede aumentar ruido y crear incompatibilidades si el role contradice el elemento.
HTML
Copiar < a role = " button" href = " /delete" > Eliminar</ a> El role puede cambiar cómo se anuncia, pero el elemento conserva comportamiento de enlace. La combinación puede confundir teclado y navegación.
Usa un button para la acción.
HTML
Copiar < div aria-expanded = " true" > Contenido</ div> El estado no tiene sentido sin un control o patrón que pueda expandirse.
ARIA incorrecto puede ocultar semántica nativa, crear nombres erróneos o anunciar estados inexistentes.
ARIA aporta cuando JavaScript mantiene un componente:
HTML
Copiar < button
type = " button"
aria-expanded = " false"
aria-controls = " filters"
>
Filtros
</ button>
< section id = " filters" hidden > ...</ section> Texto
Copiar aria-expanded="true"
hidden eliminadoAmbos estados deben permanecer sincronizados.
HTML
Copiar < svg aria-hidden = " true" > ...</ svg> Oculta contenido del árbol accesible, no necesariamente de la pantalla.
Elementos enfocables.
Contenido esencial.
Un parent que contiene controles utilizables.
Un elemento visible pero aria-hidden puede crear una experiencia distinta para usuarios.
HTML
Copiar < table role = " presentation" > ...</ table> Elimina semántica estructural cuando el elemento se usa solo para layout heredado.
No lo uses en una tabla de datos: perdería encabezados y relaciones.
Algunos roles de la especificación sirven como categorías y no deben asignarse directamente. Utiliza roles concretos documentados para autoría.
Un tablist necesita tabs y tabpanels relacionados; un menu ARIA requiere navegación y comportamiento de aplicación.
HTML
Copiar < div role = " menu" > ...</ div>
Arrow navigation.
Gestión de foco.
Activación.
Cierre con Escape.
Para navegación de sitio, una lista de enlaces suele ser mejor que un menu ARIA.
HTML
Copiar < button aria-label = " Cerrar" >
< svg aria-hidden = " true" > ...</ svg>
</ button> Es útil en icon buttons. En un botón con texto visible, deja que el texto proporcione el nombre salvo una razón clara.
Añade descripción; no cambia función ni comportamiento.
HTML
Copiar < button aria-describedby = " delete-warning" >
Eliminar proyecto
</ button>
< p id = " delete-warning" > Esta acción no se puede deshacer.</ p> Antes de construir uno, pregunta:
¿Existe elemento nativo?
¿Puede estilizarse adecuadamente?
¿Qué teclado espera el patrón?
¿Qué estados y relaciones necesita?
¿Cómo se anuncia el cambio?
¿Funciona con touch, zoom y high contrast?
HTML
Copiar < button class = " unstyled" > Guardar</ button> Puede conservar semántica, pero si CSS elimina foco, contraste o tamaño de objetivo, la experiencia sigue siendo inaccesible.
Nativo es una base, no una garantía automática.
Componentes pueden ocultar el elemento final:
TypeScript
Copiar < Tabs / >
< Select / >
< Dialog / >
DOM.
Accessibility tree.
Teclado.
Foco.
Estados ARIA.
Comportamiento sin mouse.
HTML
Copiar < button
type = " button"
aria-expanded = " false"
aria-controls = " project-details"
>
Ver detalles
</ button>
< div id = " project-details" hidden >
...
</ div> El button aporta activación; ARIA comunica el estado de una relación dinámica.
Crear buttons con div.
Añadir roles redundantes.
Cambiar el role sin cambiar el comportamiento.
Usar aria-expanded sin contenido controlado.
Ocultar controles con aria-hidden.
Aplicar presentation a estructuras de datos.
Crear menu ARIA para navegación normal.
Esperar que ARIA implemente teclado.
Confiar en el nombre de un componente.
Eliminar foco visible de controles nativos.
HTML nativo es la primera opción.
ARIA cambia exposición, no implementa comportamiento.
Los roles implícitos no necesitan repetirse.
Estados deben reflejar la UI real.
Aria-hidden no es una herramienta visual.
Patrones complejos exigen estructura y teclado completos.
Un control nativo todavía necesita buenos estilos y contenido.
Evalúa el DOM final de los frameworks.
¿Por qué role="button" no convierte completamente un div en botón?
Respuesta Porque solo modifica la semántica expuesta; no añade activación con Enter/Espacio, foco, disabled, envío de formularios ni otros comportamientos nativos.
Nombres y descripciones accesibles explica cómo se calcula la identidad de elementos y controles.