Acordeón exclusivo

Crea un acordeón exclusivo con varios elementos <details> que tengan el mismo name.

El acordeón

Un patrón de IU común en la Web es un componente de acordeón. Este es un componente que consiste en varios widgets de divulgación que se pueden expandir (o contraer) de manera individual para mostrar (u ocultar) su contenido.

Para implementar este patrón en la Web, debes combinar algunos elementos <details> y, por lo general, agruparlos visualmente para indicar que pertenecen juntos.

Demostración: Acordeón con HTML y CSS.

El exclusivo acordeón

Navegadores compatibles

  • Chrome: 120
  • Edge: 120.
  • Firefox: 130
  • Safari: 17.2.

Una variación del patrón de acordeón es el acordeón exclusivo, en el que solo se puede abrir uno de los widgets de divulgación al mismo tiempo.

Para lograrlo en la Web, ahora puedes agregar un atributo name a los elementos <details>. Cuando se usa este atributo, varios elementos <details> que tienen el mismo valor name forman un grupo semántico y se comportarán como un acordeón exclusivo. Cuando abras uno de los elementos <details> del grupo, el que abriste antes se cerrará automáticamente.

<details name="learn-css">
  <summary>Welcome to Learn CSS!</summary>
  <p>…</p>
</details>
<details name="learn-css">
  <summary>Box Model</summary>
  <p>…</p>
</details>
<details name="learn-css">
  <summary>Selectors</summary>
  <p>…</p>
</details>
Demostración: Acordeón exclusivo con HTML y CSS.

Una página puede tener varios acordeones exclusivos. Cada vez que usas un nuevo valor name en un elemento <details>, se crea un nuevo grupo lógico.

Demostración: Varios acordes exclusivos con HTML y CSS.

Ten en cuenta que los elementos <details> que forman parte de un acordeón exclusivo no necesariamente tienen que ser del mismo nivel. Pueden estar dispersos por todo el documento. Es el atributo name el que los agrupa, no su orden en el DOM.

Polyfill, el exclusivo acordeón

Con el siguiente JavaScript, es posible aplicar polyfill el comportamiento del acordeón exclusivo. El código se basa en el evento toggle del elemento <details>.

Cuando se abre un elemento <details> con un name, el código encuentra los otros elementos <details> abiertos con el mismo valor para el atributo name y los cierra.

document.querySelectorAll("details[name]").forEach(($details) => {
  $details.addEventListener("toggle", (e) => {
    const name = $details.getAttribute("name");

    if (e.newState == "open") {
      document
        .querySelectorAll(`details[name=${name}][open]`)
        .forEach(($openDetails) => {
          if (!($openDetails === $details)) {
            $openDetails.removeAttribute("open");
          }
        });
    }
  });
});

Algunas versiones anteriores de los navegadores no activan este evento toggle. En esos navegadores, el código de polyfill no realizará ninguna acción. En términos de mejora progresiva, este es el comportamiento aceptable.