【jQuery】上手に隠してデザインすっきり!アコーディオンメニューを実装しよう

jQuery/JavaScript
この記事は約13分で読めます。

アコーディオンメニューは、ドロップダウンメニューと同じように通常時はコンテンツが非表示になっています。

「よくある質問」などで見かける、クリックすると表示されるやつですね!

spica
spica

コンテンツが冗長になりがちな時に大活躍です!

スポンサーリンク

クリックで現れるメニュー(アコーディオンメニュー)を実装

オーソドックスなアコーディオンメニューです。

EDIT ON CODEPENをクリック!

See the Pen accordion-menu by spica (@spica_blog) on CodePen.

このアコーディオンメニューでの挙動
  • タイトルをクリックすると中のコンテンツがスライドしながら表示される
  • タイトルをクリックするとコンテンツがスライドしながら非表示になる
  • 1つ目のコンテンツはあらかじめ開いておく
  • コンテンツは常に1つだけ開くようにする
  • コンテンツの開閉に合わせてアイコンが回転する

HTMLを記述する

「dl」はアコーディオンメニュー全体です。
1つのブロックは「div class=”accordion」で囲み、タイトルは「dt class=”accordion-title”」、中のコンテンツは「dd class=”accordion-content”」としました。

<dl>
  <div class="accordion">
    <dt class="accordion-title">アコーディオンメニュー</dt>
    <dd class="accordion-content">アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身
    </dd>
  </div>
  
  <div class="accordion">
    <dt class="accordion-title">アイコンは疑似要素</dt>
    <dd class="accordion-content">アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身
    </dd>
  </div>
  
  <div class="accordion">
    <dt class="accordion-title">アイコンはFontAwesome</dt>
    <dd class="accordion-content">アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身
    </dd>
  </div>
  
  <div class="accordion">
    <dt class="accordion-title">slideToggle</dt>
    <dd class="accordion-content">アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身アコーディオンメニューの中身
    </dd>
  </div>
</dl>

CSSを記述する

/* base */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* アコーディオンメニュー全体 */
dl {
  width: 90%;
  margin: 10px auto;
}

/* メニュー1セット */
.accordion {  
  border: 1px solid #ccc;
  margin-top: 5px;
  cursor: pointer;
}
/* タイトル */
.accordion-title {
  position: relative;
  font-size: 18px;
  font-weight: bold;
  padding: 15px 20px;
}
/* 中身 */
.accordion-content {
  display: none;
  font-size: 14px;
  padding: 0 20px 15px 20px;
  margin-bottom: 5px;
}

/* 疑似要素にアイコンを付ける */
.accordion-title::after {
  display: inline-block;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 15px;
  margin: auto 0; /* 上下中央揃え */
  content: "\f107";
  font-family: "Font Awesome 5 free";
  font-weight: 900;
  font-size: 30px;
  width: 1em;
  height: 1em;
  text-align: center;
  color: teal;
  transition: transform 0.5s;
}
/* クラス名にopenが付いたらアイコンが180度回転 */
.accordion-title.open::after {
  transform: rotate(180deg);
}

順を追って説明していきます。

アコーディオンメニューの見た目を整える

シンプルかつ、クリックを誘導するような見た目にしましょう。

divを枠で囲む

「div class=”accordion”」は、薄いグレーの枠で囲み、上のコンテンツとの余白を5px開けます。

divはdt(タイトル)とdd(コンテンツ)を内包しているので、1つのタイトルとコンテンツが1セットということが分かりやすくなります。

「cursor: pointer;」でカーソルの形を変えて、クリックする部分であることを強調します。

.accordion {  
  border: 1px solid #ccc;
  margin-top: 5px;
  cursor: pointer;
}

タイトル

「dt class=”accordion-title”」は、アイコンを設置するため「position: relative;」とします。

.accordion-title {
  position: relative;
  font-size: 18px;
  font-weight: bold;
  padding: 15px 20px;
}

中のコンテンツ

「dd class=”accordion-content”」は、非表示にしておくので「display: none;」とします。

.accordion-content {
  display: none;
  font-size: 14px;
  padding: 0 20px 15px 20px;
  margin-bottom: 5px;
}

疑似要素にアイコン

アイコンは、「dt class=”accordion-title”」の疑似要素に設定します。
「position: absolute;」とし、位置を決めるため「top: 0;」「bottom: 0;」「right: 15px;」と指定します。
上下中央揃えのため「margin: auto 0;」も指定します。

アイコンはFont Awesomeを使います。

疑似要素エリアをアイコンのサイズに合わせるため、「width: 1em;」「height: 1em;」とし、その範囲内で左右中央揃えになるよう「text-align: center;」も指定します。

この指定をしておかないと、アニメーションでアイコンが回転した時に位置がずれてしまうからです。

アニメーションの速度を、「transition: transform 0.5s;」とします。

.accordion-title::after {
  display: inline-block;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 15px;
  margin: auto 0; /* 上下中央揃え */
  content: "\f107";
  font-family: "Font Awesome 5 free";
  font-weight: 900;
  font-size: 30px;
  width: 1em;
  height: 1em;
  text-align: center;
  color: teal;
  transition: transform 0.5s;
}

コンテンツが開くとアイコンが回転する

コンテンツが開閉すると、それに合わせてアイコンが回転するようにします。

「transform: rotate(180deg);」と指定すると、アイコンがくるっと半回転します。

「.accordion-title.open::after」は、「.accordion-title」に「open」というクラス名が追加されたときの疑似要素を指します。

このクラス名の付け外しはjQueryで行います。

.accordion-title.open::after {
  transform: rotate(180deg);
}
▼疲れてきたらヨガタイム!▼

jQueryを記述する

最後にjQueryを記述しましょう。

単純にコンテンツが開閉するだけでなく、1番目のコンテンツが初めから開いている・他のコンテンツを開くと現在開いているコンテンツが閉じるように指定します。

$(function() {
  // 1つ目は最初から開いていて、クラス名openも追加されている
  $('.accordion:first-of-type .accordion-content').css('display', 'block');
  $('.accordion:first-of-type .accordion-title').addClass('open');

  // タイトルをクリックすると
  $('.accordion-title').click(function() {
    // タイトルの次の要素ddが0.5秒の速度で開閉する
    $(this).next().slideToggle(500);
    // タイトルにクラス名openが追加され、疑似要素が回転する
    $(this).toggleClass('open');
    // クリックしたタイトル以外のddは閉じる
    $('.accordion-title').not($(this)).next().slideUp();
    // クリックしたタイトル以外クラス名openを外す
    $('.accordion-title').not($(this)).removeClass('open');
  });
});

アコーディオンメニューのコード

実行予約$(function(){})

{}の中にjQueryのコードを書いていきます。

$(function() {
  // jQueryを記述
});

【イベント】click()

タイトルをクリックした時に実行するので、セレクタは「’.accordion-title’」となります。

「$(‘.accordion-title’).click(function() {})」の{}の中に処理を書いていきます。

$('.accordion-title').click(function() {
  // 処理を書く
});

タイトルの次の要素を開閉する

ドロップダウンメニューの時に登場した、「slideToggle()」

ここでも活躍いたします。

「slideToggle()」の引数に値を指定すると、その速度で開閉します。

「this」が「’.accordion-title’」のことを指すので、「next()」はすぐ次の要素「dd」のことですね。

この記述で、「タイトルの次の要素(dd)を0.5秒で開閉する」という処理ができました。

$(this).next().slideToggle(500);

タイトルにクラス名を追加または削除する

「toggleClass()」というメソッドは、クラス名を追加する「addClass()」と、クラス名を削除する「removeClass()」を交互に行ってくれます。

引数に追加したいクラス名を指定します。

これで、「タイトルにクラス名openを付けたり外したりする」という処理ができました。

 $(this).toggleClass('open');

not()

次に「not()」を用いた処理について説明します。

このメソッドは、特定の要素以外を対象にしたい時に便利です。

引数に除外したい要素を指定します。

$('.accordion-title').not($(this)).next().slideUp();

「not($(this))」「今クリックされたタイトル以外のクラス名accordion-title」が対象となります。

「.next().slideUp();」は「次の要素をスライドアップ」なので、「クリックされたタイトル以外のコンテンツは閉じる」となります。

同様に、「not()」を用いて特定の要素以外からクラス名を外す処理も行います。

$('.accordion-title').not($(this)).removeClass('open');

「クリックされたタイトル以外のタイトルから、クラス名openを外す」となりますね。

1つ目のコンテンツを開いておく

では最後に、1つ目のコンテンツだけ最初から開いておくように設定しましょう。

記述するのはクリックイベントの外です。

「accordion:first-of-type」で、1つめの<div class=”accordion”>を指定し、その中のクラス名accordion-contentを「css(‘display’, ‘block’)」で表示にします。

$('.accordion:first-of-type .accordion-content').css('display', 'block');

同じく1つめの<div class=”accordion”>の中の、今度はクラス名accordion-titleに「addClass(‘open’)」でクラス名openを追加しておきます。

$('.accordion:first-of-type .accordion-title').addClass('open');

これで、「1つ目のコンテンツは最初から開いておく(開いているのでクラス名openをつける)」の処理ができました。

まとめ

アコーディオンメニューを実装できました!

見た目もすっきりしました!

spica
spica

ドロップダウンメニューとアコーディオンメニューの

コードの違いも学べましたね。

アコーディオンメニューはサイトのデザイン性を高めるだけでなく、ユーザーが自分の意志で見る/見ないを選択できるので、情報量が多いサイトには必須だと思います。

ドロップダウンメニューに比べて少しコードは増えましたが、一つひとつは難しくありません。

アイコンをアレンジする、アニメーションを追加するなど、自分なりの工夫をしてみてください。

コメント