[ プログラミング ] dl定義リストを利用してタブパネルをjQueryで作る方法

jQueryでタブパネルを作る場合、一般的には、というかよく使われている方法では、メニュー部分をulリストタグを利用して、コンテンツ部分は別にulリストタグあるいはdivタグを使うことが多いかと思いますが、無理やりdl定義リストタグを使ってタブパネルを実装してみたいと思います。

問題は、dtタグがメニュー部分、ddタグがコンテンツ部分になりますが、これらは交互に記述するため、タブ形式のレイアウトにするのが難しいということです。

レイアウトの部分はCSSになりますが、dt部分はfloatで横並びにし、dd部分は絶対配置(position:absolute;)でdl部分の下にくるように配置します。

また、この場合、高さを指定しないとレイアウト崩れを起こしてしまうのですが、高さが動的に変化するので、それはjQueryで制御することにします。

デモは以下からどうぞ。

DOMO

HTML5でコーティングしています。jQueryもCSSもHTMLのheadタグ内に書いています。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>[DEMO]dl定義リストを利用してタブパネルをjQueryで作る方法</title>
<script src="js/jquery.js"></script>
<script>
$(function() {
    return $('.tabmenu').each(function() {
        // 現在処理している要素を変数化
        var $wrap = $(this);

        // タブの高さを取得
        var tabHeight = $wrap.find('dt').outerHeight(true);

        // コンテンツの表示位置を指定
        $wrap.find('dd').css({'top' : tabHeight});

        // タブをクリック
        $wrap.find('dt').click(function() {
            // 全てのタブの内容を非表示
            $wrap.find('dd').css({'display' : 'none'});

            // クリックされたタブの内容を表示
            $(this).next('dd').css({'display' : 'block'});

            // タブに設定されている「.selected」を削除
            $wrap.find('dt').removeClass('selected');

            // クリックされたタブに「.selected」を追加
            $(this).addClass('selected');

            // コンテンツの高さを取得
            var conHeight = $(this).next('dd').outerHeight(true);

            // 全体の高さを指定
            $wrap.css({'height' : tabHeight + conHeight});
        });

        // 最初のタブを表示
        $wrap.find('dt:first').trigger('click');
    });
});
</script>
<style>
.tabmenu {
    position:relative;
    width:600px;
    margin:50px auto;
}

.tabmenu dt {
    float:left;
    margin:0 2px 0 0;
    padding:5px 10px;
    background:#ddd;
}

.tabmenu dt.selected {
    background:#eee;
}

.tabmenu dt:hover {
    cursor:pointer;
}

.tabmenu dd {
    position:absolute;
    box-sizing:border-box;
    width:600px;
    margin:0;
    padding:10px;
    background:#eee;
}
</style>
</head>
<body>
<dl class="tabmenu">
    <dt>メニュー1</dt>
    <dd>
    タブメニュー1の中身です。・・・
    </dd>
    <dt>メニュー2</dt>
    <dd>
    タブメニュー2の中身です。・・・
    </dd>
    <dt>メニュー3</dt>
    <dd>
    タブメニュー3の中身です。
    </dd>
</dl>
<dl class="tabmenu">
    <dt>メニュー1</dt>
    <dd>
    タブメニュー1の中身です。・・・
    </dd>
    <dt>メニュー2</dt>
    <dd>
    タブメニュー2の中身です。・・・
    </dd>
    <dt>メニュー3</dt>
    <dd>
    タブメニュー3の中身です。
    </dd>
</dl>
</body>
</html>

同じクラス名のタブがあってもちゃんと別々に動作するように、繰り返し処理をするeach関数や「.find()」を使用しています。

41行目のところで、「.trigger()」を使って、クリックイベントを呼び出して、最初のタブがすでにクリックされた状態にしています。

jQueryで高さを取得しないといけない分、コードが長くなりますね。もし、JavaScriptが効かない場合、レイアウト崩れを起こしてしまうので注意です。そういう意味では、ちゃんとメニュー部分とコンテンツ部分を切り分けてHTMLを組んだほうが無難なのかもしれません。