首页 > 解决方案 > Smoothen accordion collapse CSS3 keyframes animation

问题描述

I have an accordion element on my website that was built using ES6 JS and CSS3. I have created a CSS3 keyframes animation for opening and closing these accordions, but the collapse is abrupt and not smooth like the open animation. What am I doing wrong in the following code? What can I do to smoothen this out?

const initial = (accordions) => {
  accordions.forEach(accordion => {
    accordion.classList.add('close')
  })
}

const reset = (accordions) => {
  accordions.forEach(accordion => {
    accordion.classList.add('close')
    accordion.classList.remove('open')
  })
}

const toggle = (accordions) => {
  accordions.forEach(accordion => {
    accordion.onclick = function() {
      if (accordion.classList.contains('open')) {
        accordion.classList.remove('open')
        accordion.classList.add('close')
      } else {
        reset(accordions)
        accordion.classList.remove('close')
        accordion.classList.add('open')
      }
    }
  })
}

let accordions = Array(...document.querySelectorAll('.js-accordion'))
if (accordions.length) {
  initial(accordions)
  reset(accordions)
  toggle(accordions)
}
@keyframes open {
  0% {
    display: none;
    transform: translate3d(0, -1rem, 0);
    opacity: 0;
  }
  1% {
    display: block;
    transform: translate3d(0, -1rem, 0);
    opacity: 0;
  }
  100% {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes close {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: none;
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
.faq {
  padding: 4em 0;
}
.faq-item {
  background-repeat: no-repeat;
  background-size: 1.5em;
  background-position: 100% 50%;
  padding: 1em 0;
  cursor: pointer;
  border-bottom: 1px solid black;
}
.faq-item a {
  text-decoration: none;
}
.faq-item.open {
  background-image: url("accordion-minus.svg");
}
.faq-item.open .content {
  animation: open 0.5s ease-in-out;
  display: block;
}
.faq-item.close {
  background-image: url("accordion-plus.svg");
}
.faq-item.close .content {
  animation: close 0.5s ease-in-out;
  display: none;
}
.faq-border {
  border-bottom: 1px solid black;
}
.content {
  width: 95%;
}
<div class="faq">
<h3>Acupuncture</h3>

<div class="faq-item js-accordion">
Question
  <div class="content js-accordion-content">Answer</div>
</div>

</div>

标签: cssanimationcss-animationsaccordion

解决方案


我认为此切换动画中不需要动画或关键帧。你需要的是transitiontransform

  1. display不建议过渡。因为如果 display: none dom 没有得到维度
  2. visibility非常推荐使用and显示和隐藏过渡元素opacity
  3. 首先,把样式.faq-item .content。这是当这个元素处于隐藏状态时
  4. 然后在样式可见时放置样式.faq-item.open .content

对不起,如果我不明白。

这是你需要的吗?试试这个小提琴

const initial = (accordions) => {
  accordions.forEach(accordion => {
    accordion.classList.remove('open')
  })
}

const reset = (accordions) => {
  accordions.forEach(accordion => {
    accordion.classList.remove('open')
  })
}

const toggle = (accordions) => {
  accordions.forEach(accordion => {
    accordion.onclick = function() {
      if (accordion.classList.contains('open')) {
        accordion.classList.remove('open')
      } else {
        reset(accordions)
        accordion.classList.add('open')
      }
    }
  })
}

let accordions = Array(...document.querySelectorAll('.js-accordion'))
if (accordions.length) {
  initial(accordions)
  reset(accordions)
  toggle(accordions)
}
.faq {
  padding: 4em 0;
}
.faq-item {
  background-repeat: no-repeat;
  background-size: 1.5em;
  background-position: 100% 50%;
  padding: 1em 0;
  cursor: pointer;
  border-bottom: 1px solid black;
}
.faq-item a {
  text-decoration: none;
}
.faq-item.open {
  background-image: url("accordion-minus.svg");
}
.faq-item .content{
  display: block !important;
  transform: translateY(0);
  opacity:0;
  visibility: hidden;
  transition: all 0.5s ease-in-out;
}
.faq-item.open .content {
  display: block !important;
  transform: translateY(1em);
  opacity:1;
  visibility: visible;
}

.faq-border {
  border-bottom: 1px solid black;
}
.content {
  width: 95%;
}
<div class="faq">
<h3>Acupuncture</h3>

<div class="faq-item js-accordion">
Question
  <div class="content js-accordion-content">Answer</div>
</div>

</div>


推荐阅读