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 componente consiste en varios widgets de divulgación que se pueden expandir (o contraer) para revelar (o bien ocultar) su contenido.

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

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

El acordeón exclusivo

Navegadores compatibles

  • 120
  • 120
  • x
  • 17.2

Una variación del patrón de acordeón es el acordeón exclusivo, en el que solo uno de los widgets de divulgación se puede abrir 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 comportan como un acordeón exclusivo. Cuando abras uno de los elementos <details> del grupo, el que se abrió 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 valor name nuevo en un elemento <details>, se crea un grupo lógico nuevo.

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 elementos del mismo nivel. Pueden estar dispersas por el documento. Es el atributo name lo que los agrupa, no su orden del DOM.

Polyfill: El acordeón exclusivo

Con el siguiente JavaScript, es posible policompletar 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 la mejora progresiva, este es un comportamiento aceptable.