CSS おれおれ Advent Calendar 2012 – 05日目

だいたいいつもこんな感じで書いてますよ、というものを。それなりに面倒なんですよねー。

完成品

それでは、以下解説。

マークアップ

できるだけシンプルにしたいと思っています。

  • .tab
    • a[href=target].tab-button*
    • article#target.tab-panel*

.tab-button.tab-panelは複数あり、また対になっています。

リンクがul>li>aという構造も考えられますが、ただ並んでいるだけであって、別にリストではないかなと思って、ただただ並べています。

スタイル

タブボタンの基本的な形

.tab-button {
    /* リンクじゃない風 */
    color: inherit;
    text-decoration: none;

    /* タブっぽい枠線 */
    border: 1px #ccc;
    border-style: solid solid none;
    border-radius: 4px 4px 0 0;

    /* タブ間の隙間を殺す */
    float: left;
    margin-right: 1px;

    background-color: #eee;
    line-height: 1em;
    padding: 2px 4px;
}

a要素ではありますが、実際はリンクとして使わないので、color:inheritで通常色にしてtext-decoration:noneで下線も消しています。

タブっぽくするために、枠線borderも追加します。border-styleは下が空いた状態にして、border-radiusを使って角を丸めています。

floatは本来不要なのですが、li要素間の隙間の空白文字を消すために使っています。(HTML上では改行とインデントがあるので、これがテキストノードとしてドキュメントツリーに追加されてしまっています。) これは他の方法で消すようにしても良いでしょう。そもそもHTMLでの改行をやめれば済む話です。

タブパネルの基本的な形

.tab-panel {
    /* タブボタンと同じ形状の枠線 */
    border: solid 1px #ccc;

    /* タブボタンで`float`を使ったので配置を初期化 */
    clear: both;

    /* いきなり見えないように */
    display: none;

    background-color: #f9f9f9;
}

タブボタンと同じ枠線で囲みます。

clearはタブボタンにfloatを設定してしまったせいですね。なかなか邪魔ですね。

ところでタブは上部にボタン状の索引があり、それを選択すると対象のパネルが下部に表示される、というものです。つまりタブパネルは選択されるまで表示されません。なので基本的にdisplay:noneで非表示にします。

タブの切り替え

/* 選択されたら`.active`を付ける */
.tab-button.active {
    /* パネルと同じ背景色 */
    background-color: #f9f9f9;

    /* パネルと一体化 */
    margin-bottom: -1px;
    padding-bottom: 3px;

    font-weight: bold;
}
.tab-panel.active {
    /* 選択されたら見える */
    display: block;
}

続いてボタンで選択されたものをどうするか、ですが、選択された状態を表すクラスを追加する事にします。JavaScriptから、ボタンが押されるたびにこのクラスを移してゆけば良いでしょう。選択状態のものを.activeで表す事にします。このクラスが与えられたタブボタン、タブパネルは表示を変えます。

選択状態のタブパネルは当然画面に表示させる必要がありますので、display:blockを設定します。

最後に、選択状態のタブボタンは、タブパネルと繋がって見えるようにしたいですね。そこでpadding-bottomを元の2pxに1px加えて3pxとし、さらにmargin-bottom:-1pxのようにネガティブマージンを使って、パネルを引き上げます。そして背景色をパネルと同じにしておけば、そこだけ線が切れて繋がっているように見えます。

これでCSSは完成。

初期選択

あとは先頭のタブボタンとタブパネルに.activeを与えておきましょう。

スクリプト

CSSの話をしたいので簡単にお話しすると、事前にタブのボタンとパネルの順序を合わせておいて、n番目のボタンを押されたらn番目のパネルを表示する、という方針です。

詳細はデモのコードを見てみてください。

おしまい

というわけで、タブCSSの実装例でした。

え、せっかくならJavaScriptなしで、タブもCSSだけで実装したい? ふうん、しょうがないなあ……。