Normativas · ARIA

Rol Control

button

Marca un elemento como botón — un control que desencadena una acción al activarse. Use primero el elemento HTML nativo <button>; recurra a role="button" en un <div> o <span> solo cuando no sea posible usar el elemento nativo.

Cuándo utilizarlo

Casi nunca — use el elemento nativo <button>. El elemento nativo gestiona de forma gratuita el foco, la activación con las teclas Espacio e Intro, el estado deshabilitado y la semántica de envío de formularios. Recurrir a role="button" en un <div> implica reimplementar todo eso, y la mayoría de los autores no lo hace correctamente.

Los casos legítimos para role="button" son limitados:

  • Se trabaja con un sistema de diseño de terceros que incluye componentes que no son botones.
  • Se está creando contenido en un entorno donde <button> no está disponible (algunas plantillas de CMS heredadas).
  • Se está adaptando un <div> por accesibilidad a corto plazo mientras se planifica una refactorización.

Si se utiliza role="button", también es obligatorio:

  • Hacer el elemento enfocable con tabindex="0".
  • Conectar keydown para Enter y Space (con event.preventDefault() en Espacio para evitar el desplazamiento de la página).
  • Gestionar manualmente el estado deshabilitado mediante aria-disabled="true" e impedir que los manejadores de clic se activen.

Botones de alternancia

Si el botón es de alternancia (silenciar / activar, reproducir / pausar, seguir / dejar de seguir), establezca aria-pressed en "true" o "false". Los lectores de pantalla anuncian el estado junto con la etiqueta: «Silenciar, botón de alternancia, no presionado».

Errores habituales

  • <div onclick="…">Enviar</div> — no es enfocable, no es operable con teclado, no tiene rol. Los usuarios de ratón pueden usarlo; nadie más puede.
  • <a href="#" onclick="…"> que simula ser un botón. El navegador lo trata como un enlace, el lector de pantalla lo anuncia como enlace y el usuario espera una navegación.
  • role="button" sin tabindex="0" — el lector de pantalla anuncia «botón» pero el teclado no puede alcanzarlo.
  • Botones personalizados que responden a Intro pero no a Espacio.
  • Botones sin nombre accesible — los botones que solo contienen un icono sin aria-label son el error individual más común que detecta axe-core.

Ejemplo

<!-- Preferido -->
<button type="button" aria-pressed="false">Mute</button>

<!-- Solo cuando <button> es imposible -->
<div
  role="button"
  tabindex="0"
  aria-pressed="false"
  onclick="toggleMute()"
  onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); toggleMute(); }"
>
  Mute
</div>