Curso gratuito de HTML

HTML Demos

// 06 de 09

06 · <details> & <summary>

Acordeón nativo sin JavaScript. El navegador gestiona apertura, cierre, el evento toggle y el atributo open.

<details><summary>open name=toggle eventexclusive accordion

Demo en vivo

¿Qué es HTML semántico?
Usar etiquetas que describan el significado del contenido, no solo su apariencia: <article>, <nav>, <main>, <aside>...
¿Cuándo usar <section> vs <div>?
<section> implica un bloque temático con sentido propio, idealmente con un heading. <div> es un contenedor genérico sin semántica propia.
Este ya está abierto al cargar
El atributo open en el HTML lo hace visible desde el inicio. Es un atributo booleano, no necesita valor.
Solo uno puede estar abierto
Todos los <details> con el mismo valor de name forman un grupo. Abrir uno cierra los demás automáticamente.
Funciona como radio buttons
El navegador gestiona la exclusividad. En browsers sin soporte simplemente ignoran el name y funcionan como details normales.
Cero JavaScript necesario
Es la forma nativa de hacer un acordeón exclusivo. Accesible, retrocompatible y semántico.
Observa el toggle event
Abre y cierra este panel para ver el evento dispararse.
— abre o cierra el panel de arriba —

open como atributo — puedes leer/escribir details.open en JS para saber si está abierto.

summary — es el único hijo que el navegador requiere. Lo demás puede ser cualquier HTML.

Código importante

<!-- Básico -->
<details>
  <summary>Título visible</summary>
  <p>Contenido oculto</p>
</details>

<!-- Abierto por defecto -->
<details open>
  <summary>Visible al cargar</summary>
  <p>Este ya está expandido</p>
</details>

<!-- Exclusive accordion (Chrome 120+) -->
<!-- El mismo name= los agrupa -->
<details name="grupo">
  <summary>Item 1</summary>
  Contenido 1
</details>
<details name="grupo">
  <summary>Item 2</summary>
  Contenido 2
</details>

<!-- Evento toggle: detecta apertura/cierre -->
details.addEventListener('toggle', e => {
  if (e.newState === 'open') {
    console.log('abierto')
  } else {
    console.log('cerrado')
  }
})

<!-- Leer estado programáticamente -->
const d = document.querySelector('details')
console.log(d.open) // true o false
d.open = true       // abrir desde JS

<!-- CSS: quitar el triángulo nativo -->
summary {
  list-style: none;
}
summary::-webkit-details-marker {
  display: none;
}