Eliminar clase al hacer clic desde elementos abiertos en un acordeón

¿Cómo puedo mantener solo una definición visible al mismo tiempo en este ejemplo?

En otras palabras:

Al hacer clic en el botón i se debe alternar la clase en sí misma y la definición debajo del término, y eliminar active clase active de otros botones y open clase desde otras definiciones .

 document.querySelectorAll("dl").forEach(dl => dl.addEventListener("click", ({ target }) => { if (!target.matches("button")) return target.classList.toggle("active") target.parentElement.nextElementSibling.classList.toggle("open") }) ) 
 dd { visibility: hidden; height: 0 } .open { visibility: visible; height: auto } .active { color: DeepSkyBlue } abbr { pointer-events: none } 
 
aluminum
the chemical element of atomic number 13, a light silvery-grey metal.
silver
a precious shiny greyish-white metal, the chemical element of atomic number 47.
gold
a yellow precious metal, the chemical element of atomic number 79.
platinum
a precious silvery-white metal, the chemical element of atomic number 78.

Aquí hay una solución más concisa que usa solo clases open para hacer lo que necesita y algunas características de CSS y ES6.

La idea es eliminar open para todos y luego solo alternar con el clic. También todo el material para la eliminación está encadenado a través de los métodos ES6.

También tenga en cuenta el selector de CSS .open+dd ya que tiene hermanos y no una clase de contenedor (hubiera sido más fácil con dicho enfoque).

 document.querySelectorAll("dl").forEach(dl => dl.addEventListener("click", ({ target }) => { if (!target.matches("button")) return if (!target.parentElement.classList.contains("open")) [...target.parentElement.parentElement.children] .filter(({ tagName }) => tagName.toLowerCase() == "dt") .forEach(element => element.classList.remove("open")) target.parentElement.classList.toggle("open") }) ) 
 dd { visibility: hidden; height: 0 } .open + dd { visibility: visible; height: auto } .open button { color: DeepSkyBlue } abbr { pointer-events: none } 
 
aluminum
the chemical element of atomic number 13, a light silvery-grey metal.
silver
a precious shiny greyish-white metal, the chemical element of atomic number 47.
gold
a yellow precious metal, the chemical element of atomic number 79.
platinum
a precious silvery-white metal, the chemical element of atomic number 78.

Tienes que ocultar la opción abierta antes de abrir la nueva. Podrías hacer así:

 window.onload = function() { document.querySelectorAll("dl").forEach(dl => dl.addEventListener("click", ({ target }) => { if (!target.matches("button")) return const dl = target.closest('dl'); // Check if there is an active button and remove active class if (dl.querySelector('.active') != null) { dl.querySelector('.active').classList.toggle('active'); } // Check if there is an open dd and close it if (dl.querySelector('.open') != null) { dl.querySelector('.open').classList.toggle('open'); } target.classList.toggle("active") target.parentElement.nextElementSibling.classList.toggle("open") }) ) } 
 dd { visibility: hidden; height: 0 } .open { visibility: visible; height: auto } .active { color: DeepSkyBlue } abbr { pointer-events: none } 
 

Car List.

aluminum
the chemical element of atomic number 13, a light silvery-grey metal.
silver
a precious shiny greyish-white metal, the chemical element of atomic number 47.
gold
a yellow precious metal, the chemical element of atomic number 79.
platinum
a precious silvery-white metal, the chemical element of atomic number 78.

Esta podría ser una solución. Puede recorrer los elementos que contienen la clase que desea alternar, si es así, luego alternar

 document.querySelectorAll("dl").forEach(dl => dl.addEventListener("click", ({ target }) => { document.querySelectorAll(".open").forEach(function(element) { if(element.classList.contains("open")){ element.classList.toggle("open"); } }); document.querySelectorAll(".active").forEach(function(element) { if(element.classList.contains("active")){ element.classList.toggle("active"); } }); if (!target.matches("button")) return target.classList.toggle("active") target.parentElement.nextElementSibling.classList.toggle("open") }) ) 
 dd { visibility: hidden; height: 0 } .open { visibility: visible; height: auto } .active { color: DeepSkyBlue } abbr { pointer-events: none } 
  
aluminum
the chemical element of atomic number 13, a light silvery-grey metal.
silver
a precious shiny greyish-white metal, the chemical element of atomic number 47.
gold
a yellow precious metal, the chemical element of atomic number 79.
platinum
a precious silvery-white metal, the chemical element of atomic number 78.

Es lo mismo pero no es necesario que verifique la condición cada vez que lo haga.

Puedes simplemente usar element.classList=""; para eliminar todos los elementos de la clase del elemento.

No, no tiene clase “activa” y “abierta” para ningún elemento, necesita usar .classList.add("open") lugar de .classList.toggle("open")

Mira esto:

 document.querySelectorAll("dl").forEach(dl => dl.addEventListener("click", ({ target }) => { document.querySelectorAll("dd").forEach(function(element) { element.classList=""; }); document.querySelectorAll(".active").forEach(function(element) { element.classList=""; }); if (!target.matches("button")) return target.classList.add("active") target.parentElement.nextElementSibling.classList.add("open") }) ) 
 dd { visibility: hidden; height: 0 } .open { visibility: visible; height: auto } .active { color: DeepSkyBlue } abbr { pointer-events: none } 
 
aluminum
the chemical element of atomic number 13, a light silvery-grey metal.
silver
a precious shiny greyish-white metal, the chemical element of atomic number 47.
gold
a yellow precious metal, the chemical element of atomic number 79.
platinum
a precious silvery-white metal, the chemical element of atomic number 78.