スマホサイトなどでよくある開閉式のアコーディオンをjQueryと少しのJavaScript記述で作りたいと思います。
ベーシックな開閉アコーデイオン
jQueryの設定
jQueryライブラリを使用するのでCDNの記述を忘れずに!
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
HTMLの記述
<dl>
<dt class="accordion">ときどきWEB</dt>
<dd>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>jQuery</li>
<li>Android</li>
</ul>
</dd>
</dl>
dl要素をアコーディオンの入れ子としアコーディオン全体のボックスを作成。
引き出し部分の役割として
dt要素にアコーディオンのタイトルと
accordionクラスを指定し、
dd要素にアコーディオン内に入れたい要素を記述。
cssの記述
* {
margin:0;
padding:0;
}
dl {
width: 320px;
color:#FFF;
text-align:center;
font-weight:bold;
}
dt.accordion{
width: 100%;
height: 50px;
line-height: 50px;
color:#FFF;
background:#06F url(bg_bar.png) no-repeat;
-webkit-background-size:100%;
}
dt.accordion.opened {
background-image:url(icon.png), url(bg_bar.png);
background-repeat: no-repeat,no-repeat;
background-position:0% 0%,0% 0%;
-webkit-background-size:0% 0%,100%;
}
dd {
width: 100%;
background: url(icon02.png) no-repeat;
}
dd ul li{
list-style: none;
height:30px;
line-height: 30px;
background:#09F;
}
主にアコーディオン全体の幅、引き出し部の装飾、内部の背景色など。
javascriptの記述
$(function(){
$("dd").after().hide();
$("dt.accordion").click(function(){
$(this).toggleClass("open").next().slideToggle();
});
});
①
accordionの内部(
dd)以降の要素を初期設定で隠す。
②
accordionの引き出し部(
dt)をクリックすると起こるアクションを設定。
③前者の指定部分を
toggleClassで開く。開く動作は
slideToggleを利用。
これでタイトル要素をクリックすると開閉するアコーディオンが完成。
デモページ①
上記のアコーディオンスクリプトを実装したデモページが
こちら
アコーディオン機能の拡張(閉じるボタン)
アコーディオン内容自体が少ない場合は問題ないですが、
内容が長くなりすぎてしまうと、ページスクロールで上まで戻ってタイトル部をクリックしないと閉じられないのはよろしくないのでメニュー内部に閉じるアクションを追加します。
HTMLの追加
<dl>
<dt class="accordion">ときどきWEB</dt>
<dd>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>jQuery</li>
<li>Android</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
</ul>
<div class="close">close</div>
</dd>
</dl>
アコーディオン内部の最後に
closeクラスを記述し、閉じる要素を作成
javascriptの修正
$(function(){
$("dd").after().hide();
$("dt.accordion").click(function(){
$(this).next().slideToggle();
});
$("dd .close").click(function(){
$(this).parent().slideToggle();
});
});
dd要素内の
closeクラスをクリックすると、
その親要素(
dd)に
slideToggleアクションを起こす記述を指定
(一度内部を開く事でしかcloseクラスをクリックする事ができないため、結果的に閉じるアクションになる)
これで最下部の要素(今回の場合はテキスト)をクリックすることでも閉じる事が可能になった!
デモページ②
上記のアコーディオンスクリプトを実装したデモページが
こちら
アコーディオン開閉の初期設定を変更
アコーディオンを連続で設置するとデザインによっては開閉アクションの有無がユーザーに伝わりにくいなどの場合があるので、対応として指定の箇所のアコーディオンを初期設定として開いておく記述。
JavaScriptの記述
$(function(){
$("dd:not(:first)").after().hide();
$("dt.accordion").click(function(){
$(this).next().slideToggle();
});
$("dd .close").click(function(){
$(this).parent().slideToggle();
});
});
最初のクラス指定個所に『
:not(:first)』と記述。
つまり1番目以外は隠す(閉じる)指定。
『
first』を任意の数に変更したり、『
hide』を『
show』に変えたりで好きな指定ができます、ハイ。
デモページ③
上記のアコーディオンスクリプトを実装したデモページが
こちら
便利だね!jQuery!!
スマホUI特化型機能拡張(追記)
メニュー項目やメニュー内容がやたらと多い場合はスマホなどウィンドウ領域が狭いデバイスで閲覧された際にアコーディオン開閉の度に焦点となる部分までスクロールする手間が出てきます。
そこで、現在開いているメニュー以外は閉じて、開いたメニュー項目までページを自動でスクロールする機能を追加させます。
HTMLの記述
<dl>
<dt class="accordion">ときどきWEB</dt>
<dd>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>jQuery</li>
<li>Android</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
</ul>
<div class="close">close</div>
</dd>
<dt class="accordion">ときどきWEB</dt>
<dd>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>jQuery</li>
<li>Android</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
<li>・・・・</li>
</ul>
<div class="close">close</div>
</dd>
・
・
・
</dl>
CSSの記述
dl {
width: 320px;
color:#FFF;
text-align:center;
font-weight:bold;
margin: 200px auto 1500px;
}
dt.accordion{
cursor: pointer;
width: 100%;
height: 50px;
line-height: 50px;
color:#FFF;
background:#06F;
-webkit-background-size:100%;
}
dt.accordion.opened {
background-repeat: no-repeat,no-repeat;
background-position:0% 0%,0% 0%;
-webkit-background-size:0% 0%,100%;
}
dd {
width: 100%;
}
dd ul li{
list-style: none;
height:30px;
line-height: 30px;
background:#09F;
}
.close{
width: 100%; height: 50px; background:red;
cursor: pointer;
}
JavaScriptの記述
$(function(){
// 最初のdd要素以外は隠す
$("dd:not(:first)").after().hide();
// dt.accordionのクリック処理
$("dt.accordion").click(function(){
// 一旦dd要素をすべて閉じる
$("dd").slideUp();
// dt要素からオープン用フラグclassの"flag"を削除
$("dt").removeClass("flag");
// クリックされたdt要素がオープン用フラグclassの"flag"を持っているか?
if(!$(this).hasClass("flag")){
// 自身に"flag"classを追加し、次の要素(dd)をスライドダウン ⇒
$(this).addClass("flag").next().slideDown(function(){
// ページスクロールさせるためのドキュメント高さ位置を変数scrollPointに代入(※dt要素の高さも合わせて)
var scrollPoint = $(this).offset().top - $("dt.accordion").height();
// オープンしたメニュー先頭までスクロール
$('body,html').animate({ scrollTop : scrollPoint});
return false;
});
}
});
// 閉じるボタンのクリック処理
$('dd .close').click(function(){
// 自身の親要素のddをスライドアップ
$(this).parent('dd').slideUp();
// dt要素からオープン用フラグclassの"flag"を削除
$("dt").removeClass("flag");
});
});
スクリプトの解説
- ①複数のメニューでそれぞれの開閉の状態を監視する場合は、開いているメニューに目印となるフラグ(flagクラス)を付けます
- ②クリックされたメニュートリガーがそのフラグとなるflagクラスの付いたトリガーかどうかをhasClassメソッドで条件確認し、flagクラスの付いたメニューはslideDownメソッドで開き、それ以外のメニューはslideUpメソッドで閉じさせる
- ※従来のslideToggleメソッドは要素の状態を切り替えるためのメソッドなので、確実に開かせる場合はslideDown、閉じる場合はslideUPで処理に切り替えた方が意図しない挙動がなくなるかと思います。
- ③flagクラスの付いたメニューを開く際にページスクロールさせるためのドキュメント高さ位置(とメニュー項目dt要素の高さ分をheightメソッドで取得した分も加算)をscrollPoint変数に代入
- ④animateメソッドでオープンしたメニュー先頭位置まで自動スクロール
- ⑤閉じるボタンcloseクラスをクリックしたら自身の親要素をslideUpメソッドで閉じる
- ⑥この段階で全てのメニューは閉じている状態なので、flagクラスをすべてremoveメソッドで削除
デモページ③
上記のアコーディオンスクリプトを実装したデモページが
こちら