The client.Height function in conjunction with the forEach method JS

Viewed 68

I have an accordion list and my task was to implement a smooth tabs open/close function for dynamic content without a set height. The forEach method works perfectly.

The smooth open/close function (setHeight in JS snippet)also works fine, but only for the first tab.

In other tabs this function does not work and the opening does not happen as we would like it to. I've already racked my brains. How can I combine the forEach method and the "setHeight" function so that nothing breaks?

const accItems = document.querySelectorAll('.accordion__item');

accItems.forEach((item) => {
  const icon = item.querySelector('.accordion__icon');
  const content = item.querySelector('.accordion__content');

    item.addEventListener('click', () => {
        if (item.classList.contains('open')) {
        item.classList.remove('open');
        icon.classList.remove('open');
        content.classList.remove('open');
    
        } else {
        const accOpen = document.querySelectorAll('.open');
        accOpen.forEach((open) => {
        open.classList.remove('open');
        });

        item.classList.add('open');
        icon.classList.add('open');
        content.classList.add('open');
        }
        
        if (content.clientHeight) {
            content.style.height = 0;
        }   else {
            let accText = item.querySelector('.acc-text');
            content.style.height = accText.clientHeight + "px";
        }
    });
});
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  color: #1f1f1f;
  background: #f2f2f2; }

html {
  font-size: 62.5%; }

h5 {
  margin: 0; }

p {
  margin: 0; }

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: auto;
  max-width: 140rem; }

.section-accordion {
  display: flex;
  align-items: center;
  max-width: 134rem;
  margin: auto; }

.accordion-image {
  width: 630px;
  height: 450px;
  background: url("https://eternel.maitreart.com/wp-content/uploads/2021/07/creat-home-1.jpg");
  background-repeat: no-repeat;
  background-size: cover; }

.accordion {
  width: 63rem;
  height: auto;
  margin-left: 8rem; }
  .accordion__item {
    border-top: 1px solid #a8a6a4;
    overflow: hidden;
    transition: height .5s;
    padding-bottom: 1rem; }
    .accordion__item:last-child {
      border-bottom: 1px solid #a8a6a4; }
    .accordion__item--header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 2rem 1rem 1rem 1rem;
      cursor: pointer; }
    .accordion__item.open {
      width: 100%; }
  .accordion__title {
    font-family: 'Lora';
    font-size: 2.4rem;
    line-height: 1.2;
    font-weight: 400;
    text-transform: uppercase; }
  .accordion__icon {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 2rem;
    height: 2rem;
    transition: transform .5s ease; }
    .accordion__icon span:first-child {
      transform: rotate(90deg) translateX(1px);
      width: 1.4rem;
      height: .1rem;
      background: currentColor; }
    .accordion__icon span {
      display: block;
      width: 1.4rem;
      height: .1rem;
      background: currentColor;
      cursor: pointer; }
    .accordion__icon.open {
      transform: rotate(45deg); }
  .accordion__content {
    font-family: 'Roboto', sans-serif;
    font-size: 1.6rem;
    line-height: 1.62;
    font-weight: 400;
    padding: 0 1rem 0 1rem;
    height: 0;
    transition: height .5s;
    overflow: hidden; }
    .accordion__content.open {
      margin-bottom: 1.2rem;
      height: 100%; }
    <div class="container">
        <section class="section-accordion">
            <div class="accordion-image"></div>
                <div class="accordion">
                    <div class="accordion__item open">
                        <div class="accordion__item--header">
                            <h5 class="accordion__title">Visual direction</h5>
                            <div class="accordion__icon open">
                                <span></span>
                                <span></span>
                            </div>
                        </div>
                        <div class="accordion__content open">
                            <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. 
                            Assistance travelling so especially do prosperous appearance mr no celebrated. 
                            Wanted easily in my called formed suffer. Songs hoped sense.
                            </p>
                        </div>
                    </div>
                    <div class="accordion__item">
                        <div class="accordion__item--header">
                            <h5 class="accordion__title">Event production</h5>
                            <div class="accordion__icon">
                                <span class="accordion__icon--first"></span>
                                <span class="accordion__icon--second"></span>
                            </div>
                        </div>
                        <div class="accordion__content">
                            <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. 
                            Assistance travelling so especially do prosperous appearance mr no celebrated. 
                            Wanted easily in my called formed suffer. Songs hoped sense.
                            </p>
                        </div>
                    </div>
                    <div class="accordion__item">
                        <div class="accordion__item--header">
                            <h5 class="accordion__title">Brand creation</h5>
                            <div class="accordion__icon">
                                <span class="accordion__icon--first"></span>
                                <span class="accordion__icon--second"></span>
                            </div>
                        </div>
                        <div class="accordion__content">
                            <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. 
                            Assistance travelling so especially do prosperous appearance mr no celebrated. 
                            Wanted easily in my called formed suffer. Songs hoped sense.
                            </p>
                        </div>
                    </div>
                    <div class="accordion__item">
                        <div class="accordion__item--header">
                            <h5 class="accordion__title">Design concept</h5>
                            <div class="accordion__icon">
                                <span class="accordion__icon--first"></span>
                                <span class="accordion__icon--second"></span>
                            </div>
                        </div>
                        <div class="accordion__content">
                            <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. 
                            Assistance travelling so especially do prosperous appearance mr no celebrated. 
                            Wanted easily in my called formed suffer. Songs hoped sense.
                            </p>
                        </div>
                    </div>
                </div>
            </div>
     

2 Answers

cleaned up js to make it more readable:

const accItems = document.querySelectorAll('.accordion__item'); 
function handleItemClick(e, i) {
    if (e) e.preventDefault();

    const actives = document.getElementsByClassName("open");
    while (actives.length)
        actives[0].classList.remove('open');
    accItems[i].classList.add("open"); 
}
accItems.forEach((item, i) => 
    item.addEventListener("click", (e) => handleItemClick(e, i))
);

Handling height with just css:

I made icon and content children of .open

 .accordion {
    width: 63rem;
    height: auto;
    margin-left: 8rem; }
    .accordion__item {
        border-top: 1px solid #a8a6a4;
        overflow: hidden;
        transition: height .5s;
        padding-bottom: 1rem; }
        .accordion__item:last-child {
        border-bottom: 1px solid #a8a6a4; }
        .accordion__item--header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 2rem 1rem 1rem 1rem;
        cursor: pointer; }
        .open .accordion__item {
        width: 100%; }
    .accordion__title {
        font-family: 'Lora';
        font-size: 2.4rem;
        line-height: 1.2;
        font-weight: 400;
        text-transform: uppercase; }
    .accordion__icon {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        width: 2rem;
        height: 0;
        transition: transform .5s ease; }
        .accordion__icon span:first-child {
        transform: rotate(90deg) translateX(1px);
        width: 1.4rem;
        height: .1rem;
        background: currentColor; }
        .accordion__icon span {
        display: block;
        width: 1.4rem;
        height: .1rem;
        background: currentColor;
        cursor: pointer; }
        open .accordion__icon {
        transform: rotate(45deg);
        height: 2rem; }
    .accordion__content {
        font-family: 'Roboto', sans-serif;
        font-size: 1.6rem;
        line-height: 1.62;
        font-weight: 400;
        padding: 0 1rem 0 1rem;
        height: 0;
        transition: height .5s;
        overflow: hidden; }
        .open .accordion__content {
        margin-bottom: 1.2rem;
        height: 100%; }

It does not seem that you need setHeight which is the one that messes the display

Here is a delegated version

const accordionItems = document.querySelectorAll(".accordion__item");
document.querySelector('.accordion').addEventListener('click', (e) => {
  const item = e.target.closest(".accordion__item");
  if (!item) return
  accordionItems.forEach(acItem => {
    if (acItem !== item) {
      acItem.classList.remove('open');
      acItem.querySelector('.accordion__icon').classList.remove('open');
      acItem.querySelector('.accordion__content').classList.remove('open');
    }
  });
  
  const icon = item.querySelector('.accordion__icon');
  const content = item.querySelector('.accordion__content');
  item.classList.toggle("open")
  const isOpen = item.classList.contains("open");
  icon.classList.toggle("open", isOpen);
  content.classList.toggle('open', isOpen);
});
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  color: #1f1f1f;
  background: #f2f2f2;
}

html {
  font-size: 62.5%;
}

h5 {
  margin: 0;
}

p {
  margin: 0;
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: auto;
  max-width: 140rem;
}

.section-accordion {
  display: flex;
  align-items: center;
  max-width: 134rem;
  margin: auto;
}

.accordion-image {
  width: 630px;
  height: 450px;
  background: url("https://eternel.maitreart.com/wp-content/uploads/2021/07/creat-home-1.jpg");
  background-repeat: no-repeat;
  background-size: cover;
}

.accordion {
  width: 63rem;
  height: auto;
  margin-left: 8rem;
}

.accordion__item {
  border-top: 1px solid #a8a6a4;
  overflow: hidden;
  transition: height .5s;
  padding-bottom: 1rem;
}

.accordion__item:last-child {
  border-bottom: 1px solid #a8a6a4;
}

.accordion__item--header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 2rem 1rem 1rem 1rem;
  cursor: pointer;
}

.accordion__item.open {
  width: 100%;
}

.accordion__title {
  font-family: 'Lora';
  font-size: 2.4rem;
  line-height: 1.2;
  font-weight: 400;
  text-transform: uppercase;
}

.accordion__icon {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 2rem;
  height: 2rem;
  transition: transform .5s ease;
}

.accordion__icon span:first-child {
  transform: rotate(90deg) translateX(1px);
  width: 1.4rem;
  height: .1rem;
  background: currentColor;
}

.accordion__icon span {
  display: block;
  width: 1.4rem;
  height: .1rem;
  background: currentColor;
  cursor: pointer;
}

.accordion__icon.open {
  transform: rotate(45deg);
}

.accordion__content {
  font-family: 'Roboto', sans-serif;
  font-size: 1.6rem;
  line-height: 1.62;
  font-weight: 400;
  padding: 0 1rem 0 1rem;
  height: 0;
  transition: height .5s;
  overflow: hidden;
}

.accordion__content.open {
  margin-bottom: 1.2rem;
  height: 100%;
}
<div class="container">
  <section class="section-accordion">
    <div class="accordion-image"></div>
    <div class="accordion">
      <div class="accordion__item open">
        <div class="accordion__item--header">
          <h5 class="accordion__title">Visual direction</h5>
          <div class="accordion__icon open">
            <span></span>
            <span></span>
          </div>
        </div>
        <div class="accordion__content open" id="content__wrapper">
          <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
          </p>
        </div>
      </div>
      <div class="accordion__item">
        <div class="accordion__item--header">
          <h5 class="accordion__title">Event production</h5>
          <div class="accordion__icon">
            <span class="accordion__icon--first"></span>
            <span class="accordion__icon--second"></span>
          </div>
        </div>
        <div class="accordion__content" id="content__wrapper">
          <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
          </p>
        </div>
      </div>
      <div class="accordion__item">
        <div class="accordion__item--header">
          <h5 class="accordion__title">Brand creation</h5>
          <div class="accordion__icon">
            <span class="accordion__icon--first"></span>
            <span class="accordion__icon--second"></span>
          </div>
        </div>
        <div class="accordion__content" id="content__wrapper">
          <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
          </p>
        </div>
      </div>
      <div class="accordion__item">
        <div class="accordion__item--header">
          <h5 class="accordion__title">Design concept</h5>
          <div class="accordion__icon">
            <span class="accordion__icon--first"></span>
            <span class="accordion__icon--second"></span>
          </div>
        </div>
        <div class="accordion__content" id="content__wrapper">
          <p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
          </p>
        </div>
      </div>
    </div>
</div>
</section>
</div>

Related