No es el mejor con javascript y actualmente estoy atascado en algo. Me las arreglé para armar un acordeón que se expande y contrae con un ícono: después que se transforma cuando se abre el objeto. También solo permite abrir un acordeón a la vez, que es lo que se necesita.
Mi problema es que el ícono :after no funciona correctamente porque una vez que se agrega la clase "activa", solo se elimina si se abre otro objeto, no si se cierra el mismo objeto. ¿Alguien tiene una solución que pueda arreglar esto? Necesito que se elimine la clase si se abre otro acordeón, así como si se vuelve a hacer clic en el objeto para cerrarlo.
Como se mencionó anteriormente, no soy el mejor con JS y realmente solo logré lo que tengo con este acordeón de otras respuestas que encontré aquí. Aquí está mi código actual. ¡Cualquier ayuda es muy apreciada!
JavaScript
var acc = document.getElementsByClassName("accordion"); var i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { var panel = this.nextElementSibling; if (panel.style.maxHeight){ panel.style.maxHeight = null; } else { let active = document.querySelectorAll(".accordion-div .accordion.active"); for(let j = 0; j < active.length; j++){ active[j].classList.remove("active"); active[j].nextElementSibling.style.maxHeight = null; } this.classList.toggle("active"); panel.style.maxHeight = panel.scrollHeight + "px"; } }); }HTML
<div class="accordion-div"> <h5 class="accordion">Heading</h5> <div class="panel"> <p>Some Text</p> <h5 class="accordion">Heading 2</h5> <div class="panel"> <p>Some Text</p> <h5 class="accordion">Heading 3</h5> <div class="panel"> <p>Some Text</p> </div> </div>CSS
h5.accordion { cursor: pointer; padding: 25px!important; padding-left:2px!important; width: 100%; line-height:13px; text-align: left; outline: none; transition: 0.4s; font-size:13px!important; vertical-align:center; font-family:"Avenir Next", sans-serif; font-weight:300; margin:0; margin-top:2px; border-bottom:0!important; } h5.accordion:after { content: '\002B'; line-height:13px; font-size:22px; float: right; color:#5f5f5f; margin-left: 5px; transition: transform .5s; transform-origin: 50% 60%; } .active:after { transform: rotate(-225deg); } .panel { padding: 0 2px; max-height: 0; overflow: hidden; transition: max-height 0.2s ease-out; border-bottom:solid 1px #f1f1f1; }Hubo un error tipográfico que indicaba que no estaba cerrando div para sus encabezados en su HTML, verifique el fragmento, también para open y close , agregué una línea de JS para eliminar primero la clase active si está presente y luego alternar según this
Ejecute el fragmento y vea
var acc = document.getElementsByClassName("accordion"); var i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { this.classList.remove("active"); var panel = this.nextElementSibling; if (panel.style.maxHeight){ panel.style.maxHeight = null; } else { let active = document.querySelectorAll(".accordion-div .accordion.active"); for(let j = 0; j < active.length; j++){ active[j].classList.remove("active"); active[j].nextElementSibling.style.maxHeight = null; } this.classList.toggle("active"); panel.style.maxHeight = panel.scrollHeight + "px"; } }); } h5.accordion { cursor: pointer; padding: 25px!important; padding-left:2px!important; width: 100%; line-height:13px; text-align: left; outline: none; transition: 0.4s; font-size:13px!important; vertical-align:center; font-family:"Avenir Next", sans-serif; font-weight:300; margin:0; margin-top:2px; border-bottom:0!important; } h5.accordion:after { content: '\002B'; line-height:13px; font-size:22px; float: right; color:#5f5f5f; margin-left: 5px; transition: transform .5s; transform-origin: 50% 60%; } .active:after { transform: rotate(-225deg); } .panel { padding: 0 2px; max-height: 0; overflow: hidden; transition: max-height 0.2s ease-out; border-bottom:solid 1px #f1f1f1; } javascript jquery <div class="accordion-div"> <h5 class="accordion">Heading</h5> <div class="panel"> <p>Some Text</p> </div> <h5 class="accordion">Heading 2</h5> <div class="panel"> <p>Some Text</p> </div> <h5 class="accordion">Heading 3</h5> <div class="panel"> <p>Some Text</p> </div> </div>Primero, elimine todas las clases activas cuando se haga clic en la etiqueta h5
const removeActiveClasses = (e) => { const target = e.targrt || e.currentTarget; const active = target.querySelector(".accordion.active"); active.classList.remove("active"); }Entonces necesitas activar el elemento actual.
const activeElement = (e) => { const target = e.target.nextElementSibling; target.classList.add("active"); }Al final
const accordion = e => { removeActiveClasses(e); activeElement(e); } for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", accordion); } Aviso: no necesita usar un bucle because solo desea un elemento activo