みなさん、こんにちは!ヒロックラボの平山です。

コーディングをしていて、こんな経験はありませんか?

『指示されたアニメーションのコードの書き方が分からず、検索してもヒットしない…』

先日、まさにこのような状況に陥ってしまいました。

そのアニメーションとは、

  1. 1.エリア外からアンカーリンク移動してアコーディオンメニューが開く。
  2. 2.エリア外のアンカーリンクで、リンク先の項目を含めるアコーディオンメニューが開き、スクロール移動する。

というものでした。

「いくら調べても答えが見つからない」と諦めかけていましたが、試行錯誤しながらなんとか実装できました。

今回は、jQueryを使用して上記2つのアニメーションの実装方法をお伝えしていきます。

jQueryを使用して、エリア外からアコーディオンメニューを開く

今回、実装したいアニメーションは、画像にあるような2つです。

それでは早速、コードを書いていきます。

エリア外からアンカーリンク移動してアコーディオンメニューが開く。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="icon" href="./">
  <title>アコーディオンメニュー</title>
  <meta name="description" content="">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="header">
    <p>アコーディオンメニュー</p>
  </header>
  <div class="anchor-wrap">
    <div class="section-inner">
      <dl class="anchor-unit">
        <dt class="anchor-unit_dt">
          <a href="#link1">リンク1</a>
        </dt>
        <dd class="anchor-unit_dd">
          <ul>
            <li><a href="#link1_1">リンク1-1</a></li>
            <li><a href="#link1_2">リンク1-2</a></li>
            <li><a href="#link1_3">リンク1-3</a></li>
          </ul>
        </dd>
      </dl>
      <dl class="anchor-unit">
        <dt class="anchor-unit_dt">
          <a href="#link2">リンク2</a>
        </dt>
        <dd class="anchor-unit_dd">
          <ul>
            <li><a href="#link2_1">リンク2-1</a></li>
            <li><a href="#link2_2">リンク2-2</a></li>
            <li><a href="#link2_3">リンク2-3</a></li>
          </ul>
        </dd>
      </dl>
      <dl class="anchor-unit">
        <dt class="anchor-unit_dt">
          <a href="#link3">リンク3</a>
        </dt>
        <dd class="anchor-unit_dd">
          <ul>
            <li><a href="#link3_1">リンク3-1</a></li>
            <li><a href="#link3_2">リンク3-2</a></li>
            <li><a href="#link3_3">リンク3-3</a></li>
          </ul>
        </dd>
      </dl>
    </div>
  </div>
  <div class="accordion-wrap">
    <div class="section-inner">
      <dl class="accordion-dlist" id="link1">
          <dt class="accordion-term">
            <h3 class="accordion-subtitle">リンク1</h3>
          </dt>
          <dd class="accordion-desc">
            <ul>
              <li id="link1_1">リンク1-1</li>
              <li id="link1_2">リンク1-2</li>
              <li id="link1_3">リンク1-3</li>
            </ul>
          </dd>
      </dl>
      <dl class="accordion-dlist" id="link2">
        <dt class="accordion-term">
          <h3 class="accordion-subtitle">リンク2</h3>
        </dt>
        <dd class="accordion-desc">
          <ul>
            <li id="link2_1">リンク2-1</li>
            <li id="link2_2">リンク2-2</li>
            <li id="link2_3">リンク2-3</li>
          </ul>
        </dd>
      </dl>
      <dl class="accordion-dlist" id="link3">
        <dt class="accordion-term">
          <h3 class="accordion-subtitle">リンク3</h3>
        </dt>
        <dd class="accordion-desc">
          <ul>
            <li id="link3_1">リンク3-1</li>
            <li id="link3_2">リンク3-2</li>
            <li id="link3_3">リンク3-3</li>
          </ul>
        </dd>
      </dl>
    </div>
  </div>
  <script src="jquery-3.6.0.min.js"></script>
  <script src="style.js"></script>
</body>
</html>
/**
* base.css
* ========================== */
body {
  font-family: "ヒラギノ角ゴ Pro", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, "MS Pゴシック", "MS PGothic", sans-serif;;
  color: #333;
  line-height: 2;
}
a {
  text-decoration: none; 
  color: #333; 
  display: inline-block;
}
a:hover {
  opacity: 0.6; 
}
.section-inner {
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}
/**
* header
* ========================== */
.header {
  width: 100%;
  padding: 0 80px;
  height: 80px;
  background-color: #333;
  color: #fff;
  display: flex;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
}
/**
* anchor
* ========================== */
.anchor-wrap {
  padding: 80px 0 800px;
}
.anchor-unit {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 15px 0;
}
.anchor-unit_dt {
  width: 15%;
  border-right: 2px solid #ff9b3c;
}
.anchor-unit_dd {
  width: 80%;
  padding-left: 20px;
}
.anchor-unit_dd ul {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.anchor-unit_dd ul li {
  padding: 0 15px 0 0;
}
/**
* accordion
* ========================== */
.accordion-wrap {
  padding-bottom: 800px;
}
.accordion-dlist:not(:first-child) {
  margin-top: 20px;
}
.accordion-term {
  align-items: center;
  cursor: pointer;
  display: flex;
  padding: 20px 70px 20px 20px;
  position: relative;
  background-color: #ff9b3c;
}
.accordion-term::before, .accordion-term::after {
  background-color: #c7000a;
  content: "";
  height: 2px;
  margin: 0 auto;
  position: absolute;
  right: 34px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
}
.accordion-term::after {
  transform: rotate(90deg);
  transition: .3s transform;
  }
  .accordion-subtitle {
  font-size: 16px;
  padding-left: 40px;
  }
.accordion-desc {
  display: none; 
  font-size: 16px;
  line-height: 2;
  padding: 35px 115px 35px 100px;
  text-align: left;
}
.accordion-term.active::after {
  transform: rotate(0);
}
// アコーディオン開いている状態でアンカーリンク移動したときの位置調整
$('a[href^="#"]').click(function(){
  var speed = 500;
  var href = $(this).attr("href");
  var target = $(href == "#" || href == ""? 'html':href);
  var position = target.offset().top - 150;
  $("html,body").animate({
      scrollTop: position
  },speed,"swing");
  return false;
});
//エリア外からアンカーリンク移動してアコーディオンメニューが開く。
$(function(){
  $('.anchor-unit_dt a').on('click', function(){
      var href = $(this).attr('href');
      var term = $(href).find('.accordion-term');
      $(term).toggleClass('active').next('.accordion-desc').slideDown({
          step: function(){
              var headerHight = 150;
              var target = $(href);
              var position = target.offset().top - headerHight;
              $('body,html').stop().animate({scrollTop:position}, 400), 'swing';
          }
      });
      $('.accordion-term').not($(term)).siblings('.accordion-desc').slideUp();
      $('.accordion-term').not($(term)).removeClass('active');
  });
});

コードを順番に見ていきます。

まず、アンカーリンクをクリックしたらアニメーションが作動するので、

$('.anchor-unit_dt a').on('click', function(){
      
  });

クリックイベントを記載します。そしてその中に、

  • ・該当するアコーディオンメニュータブにactiveクラスをつける
  • ・該当するアコーディオンメニューを開く
  • ・該当するアコーディオンメニューまでスクロール移動

についてのコードを記載していきます。

var href = $(this).attr('href');
var term = $(href).find('.accordion-term'); 
$(term).toggleClass('active').next('.accordion-desc').slideDown();

上記コードが、

  • ・該当のアコーディオンメニュータブにactiveクラスをつける
  • ・該当のアコーディオンメニューを開く

に該当します。

step: function(){
              var headerHight = 150;
              var target = $(href);
              var position = target.offset().top - headerHight;
              $('body,html').stop().animate({scrollTop:position}, 400), 'swing';
          }

上記コードは、スクロールでアンカーリンク移動になります。

slideDown()の中に記載することで、アコーディオンメニューが開いた後にスクロール移動するため、表示位置がずれることを避けることができます

1つのメニューが開くときに、他のメニューを閉じたい場合は、下記のコードを記載します。

$('.accordion-term').not($(term)).siblings('.accordion-desc').slideUp();
$('.accordion-term').not($(term)).removeClass('active');

エリア外のアンカーリンクで、リンク先の項目を含めるアコーディオンメニューが開き、スクロール移動する。

$(function(){
  $('.anchor-unit_dd a').on('click', function(){
      var href = $(this).attr('href');
      var desc = $(href).parents('.accordion-desc');
      var area = $(desc).parent().find('.accordion-term');
      $(area).toggleClass('active').next('.accordion-desc').slideDown({
          step: function(){
              var headerHight = 150;
              var target = $(href);
              var position = target.offset().top - headerHight;
              $('body,html').stop().animate({scrollTop:position}, 400);
          }
      });
      $('.accordion-term').not($(area)).siblings('.accordion-desc').slideUp();
      $('.accordion-term').not($(area)).removeClass('active');
  });
});

①と同じように、アンカーリンクをクリックしたらアニメーションが作動するので、

$('.anchor-unit_dd a').on('click', function(){
      
  });

のクリックイベントの中に、

  • ・リンク先の要素を含む親要素であるアコーディオンメニューにactiveクラスをつける
  • ・リンク先の要素を含むアコーディオンメニューを開く
  • ・メニューが開いた後にリンク先までスクロール移動

について記載していきます。

var href = $(this).attr('href');
var desc = $(href).parents('.accordion-desc');
var area = $(desc).parent().find('.accordion-term');
$(area).toggleClass('active').next('.accordion-desc').slideDown();

上記コードが、

  • ・リンク先のある親要素であるアコーディオンメニューにactiveクラスをつける
  • ・リンク先のあるアコーディオンメニューを開く

に該当します。

ここで気をつけたいところは、リンク先がアコーディオンメニュー内にあるので、リンク先からみて、accordion-descクラス、accordion-termクラスが親要素にあたります。そのため、parent()、parents()メソッドを使い、変数を定義していきます。

アコーディオンが開き、スクロール移動する部分のコードは①と同じです。

さいごに

今回は、jQueryを使って、エリア外からアコーディオンメニューを開く方法についてお伝えしてきました。

「エリア外からアコーディオンメニューを開く」と検索すると、コードの書き方はすぐに出てきました。

しかし、検索して出てきた参考のコードはアコーディオンメニュー単体で、複数のアコーディオンメニューには適応せず、該当するメニュー以外も開いてしまったり、アニメーションがうまく作動しなかったりと思うようにいきませんでした。

そこで、アニメーションの動作を細分化しました。そして細分化した動作を一つひとつクリアしていくことで、解決することができました

もし、調べても「アニメーションの実装の仕方が分からない!」という時は、アニメーションの動作を一つひとつ細分化してみてください。