【jQuery】アコーディオン、エリア外からのアンカーでアコーディオンが開く、そしてアンカー場所へ移動する。

デザオ
あのー、アンカーリンクのボタンを押したらアコーディオンが開いてその中にあるアンカーリンクの場所にスルスルーと移動させたいのですが可能ですかね?
デザコト
なんだかややこしそうですが、やってみましょうかー

さっそく実装してみる

コードを見る(HTML・CSS・jQuery)

HTML

<section class="section">
  <div class="anchor">
    <ul>
      <li>
        <a href="#anchor1">アンカー1へ</a>
      </li>
      <li>
        <a href="#anchor2">アンカー2へ</a>
      </li>
      <li>
        <a href="#anchor3">アンカー3へ</a>
      </li>
    </ul>
  </div>
  <button class="more" type="button" aria-expanded="false">もっとみる(アコーディオン)</button>

  <div class="one-detail hide">
    <div class="one-body" id="anchor1">
      <p>アンカー1</p>
    </div>
    <div class="one-body" id="anchor2">
      <p>アンカー2</p>
    </div>
    <div class="one-body" id="anchor3">
      <p>アンカー3</p>
    </div>
  </div>
</section>

CSS

絶対に必要なものだけ記載しておきます。デザインはおまかせしますー。

/* 見本そのもの(これだけは必要) */
.hide {
  display: none;
}

/* ここから下は見た目(なくても動きます) */
/*=========
.anchor
=========*/

.anchor ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  list-style-type: none;
  margin: 0 0 100px;
  padding: 0;
  box-sizing: border-box;
}
.anchor ul li {
  width: calc(100% / 3);
  border-right: 1px solid #fff;
  text-align: center;
  box-sizing: border-box;
}
.anchor ul li:last-child {
  border-right: none;
}
.anchor ul li a {
  display: block;
  padding: 10px;
  text-decoration: none;
  color: #fff;
  font-size: 16px;
  background: #2b2a27;
  border: 1px solid #2b2a27;
  transition: .3s;
}
.anchor ul li a:hover {
  color: #2b2a27;
  background: #fff;
}

/*=========
.more
=========*/

.more {
  display: block;
  width: 100%;
  font: inherit;
  color: #fff;
  font-size: 16px;
  text-align: center;
  background: #2b2a27;
  border: 1px solid #2b2a27;
  padding: 10px;
  cursor: pointer;
  transition: .3s;
}
.more:hover {
  color: #2b2a27;
  background: #fff;
}

/*=========
.one-detail
=========*/

.one-detail {
  border: 1px solid #2b2a27;
  background: #f3efe6;
  padding: 30px;
}
.one-body {
  margin: 0 0 100px;
}
.one-body p {
  font-size: 16px;
  margin: 0;
}

/* 動きを減らす設定のとき(jQuery の動きは <script> の $.fx.off で止める) */
@media (prefers-reduced-motion: reduce) {
  .anchor ul li a,
  .more { transition: none; }
}

jQuery

一行解説したいところですが、ざっくり説明すると、スルスルーとスクロール設定、待機設定、アコーディオン設定、アンカーからのアコーディオン設定、をしています。

$(function(){
  // 動きを減らす設定のときは、jQuery の動きを止める
  $.fx.off = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  //scrollTo
  function scrollTo(_target, _offset){
    var
      _f = true,
      _s = 500,
      _t = 0;

    if(_target && _target.length){
      try{
        _t = _target.offset().top;
      }
      catch(e){
        _f = false;
      }
    }
    if(_offset !== undefined){
      _t = Math.max(0, _t + _offset);
    }
    if(_f){
      $('body, html').animate({scrollTop: _t}, _s, 'swing');
    }
  }
  //wait
  $.wait = function(msec) {
    var d = new $.Deferred;

    setTimeout(function(){
      d.resolve(msec);
    }, msec);

    return d.promise();
  };
  //more
  $('.section').find('.more').on('click', function(){
    var _p = $(this).closest('.section');
    _p
      .toggleClass('is-open')
      .find('.one-detail').slideToggle(250);
    // 開いているかどうか(aria-expanded)を切り替える
    $(this).attr('aria-expanded', _p.hasClass('is-open'));

    if(_p.hasClass('is-open')){
      $.when(function(){
        return $.wait(100);
      }())
        .then(function(){
        scrollTo(_p.find('.one-detail'), -48.8);
      });
    }
    return false;
  });
  //anchor + open
  $('.section').find('.anchor').find('a').off().on('click', function(){
    var
      _p      = $(this).closest('.section'),
      _target = $($(this).attr('href')),
      _wait   = 300;

    if(_p.hasClass('is-open')){
      _wait = 100;
    }

    _p
      .addClass('is-open')
      .find('.one-detail').show();
    _p.find('.more').attr('aria-expanded', 'true');

    $.when(function(){
      return $.wait(_wait);
    }())
      .then(function(){
      scrollTo(_target, -0);
    });
    return false;
  });
});

メモ

jQueryのことで何かわからないことがあればjQueryの日本語リファレンスサイトがあるので一度チェックしてみるのをおすすめします。

さいごに

デザオ
おー、これですー
デザコト
なかなかややこしかったですねー。さ、甘いもの食べに行きましょうー

ふたりの小言

関連記事

デザコトauthor

あ、いいな、と思うWebデザインを紹介しています。デザインの参考に。やさしいデザインが多いです。Webデザインギャラリー『デザインのこと - Web design gallery』を運営しています。