Kuci
Kuci

Reputation: 198

Simple vanilla javascript accordion - problem when click on active item

I have a problem with my accordion script.

Can someone explain me - why after clicking on the active item, the animation is not performed like when clicking on the next item?

It seems to me that the problem is at the beginning of the if condition:

if (this.nextElementSibling.style.maxHeight) {

when I click on accordionItemHead

let accordions = document.querySelectorAll('.js-accordions');

accordions.forEach(function(accordion) {

  let singleAccordionItems = accordion.querySelectorAll('.js-accordions-item');

  singleAccordionItems.forEach(function(accordionItem) {

    let accordionItemHead = accordionItem.querySelector('.js-accordions-head');
    let accordionItemContent = accordionItem.querySelector('.js-accordions-content');

    accordionItemHead.addEventListener("click", function() {

      if (this.nextElementSibling.style.maxHeight) {
        this.nextElementSibling.style.maxHeight = null;

      } else {

        singleAccordionItems.forEach(function(item) {

          item.querySelector('.js-accordions-content').style.maxHeight = null;
          item.classList.remove('is-active');

        });
      }

      accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
      accordionItem.classList.toggle('is-active');

    });


  });

});
.c-accordion {
  box-shadow: 2px 2px 24px rgba(0, 0, 0, 0.05);
}

.c-accordion__item {
  padding-left: 20px;
}

.c-accordion__header {
  position: relative;
  cursor: pointer;
  padding: 26px 0 22px;
}

.c-accordion__header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background-color: blue;
}

.c-accordion__item:first-child .c-accordion__header::before {
  content: none;
}

.c-accordion__header h4 {
  padding-right: 60px;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.2;
}

.c-accordion__text {
  max-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition-duration: 400ms;
  transition-property: max-height, visibility;
  transition-delay: 0, 400ms;
}

.is-active .c-accordion__text {
  visibility: visible;
  transition-duration: 400ms;
  transition-property: max-height, visibility;
  transition-delay: 400ms, 0;
}

.c-accordion__text p {
  margin-top: 0;
  margin-bottom: 25px;
}

.c-accordion__text-inner {
  display: flex;
  flex-direction: column;
}

.c-accordion__icon {
  position: absolute;
  top: 50%;
  margin-top: -9px;
  right: 25px;
  font-size: 18px;
  color: red;
}

.c-accordion__icon::after {
  position: absolute;
  top: 50%;
  margin-top: -1px;
  left: 0;
  content: '';
  width: 19px;
  height: 2px;
  background-color: blue;
  transform: scalex(0);
  transition: transform 0.4s;
}

.is-active .c-accordion__icon::after {
  transform: scaleX(1);
}

.c-accordion__icon::before {
  display: inline-block;
  transition: transform 0.3s, opacity 0.5s;
}

.is-active .c-accordion__icon::before {
  transform: rotate(90deg);
  opacity: 0;
}
<div class="c-accordion js-accordions">
  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content" style="">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 2</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

Views: 141

Answers (3)

user2495207
user2495207

Reputation: 861

Just a little change in the conditionals makes it work:

      let accordions = document.querySelectorAll(".js-accordions");

      accordions.forEach(function (accordion) {
        let singleAccordionItems = accordion.querySelectorAll(".js-accordions-item");

        singleAccordionItems.forEach(function (accordionItem) {
          let accordionItemHead = accordionItem.querySelector(".js-accordions-head");
          let accordionItemContent = accordionItem.querySelector(".js-accordions-content");

          accordionItemHead.addEventListener("click", function () {
            if (this.nextElementSibling.style.maxHeight) {
              this.nextElementSibling.style.maxHeight = null;
            } else {
              singleAccordionItems.forEach(function (item) {
                item.querySelector(".js-accordions-content").style.maxHeight = null;
                item.classList.remove("is-active");
              });
              accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
              accordionItem.classList.toggle("is-active");
            }
          });
        });
      });
     .c-accordion {
        box-shadow: 2px 2px 24px rgba(0, 0, 0, 0.05);
      }

      .c-accordion__item {
        padding-left: 20px;
      }

      .c-accordion__header {
        position: relative;
        cursor: pointer;
        padding: 26px 0 22px;
      }

      .c-accordion__header::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 1px;
        background-color: blue;
      }

      .c-accordion__item:first-child .c-accordion__header::before {
        content: none;
      }

      .c-accordion__header h4 {
        padding-right: 60px;
        font-size: 18px;
        font-weight: 500;
        line-height: 1.2;
      }

      .c-accordion__text {
        max-height: 0;
        overflow: hidden;
        visibility: hidden;
        transition-duration: 400ms;
        transition-property: max-height, visibility;
        transition-delay: 0, 400ms;
      }

      .is-active .c-accordion__text {
        visibility: visible;
        transition-duration: 400ms;
        transition-property: max-height, visibility;
        transition-delay: 400ms, 0;
      }

      .c-accordion__text p {
        margin-top: 0;
        margin-bottom: 25px;
      }

      .c-accordion__text-inner {
        display: flex;
        flex-direction: column;
      }

      .c-accordion__icon {
        position: absolute;
        top: 50%;
        margin-top: -9px;
        right: 25px;
        font-size: 18px;
        color: red;
      }

      .c-accordion__icon::after {
        position: absolute;
        top: 50%;
        margin-top: -1px;
        left: 0;
        content: "";
        width: 19px;
        height: 2px;
        background-color: blue;
        transform: scalex(0);
        transition: transform 0.4s;
      }

      .is-active .c-accordion__icon::after {
        transform: scaleX(1);
      }

      .c-accordion__icon::before {
        display: inline-block;
        transition: transform 0.3s, opacity 0.5s;
      }

      .is-active .c-accordion__icon::before {
        transform: rotate(90deg);
        opacity: 0;
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <div class="c-accordion js-accordions">
      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content" style="">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 2
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>
    </div>

Upvotes: 1

Kuci
Kuci

Reputation: 198

Corrected JS code:

let accordions = document.querySelectorAll('.js-accordions');

accordions.forEach(function (accordion) {

    let singleAccordionItems = accordion.querySelectorAll('.js-accordions-item');

    singleAccordionItems.forEach(function (accordionItem) {

        let accordionItemHead = accordionItem.querySelector('.js-accordions-head');
        let accordionItemContent = accordionItem.querySelector('.js-accordions-content');

        accordionItemHead.addEventListener("click", function() {

            if (this.nextElementSibling.style.maxHeight) {
                this.nextElementSibling.style.maxHeight = null;
                accordionItem.classList.remove('is-active');

            } else {

                singleAccordionItems.forEach(function (item) {

                    item.querySelector('.js-accordions-content').style.maxHeight = null;
                    item.classList.remove('is-active');

                });

                accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
                accordionItem.classList.toggle('is-active');
            }
            
        });
        
    
    });
    
});

Upvotes: 0

Arthur Medeiros
Arthur Medeiros

Reputation: 140

I think it's because you're triyng to control the animation using both css and javascript.
One thing that you could do, is to have a css classes for both states active and no-active, and then you use Js to swtich betwen them.

.no-active {
max-height: 0px
}
.no-active {
max-height: 9999px
}

Upvotes: 0

Related Questions