三十路からのWeb屋入門

新人Webデザイナーの備忘録

【html/css/jQuery】アコーディオンメニューの開閉がカクカクになる【ハマりメモ】

2020/10/3

ブログを作った翌日からさっそく体調を崩したpullkawaです。
病気するとお金がかかっていやね。

アコーディオンを実装する中で、地味にハマったことがあったのでメモ。

■アコーディオンメニューの開閉アニメがカクカクする

「ひとつのメニューを開いたら、他のメニューは閉じる」というアコーディオンメニューを実装しました。
これ自体はサクッとできましたが、他部分のコードを書いているうちになぜか開閉時にカクカクするように。。
横の開閉マークは問題なく動作しているので、jQueryの記述ミスではなさそう。

修正前デモ

結論から言うと、メニュー内の要素(.list_content)にtransition:allを指定してるのがよくなかったようです。
開閉するタイミングでstyleを変更してて、そこにtransition:allのアニメーションが干渉してしまっているらしい。
というわけで、今回は.list_contentのtransition設定を削除すると、スムーズにアニメーションするようになりました。

修正後デモ

html/css/jQueryの記述は以下。

html

<div class="list_sample">
  <h2>スムーズなアコーディオン</h2>
  <ul class="list_good">
    <li class="list_box">
      <div class="list_title">
        <p>アコーディオン</p>
      </div>
      <div class="list_content">
        <p>
          自然な動き
        </p>
      </div>
    </li>
    <li class="list_box">
      <div class="list_title">
        <p>アコーディオン</p>
      </div>
      <div class="list_content">
        <p>
          スムーズ<br>
          スムーズ<br>
          スムーズ<br>
          スムーズ<br>
          スムーズ<br>
          スムーズ
        </p>
      </div>
    </li>
  </ul>
</div>

css

.list_sample{
    margin:40px;
    position: relative;
    width: 60%;
    max-width: 640px;
}
.list_box{
    margin-bottom:20px;
    border: 1px solid #aaa;
    position: relative;
    width: 100%;
}
.list_title{
    padding:20px;
    display: block;
    position: relative;
    text-decoration: none;
    text-align: center;
    cursor: pointer;
    width: 100%;
}
.list_content{
    display: block;
    position: relative;
}
.list_title p, .list_content p{
    position: relative;
    margin-right: 5px;
    line-height:22px;
}
.list_title p{
    margin-right: 35px
}
.list_title p:before, .list_content p:before{
    position: absolute;
    color: #aaa;
    font-size: 26px;
    font-weight: bold;
    left:-40px;
}
.list_title:before,
.list_title:after {
    content: '';
    display: block;
    width: 16px;
    height:1px;
    background: #aaa;
    position:absolute;
    right:15px;
    top:50%;
    transform: translateY(-50%);
}
.list_title:after{
    transform: translateY(-50%) rotate(90deg);
    transition: 0.5s;
}
.list_title.active:after{
    transform:rotate(0);
    transition: 0.5s;
    top:50%
}
.list_content{
    display: none;
    padding:12px;
}
$(function(){
  $('.list_title').click(function(){
    if($(this).next().is(':hidden')){
      $('.list_content').slideUp('selected');
      $(this).next().slideDown('selected');
      $(this).addClass('active');
    } else {
      $(this).next().slideUp('selected');
      $(this).removeClass('active');
    }
  });
});

参考にさせていただいた記事

http://b-nana.com/slidetoggle-not-working/
今回の場合、slideToggleではなくslideUp/slideDownだったのですが、同様の手段で解決できました。

今回の場合メニュー内の要素にtransitionを指定する必要はないので、
そもそも無駄なコードを書かないことが大事ですね。。
もし、開閉時にフェードイン・アウトなどさせたい場合は
こちらの記事にもあるように、transition-propatyを指定する必要がありそう。

Profile

pullkawa
1991.01.21
主にソシャゲの会社で5年ぐらいUIデザインやイベントロゴのデザイン、なぜか背景アニメーションも作ったりしました。
今はずっと行きたかったWeb業界に転職できて、日々jQueryと戦っています。
UI/UX/IAに興味あり。民俗学や江戸文化も好き。
いぬが好きです。目標はフルリモートで働けるようになっていぬかねこを飼うことです。

Cocoda!Contact