Acerca de este problema HTML
El estándar HTML living define tanto <a> como <button> como contenido interactivo. Los elementos de contenido interactivo no pueden ser descendientes de otros elementos de contenido interactivo. Cuando colocas un <button> dentro de un <a>, creas una situación ambigua: ¿debería un clic activar la navegación del enlace o la acción del botón? Los navegadores manejan esto de manera inconsistente, lo que lleva a un comportamiento impredecible para todos los usuarios.
Esto es especialmente problemático para la accesibilidad. Los lectores de pantalla y otras tecnologías de asistencia dependen de una jerarquía de elementos clara y bien definida para comunicar el propósito de los controles a los usuarios. Un botón anidado dentro de un enlace crea una experiencia confusa — el usuario puede escuchar tanto un enlace como un botón anunciados, sin una indicación clara de lo que realmente pasará cuando lo activen. La navegación por teclado también puede fallar, ya que el comportamiento del foco se vuelve poco confiable.
La misma regla se aplica a elementos que no son literalmente <button> pero tienen role="button". Por ejemplo, un <span role="button"> dentro de una etiqueta <a> desencadena el mismo error de validación, porque el role ARIA lo hace semánticamente interactivo.
Cómo solucionarlo
La solución depende de lo que estés tratando de lograr:
-
Si el elemento debe navegar a una URL, usa un elemento
<a>y dale estilo para que parezca un botón con CSS. Elimina completamente el<button>. -
Si el elemento debe realizar una acción JavaScript, usa un elemento
<button>y quita el<a>que lo envuelve. Adjunta la acción mediante un event listener. - Si necesitas tanto un enlace como un botón, colócalos lado a lado como hermanos en lugar de anidar uno dentro del otro.
Ejemplos
❌ Inválido: Botón dentro de un enlace
<a href="/dashboard">
<button>Ir al Panel</button>
</a>
✅ Solucionado: Enlace con estilo de botón
Si el objetivo es la navegación, usa un enlace y dale estilo con CSS:
<a href="/dashboard" class="btn">Ir al Panel</a>
.btn {
display: inline-block;
padding: 8px 16px;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 4px;
}
✅ Solucionado: Botón con una acción JavaScript
Si el objetivo es desencadenar una acción (como navegar programáticamente), usa un botón por sí solo:
<button type="button" onclick="window.location.href='/dashboard'">
Ir al Panel
</button>
❌ Inválido: Elemento con role="button" dentro de un enlace
<a href="/settings">
<span role="button">Configuración</span>
</a>
✅ Solucionado: Eliminar el role redundante
Dado que el elemento <a> ya comunica interactividad, el role="button" interno es innecesario y conflictivo. Simplemente usa el enlace directamente:
<a href="/settings">Configuración</a>
❌ Inválido: Enlace dentro de un botón
Ten en cuenta que lo contrario — un <a> dentro de un <button> — también es inválido por la misma razón:
<button>
<a href="/home">Inicio</a>
</button>
✅ Solucionado: Elige un elemento
<a href="/home" class="btn">Inicio</a>
El principio clave es simple: nunca anides un elemento interactivo dentro de otro. Elige el elemento que mejor coincida con la semántica de tu caso de uso — <a> para navegación, <button> para acciones — y usa CSS para lograr el diseño visual que necesitas.
Encuentra problemas como este automáticamente
Rocket Validator escanea miles de páginas en segundos, detectando problemas de HTML en todo tu sitio web.
Más información: