Acordeón exclusivo

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

El acordeón

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

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

Demo: acordeón con HTML y CSS.

El acordeón exclusivo

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 a la vez.

Para crear un acordeón exclusivo en la Web, agrega 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 comportan como un acordeón exclusivo. Cuando abras uno de los elementos <details> del grupo, se cerrará automáticamente el que se abrió anteriormente.

<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>
Demo: acordeón exclusivo con HTML y CSS.

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

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

Los elementos <details> que forman parte de un acordeón exclusivo no necesariamente deben ser hermanos. Pueden estar dispersos en el documento. Es el atributo name el que los agrupa, no su orden de DOM.

Cómo implementar el acordeón exclusivo

Con el siguiente código JavaScript, es posible 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 navegadores no activan este evento toggle. En esos navegadores, el código de polyfill no hará nada. En términos de mejora progresiva, este es un comportamiento aceptable.