CSSのみでタブ表示

タブ切り替えコンテンツをJavascriptを使わずにCSSのみで実装する方法を解説します。いくつか方法がありますが、今回はradio要素の:checkを利用した方法をご紹介したいと思います。

最小限のHTMLとCSS

いきなりですが、CSSのみでタブを実装するHTMLとCSSです。
なんの装飾もしていない最小限のコードです。

◆HTML
<div class="tab-content">
  <input type="radio" id="tab1" name="tab" checked >
  <label for="tab1">タブ1</label>
  <input type="radio" id="tab2" name="tab">
  <label for="tab2">タブ2</label>
  <input type="radio" id="tab3" name="tab">
  <label for="tab3">タブ3</label>
  <div class="tab-box">
    <div id="tabView1">コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。</div>
    <div id="tabView2">コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。</div>
    <div id="tabView3">コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。</div>
  </div>
</div>
◆CSS
.tab-content input[type="radio"] {
  display: none;
}

.tab-content .tab-box {
  width: 250px;
  height: 100px;
  border: 1px solid #AAA;
}

.tab-content > .tab-box > div {
  display: none;
}

#tab1:checked ~ .tab-box > #tabView1 {
  display: block;
}

#tab2:checked ~ .tab-box > #tabView2 {
  display: block;
}

#tab3:checked ~ .tab-box > #tabView3 {
  display: block;
}
◆サンプル
コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。
コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。
コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。

意外と少ないコード量で表現できますね。
あくまで最小限ですので、ここから各々サイトデザインにマッチした装飾を施しましょう。
簡単な装飾したコードも後で紹介しますが、先に上記のコードを軽く解説しておきます。

コードの解説

radio要素は非表示にしてlabel要素で制御する

ここでは制御にラジオボタンを使用していますが、ラジオボタンが表示されてしまうとタブ表示としてはおかしな表示となってしまうため非表示にしています。
では、どうやってラジオボタンを制御しているかというとlabel要素を使用しています。

labelのfor属性にチェックボックスやラジオボタンのidを指定しておくと、label要素をクリックしたときに対象のコントロールを操作してくれます。 この挙動を利用してタブを表現しています。

<input type="radio" id="tab1" name="tab" checked> <!-- 非表示にする -->
<label for="tab1">タブ1</label> <!-- for属性でtab1のradioボタンを制御する -->

CSSセレクタ「~」とは

CSSセレクタの「~」は自分と同じ階層で自分よりも後ろにある要素を指定することができます。
radio要素とタブコンテンツを同じ階層にしておき、:checkedと組み合わせて、チェックされているときのみ対象のコンテンツを表示するようにしています。

#tab1:checked ~ .tab-box > #tabView1 {
  display: block;
}

「tab1のラジオボタンがチェックされているとき、後ろにある要素.tab-boxの子要素#tabView1を表示状態にする」
という指定を行っています。

装飾を施す

では最後に最小限のコードに対して装飾を施しましょう。

◆HTML
<div class="tab-content">
  <input type="radio" id="tab1" name="tab" checked><label for="tab1">タブ1</label><input type="radio" id="tab2" name="tab"><label for="tab2">タブ2</label><input type="radio" id="tab3" name="tab"><label for="tab3">タブ3</label>
  <div class="tab-box">
    <div id="tabView1">コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。</div>
    <div id="tabView2">コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。</div>
    <div id="tabView3">コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。</div>
  </div>
</div>
◆CSS
.tab-content input[type="radio"] {
  display: none;
}

.tab-content label {
  display: inline-block;
  padding: 5px 10px;
  font-weight: bold;
  font-size: 13px;
  color: #009900;
  background-color: #e1fae1;
  cursor: pointer;
  box-shadow: inset -1px 1px 2px rgba(0, 0, 0, 0.3);
  border-radius: 5px 5px 0 0;
  box-sizing: border-box;
}
.tab-content label:hover,
.tab-content input[type="radio"]:checked + label {
  color: #FFF;
  background-color: #009900;
}

.tab-content .tab-box {
  width: 250px;
  height: 100px;
  padding: 10px;
  border: 2px solid #009900;
  border-radius: 0 5px 5px 5px;
  box-sizing: border-box;
}

.tab-content > .tab-box > div {
  display: none;
}

#tab1:checked ~ .tab-box > #tabView1 {
  display: block;
}

#tab2:checked ~ .tab-box > #tabView2 {
  display: block;
}

#tab3:checked ~ .tab-box > #tabView3 {
  display: block;
}
◆サンプル
コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。
コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。
コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。

HTMLは内容の変更はありませんが、radioとlabelタグの行の改行を削除しています。 ソースコードは見にくくなってしまいますが、これをしておかないとタブとタブの間に隙間ができてしまいます。

これはインラインブロック要素を横並びにした時にできてしまう隙間で、対処方法はいくつかあるのですが、ここでは間の改行を削除することで隙間が表示されないようにしています。