Skip to main content
Validación HTML

El elemento “button” no debe aparecer como descendiente de un elemento con el atributo “role=button”.

Acerca de este problema HTML

El atributo role="button" indica a las tecnologías de asistencia como los lectores de pantalla que un elemento se comporta como un botón — un widget utilizado para realizar acciones como enviar un formulario, abrir un diálogo o activar un comando. Cuando un elemento <button> aparece dentro de un elemento con role="button", el resultado es un control interactivo anidado. La especificación HTML prohíbe explícitamente esto porque el contenido interactivo no debe anidarse dentro de otro contenido interactivo.

Este anidamiento causa problemas reales. Los lectores de pantalla pueden anunciar el elemento exterior como un botón pero fallar en reconocer o alcanzar el <button> interior. Los usuarios de teclado pueden no ser capaces de enfocar o activar el control interior. Diferentes navegadores manejan la situación de forma inconsistente — algunos pueden ignorar completamente uno de los controles, otros pueden activar eventos en el elemento incorrecto. El resultado final es una interfaz que está rota para muchos usuarios.

Este problema surge comúnmente en algunos escenarios:

  • A un <div> o <span> se le asigna role="button" y después se coloca un <button> dentro para propósitos de estilo o manejo de clics.
  • Una librería de componentes envuelve contenido en un contenedor role="button", y un desarrollador añade un <button> dentro sin darse cuenta del conflicto.
  • Una tarjeta personalizada o elemento de lista se hace clickeable con role="button", pero también contiene botones de acción dentro.

La solución depende de tu intención. Si el elemento exterior es el control interactivo previsto, elimina el <button> interior y maneja las interacciones en el elemento exterior. Si el <button> interior es el control previsto, elimina role="button" del ancestro. Si ambos necesitan ser clickeables independientemente, reestructura el marcado para que ninguno sea descendiente del otro.

Ejemplos

❌ Incorrecto: <button> dentro de un elemento con role="button"

<div role="button" tabindex="0" onclick="handleClick()">
  <button type="button">Click me</button>
</div>

Esto es inválido porque el <button> es descendiente del <div> que tiene role="button".

✅ Opción de corrección 1: Usar solo el elemento <button>

Si el <button> interior es el control real, elimina role="button" del contenedor:

<div>
  <button type="button" onclick="handleClick()">Click me</button>
</div>

✅ Opción de corrección 2: Usar solo el elemento exterior role="button"

Si el elemento exterior es el control interactivo previsto, elimina el <button> interior:

<div role="button" tabindex="0" onclick="handleClick()">
  Click me
</div>

Ten en cuenta que cuando usas role="button" en un elemento que no es <button>, también debes manejar eventos de teclado (Enter y Espacio) manualmente. Un <button> nativo proporciona esto automáticamente, así que prefiere la opción 1 cuando sea posible.

❌ Incorrecto: Tarjeta clickeable que contiene botones de acción

<div role="button" tabindex="0" class="card">
  <h3>Item title</h3>
  <p>Description text</p>
  <button type="button">Delete</button>
</div>

✅ Corrección: Separar el enlace de la tarjeta de los botones de acción

<div class="card">
  <h3><button type="button" class="card-link">Item title</button></h3>
  <p>Description text</p>
  <button type="button">Delete</button>
</div>

En este enfoque, la acción principal de la tarjeta se maneja mediante un <button> en el título, mientras que el botón “Delete” permanece como un control independiente. Ninguno está anidado dentro del otro, y ambos son accesibles para usuarios de teclado y lectores de pantalla.

Encuentra problemas como este automáticamente

Rocket Validator escanea miles de páginas en segundos, detectando problemas de HTML en todo tu sitio web.

Ayúdanos a mejorar nuestras guías

¿Te ha sido útil esta guía?

¿Listo para validar tus sitios?
Inicia tu prueba gratuita hoy.