Acordeones sin JavaScript: <details> y <summary>
¿Cuántas veces has instalado una librería de acordeones o escrito decenas de líneas de JavaScript para mostrar y ocultar contenido? Con <details> y <summary> el navegador lo hace por ti, de forma accesible y sin dependencias.
Cómo funciona <details>
<details> es un elemento desplegable. Su contenido está oculto por defecto y se muestra al hacer clic sobre el <summary>, que actúa como título o etiqueta del bloque.
<details>
<summary>¿Qué es HTML?</summary>
<p>
HTML (HyperText Markup Language) es el lenguaje de marcado estándar
para crear páginas web. Define la estructura y el significado del contenido.
</p>
</details>
Así de simple. El navegador añade el triángulo de apertura, gestiona la animación y expone el estado a las tecnologías de asistencia.
El atributo open
Por defecto <details> está cerrado. Si quieres que empiece abierto, añade el atributo open:
<details open>
<summary>Esta sección está abierta por defecto</summary>
<p>El contenido es visible al cargar la página.</p>
</details>
Detectar cambios de estado con JavaScript
El elemento emite un evento toggle cada vez que cambia entre abierto y cerrado:
<details id="acordeon">
<summary>Más información</summary>
<p>Contenido adicional.</p>
</details>
<script>
const acordeon = document.getElementById('acordeon');
acordeon.addEventListener('toggle', () => {
if (acordeon.open) {
console.log('Abierto');
} else {
console.log('Cerrado');
}
});
</script>
Estilizar <details> y <summary>
El triángulo por defecto es el marcador nativo del navegador. Puedes reemplazarlo completamente:
/* Ocultar el marcador nativo */
details > summary {
list-style: none;
cursor: pointer;
}
details > summary::-webkit-details-marker {
display: none;
}
/* Estilo personalizado */
details {
border: 1px solid #333;
border-radius: 8px;
padding: 0;
overflow: hidden;
}
summary {
padding: 1rem 1.25rem;
font-weight: 600;
display: flex;
justify-content: space-between;
align-items: center;
background: #1a1a2e;
color: #fff;
}
/* Icono con CSS puro */
summary::after {
content: '+';
font-size: 1.25rem;
transition: transform 0.2s;
}
details[open] summary::after {
transform: rotate(45deg);
}
details > *:not(summary) {
padding: 1rem 1.25rem;
}
Acordeón de preguntas frecuentes (FAQ)
Un caso de uso muy habitual es el bloque de preguntas frecuentes, que también tiene valor SEO gracias al marcado estructurado:
<section>
<h2>Preguntas frecuentes</h2>
<details>
<summary>¿Cuánto tiempo dura el curso?</summary>
<p>El curso tiene una duración aproximada de 6 horas de contenido.</p>
</details>
<details>
<summary>¿Necesito conocimientos previos?</summary>
<p>Solo necesitas saber qué es HTML a nivel básico.</p>
</details>
<details>
<summary>¿Hay certificado al terminar?</summary>
<p>Sí, recibirás un certificado de finalización por correo electrónico.</p>
</details>
</section>
Acordeón exclusivo: solo uno abierto a la vez
El atributo name en <details> permite crear grupos exclusivos: al abrir uno, los demás del mismo grupo se cierran automáticamente. Es la solución nativa al acordeón clásico sin JavaScript:
<details name="faq">
<summary>¿Pregunta 1?</summary>
<p>Respuesta a la pregunta 1.</p>
</details>
<details name="faq">
<summary>¿Pregunta 2?</summary>
<p>Respuesta a la pregunta 2.</p>
</details>
<details name="faq">
<summary>¿Pregunta 3?</summary>
<p>Respuesta a la pregunta 3.</p>
</details>
Todos los <details> con el mismo name forman un grupo. El navegador garantiza que solo uno esté abierto a la vez.
Nota: el atributo
namepara grupos de acordeón tiene soporte en Chrome 120+ y Firefox 130+. Para Safari, considera un pequeño polyfill si necesitas compatibilidad total.
Animación de apertura
Por defecto la apertura es instantánea. Con CSS moderno puedes añadir una transición suave:
details > *:not(summary) {
overflow: hidden;
transition: height 0.3s ease;
}
/* Técnica con interpolate-size (CSS moderno) */
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details > *:not(summary) {
height: 0;
}
details[open] > *:not(summary) {
height: auto;
}
}
<details> como widget de navegación
<details> no es solo para FAQs. Sirve para cualquier contenido colapsable: filtros de búsqueda, opciones avanzadas de formularios, secciones de código, notas al margen…
<!-- Filtros de búsqueda colapsables -->
<details>
<summary>Filtros avanzados</summary>
<form>
<label>
Categoría:
<select name="categoria">
<option>Todas</option>
<option>Frontend</option>
<option>Backend</option>
</select>
</label>
<label>
<input type="checkbox" name="gratis" /> Solo gratuitos
</label>
</form>
</details>
¿Qué hemos aprendido?
<details>+<summary>crean acordeones nativos sin JavaScript.- El atributo
opencontrola el estado inicial. - El atributo
nameagrupa<details>para que solo uno esté abierto a la vez. - El evento
togglepermite reaccionar a los cambios de estado. - Se puede animar con CSS sin trucos complicados.
Siguiente paso
En la próxima lección veremos los atributos data-*: cómo almacenar y acceder a datos personalizados directamente en los elementos HTML.