サンプルデモ
今回、作るアコーディオンのサンプルデモです。「メニュー1」「メニュー2」をクリックすると、それぞれの子メニューが開閉します。ここでの項目は最低限の2つだけですが、数は、後からいくつでも増やすことができます。あと、デザインは仕組みを理解する上で邪魔なので、排除しちゃってます。記事の最後でダウンロードできるので、あなた自身で好きなようにデザインをして下さいね。
クリックすると開閉するコンテンツ、いわゆるアコーディオンの作り方を、初心者が1から作れるように説明します。難しいようでシンプルなので、15分あれば、確実に理解できます。当サイトでは、カテゴリを選択するサイトマップで利用しています。
今回、作るアコーディオンのサンプルデモです。「メニュー1」「メニュー2」をクリックすると、それぞれの子メニューが開閉します。ここでの項目は最低限の2つだけですが、数は、後からいくつでも増やすことができます。あと、デザインは仕組みを理解する上で邪魔なので、排除しちゃってます。記事の最後でダウンロードできるので、あなた自身で好きなようにデザインをして下さいね。
アコーディオンの仕組みは、とっても簡単で、jQueryのslideToggle()
というメソッドを利用しているだけです。
slideToggle()
は、「開いている時には閉めて、閉まっている時には開く」という便利な、jQueryのメソッドです。まるで楽器のアコーディオンのようにビヨ〜ンと上下にアニメーションして動作します。
クリックイベントで挙動を確認してみましょう。まずは適当に、ボタンと開閉する要素の2つを用意します。
HTML
<!-- クリックイベントを設定するボタン -->
<p><a id="acdn-button" class="acdn-button"><b>開閉する</b></a></p>
<!-- 開閉する要素 -->
<p id="acdn-target" class="acdn-content">ターゲットとなる要素</p>
CSS
/* 開閉する要素 */
.acdn-content
{
width: 200px ;
height: 200px ;
background: #D36015 ;
}
なんてことのない、次のようなデザインが出来上がりましたね。まだ単なるデザイン段階なので、「開閉する」をクリックしても、何も起こりません。
ターゲットとなる要素
続いて、「開閉する」というリンクテキスト(#acdn-button
)に対して、「開閉する要素(#acdn-target
)にslideToggle()
を実行する」というクリックイベントを設定してみましょう。
JavaScript
// [#acdn-button]にクリックイベントを設定する
$( '#acdn-button' ).click( function()
{
// [#acdn-target]に[slideToggle()]を実行する
$( '#acdn-target' ).slideToggle() ;
} ) ;
それでは、「開閉する」をクリックして、どのような挙動をするのか、確認してみて下さい。上下に「閉じる」「開く」を交互に繰り返すはずです。
ターゲットとなる要素
先ほどのサンプルで既に「これならもう、アコーディオン作れるなっ」という人がいるんじゃないでしょうか。アコーディオンの仕組みとはシンプルなもので、「トリガーとなるボタン」と「ターゲットとなるコンテンツ」のペアを作って、slideToggle()
を実行するクリックイベントを設定するだけのことです。1つ1つのトリガーに対して、新しく処理を記述していくのは大変なので、あとは、「いかに拡張性のあるプログラムにするか」という工夫をするのみです。それを次章で紹介します。
アコーディオンの仕組みを理解できたら、早速、作成してみましょう。
まずは、HTML部分を作成しましょう。シンプルに、ul
要素で構成しましょう。まずは、土台となる親メニューを作ります。親メニューには、クリックイベントを設定するための、共通のクラス属性値(サンプルではsyncer-acdn
)を付けておいて下さい。
HTML
<ul>
<li><p><a class="syncer-acdn">メニュー1</p></li></a>
<li><p><a class="syncer-acdn">メニュー2</p></li></a>
</ul>
続いて、それぞれのli
要素の中に、子メニューを入れましょう。子メニューもここでは、ul
要素で構成します。次のような形になります。親メニュー名をクリックすると、子であるul
要素に対してslideToggle()
が実行されるというシステムを目指します。
HTML
<ul>
<li><p><a class="syncer-acdn">メニュー1</a></p>
<ul>
<li>子メニュー 1-1</li>
<li>子メニュー 1-2</li>
</ul>
</li>
<li><p><a class="syncer-acdn">メニュー2</a></p>
<ul>
<li>子メニュー 2-1</li>
<li>子メニュー 2-2</li>
</ul>
</li>
</ul>
親メニュー(トリガー)と子メニュー(ターゲット)のペアをいくら増やしても、同じようにプログラムが作動するように、この2つを繋ぎましょう。まず、ターゲットとなるul
要素に、一意のID属性値を設定します。サンプルでは、syncer-acdn-01
、syncer-acdn-02
を設定しました。
HTML
<ul>
<li><p><a class="syncer-acdn">メニュー1</a></p>
<ul id="syncer-acdn-01">
<li>子メニュー 1-1</li>
<li>子メニュー 1-2</li>
</ul>
</li>
<li><p><a class="syncer-acdn">メニュー2</a></p>
<ul id="syncer-acdn-02">
<li>子メニュー 2-1</li>
<li>子メニュー 2-2</li>
</ul>
</li>
</ul>
そしてトリガーとなるa
要素には、data-target
という属性を追加し、その値には、ターゲットとなる要素のID名を設定します。次の通りですね。
HTML
<ul>
<li><p><a class="syncer-acdn" data-target="syncer-acdn-01">メニュー1</a></p>
<ul id="syncer-acdn-01">
<li>子メニュー 1-1</li>
<li>子メニュー 1-2</li>
</ul>
</li>
<li><p><a class="syncer-acdn" data-target="syncer-acdn-02">メニュー2</a></p>
<ul id="syncer-acdn-02">
<li>子メニュー 2-1</li>
<li>子メニュー 2-2</li>
</ul>
</li>
</ul>
トリガーとなるa要素をクリックすると、そのdata-target
の値(例えばsyncer-acdn-01
)を読み込み、その値と同じ名前のIDを持つ要素に対してslideToggle()
を実行する、というプログラムを作成します。これなら、いくらペアが増えても、JavaScriptのコードを改変する必要がなくなるというわけです。
まずは、トリガーに共通して設定されているsyncer-acdn
を対象に、クリックイベントを設定します。次の通りですね。
JavaScript
// [.syncer-acdn]にクリックイベントを設定する
$( '.syncer-acdn' ).click( function(){
// 処理の記述
// ...
} ) ;
次に、クリックした要素($(this)
)の、data-target
属性値を読み込みます。これを任意の変数であるtarget
に代入します。
JavaScript
// [data-target]の属性値を代入する
var target = $(this).data( 'target' ) ;
仕上げです。target
に代入された文字列と同じ名前のID名を持つ要素に対して、slideToggle()
を実行します。これで、アコーディオンの完成です。呆気なさ過ぎて時間が余ってしまいましたか?
JavaScript
// [target]と同じ名前のIDを持つ要素に[slideToggle()]を実行する
$( '#' + target ).slideToggle() ;
完成版のコードです。これだけで、トリガーとターゲットのペアをいくら増やしても、それら全てがアコーディオンになります。ul
要素に限らず、div
要素でもol
要素でも、ルールを守れば、どんな要素にも適用できます。
JavaScript
// [.syncer-acdn]にクリックイベントを設定する
$( '.syncer-acdn' ).click( function()
{
// [data-target]の属性値を代入する
var target = $( this ).data( 'target' ) ;
// [target]と同じ名前のIDを持つ要素に[slideToggle()]を実行する
$( '#' + target ).slideToggle() ;
} ) ;
記事の冒頭で紹介したものです。下地として利用するのに最適な、余計なデザインを一切施していないアコーディオンコンテンツです。スタイルシートはありません。
HTML
<h2>アコーディオン</h2>
<p>分かりやすいように、デザインを排除したシンプルなアコーディオンです。親メニュー名をクリックすることで、子メニューが開閉します。</p>
<ul>
<li><p><a class="syncer-acdn" data-target="syncer-acdn-01">メニュー1</a></p>
<ul id="syncer-acdn-01">
<li>子メニュー 1-1</li>
<li>子メニュー 1-2</li>
</ul>
</li>
<li><p><a class="syncer-acdn" data-target="syncer-acdn-02">メニュー2</a></p>
<ul id="syncer-acdn-02">
<li>子メニュー 2-1</li>
<li>子メニュー 2-2</li>
</ul>
</li>
</ul>
JavaScript
// DOMを全て読み込んでから処理する
$(function()
{
// [.syncer-acdn]にクリックイベントを設定する
$( '.syncer-acdn' ).click( function()
{
// [data-target]の属性値を代入する
var target = $( this ).data( 'target' ) ;
// [target]と同じ名前のIDを持つ要素に[slideToggle()]を実行する
$( '#' + target ).slideToggle() ;
// 終了
return false ;
} ) ;
}) ;
アコーディオンに、ある程度のデザインを施したサンプルデモです。JavaScriptは、前項で紹介したものと同じです。
HTML
<h2>アコーディオン</h2>
<p>ある程度のデザインを加えたアコーディオンです。</p>
<ul class="syncer-acdn-parent">
<li><p><a class="syncer-acdn" data-target="syncer-acdn-03">メニュー1</a></p>
<ul id="syncer-acdn-03" class="syncer-acdn-child">
<li><a href="#syncer-acdn-01">子メニュー 1-1</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-2</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-3</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-4</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-5</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-6</a></li>
<li><a href="#syncer-acdn-01">子メニュー 1-7</a></li>
</ul>
</li>
<li><p><a class="syncer-acdn" data-target="syncer-acdn-04">メニュー2</a></p>
<ul id="syncer-acdn-04" class="syncer-acdn-child">
<li><a href="#syncer-acdn-02">子メニュー 2-1</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-2</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-3</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-4</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-5</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-6</a></li>
<li><a href="#syncer-acdn-02">子メニュー 2-7</a></li>
</ul>
</li>
</ul>
CSS
/******************************
デザインあり
******************************/
/* 親の[ul] */
.syncer-acdn-parent
{
width: 250px ;
margin: 1.5em 0 0 ;
padding: 12px 18px ;
border: 2px solid rgba( 0,0,0, 0.1 ) ;
}
/* 子の[ul] */
.syncer-acdn-child
{
display: none ;
}
/* 余白設定 */
.syncer-acdn-child ,
.syncer-acdn-parent li ,
.syncer-acdn-parent li p
{
margin: 0 ;
padding: 0 ;
}
/* 親と子の[li] */
.syncer-acdn-parent li
{
list-style: none ;
}
/* 親の[a] */
.syncer-acdn-parent li p a
{
position: relative ;
top: 0 ;
left: 0 ;
}
.syncer-acdn-parent li p a:after ,
.syncer-acdn-parent li p a:hover:after
{
color: #333 ;
background: rgba( 0,0,255 , 0.1 ) ;
}
.syncer-acdn-parent li p a:after
{
position: absolute ;
top: 50% ;
right: 12px ;
content: "開閉" ;
font-size: .85em ;
margin-top: -12.5px ;
height: 17px ;
line-height: 17px ;
padding: 4px 8px ;
}
/* 親の[a]と子の[li] */
.syncer-acdn-parent li p a ,
.syncer-acdn-child li
{
border-bottom: 1px solid rgba( 0,0,0, 0.1 ) ;
}
/* 親と子の[a] */
.syncer-acdn-parent li a
{
display: block ;
padding: 8px 0 ;
font-weight: 700 ;
text-decoration: none ;
color: #333 ;
}
.syncer-acdn-parent li a:hover
{
cursor: pointer ;
color: #f00 ;
background: rgba( 0,0,0, 0.1 ) ;
}
/* 子の[a] */
.syncer-acdn-child li a:before
{
content: "∟" ;
padding-right: 5px ;
}
FAQなどのコンテンツによくある、質問タイトルをクリックすると、回答が表示されるタイプのアコーディオンです。これまでのul
要素ではなく、dl
要素を使っているのが特徴です。このようなコンテンツも実現します。JavaScriptの内容も、ここまでに紹介したのと全く同じです。拡張性が高いというのは美しいものですね。
HTML
<h2>アコーディオン</h2>
<p>クリックすると回答を見ることができる、Q&A形式のアコーディオンです。質問をクリックすると、回答を見ることができます。</p>
<dl class="syncer-acdn-faq">
<dt class="syncer-acdn" data-target="syncer-acdn-05">Q. あなたの名前はなんですか?</dt>
<dd id="syncer-acdn-05">A. 私の名前はまだありません…。</dd>
<dt class="syncer-acdn" data-target="syncer-acdn-06">Q. 昨日のご飯はなんでしたか?</dt>
<dd id="syncer-acdn-06">A. 昨日は「さすけ食堂」で黄金鯵を食べました…。</dd>
<dt class="syncer-acdn" data-target="syncer-acdn-07">Q. あなたが好きな犬の種類はなんですか?</dt>
<dd id="syncer-acdn-07">A. ダントツで<a href="https://twitter.com/arayutw/status/631488635871735808" target="_blank">黒柴</a>です。</dd>
<dt class="syncer-acdn" data-target="syncer-acdn-08">Q. 好きな水族館はどこですか?</dt>
<dd id="syncer-acdn-08">A. 高知県桂浜にある「桂浜水族館」です。砂浜の中にある独特の景観もいいですし、館内の「手作り感」に親しみを覚えるのです。</dd>
</dl>
CSS
/******************************
Q&A形式
******************************/
.syncer-acdn-faq
{
margin: 1.5em 0 0 ;
}
.syncer-acdn-faq dt ,
.syncer-acdn-faq dd
{
margin: 0 0 0 2em ;
padding: 4px 0 ;
}
.syncer-acdn-faq dt:hover
{
cursor: pointer ;
color: #777 ;
}
.syncer-acdn-faq dt
{
font-weight: 700 ;
}
.syncer-acdn-faq dd
{
display: none ;
padding: 12px 0 1.5em 1.5em ;
}
この記事で紹介してきた、各サンプルプログラムを配布しています。あなたのウェブサイトに活用していただければ、記事を書いた者としてこの上ない喜びです。
ファイル一覧
ファイル名をクリックすると内容を確認できます。「Download Zip」をクリックするとファイル一式をダウンロードできます。