CSSのみでタブ表示(2)

タブ切り替えコンテンツをJavascriptを使わずにCSSのみで実装する方法を解説します。前回はradioボタンを利用したものを紹介しましたが今回は:targetを利用したものを紹介します。

最小限のHTMLとCSS

最初になんの装飾も施していない、最小限のHTMLとCSSのコードです。

◆HTML
<div class="tab-content">
  <div id="tab1" class="tab">
    <a href="#tab1">タブ1</a>
  </div>
  <div id="tab2" class="tab">
    <a href="#tab2">タブ2</a>
  </div>
  <div id="tab3" class="tab">
    <a href="#tab3">タブ3</a>
  </div>
  <div class="tab-box">
    <div class="tab-view1">コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。</div>
    <div class="tab-view2">コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。</div>
    <div class="tab-view3">コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。</div>
  </div>
</div>
◆CSS
.tab {
  display: inline-block;
}

.tab-box div {
  display: none;
}

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

#tab1:target ~ .tab-box > .tab-view1{
  display: block;
}

#tab2:target ~ .tab-box > .tab-view2{
  display: block;
}

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

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

コードの解説

:target擬似クラス

:targetはURIにおいてhttp://sample.com#tab1の様に#付きで指定された際、アンカーとなる要素に対してスタイルを指定できます。 今回のサンプルの場合、タブをa要素で作成しており、そのリンク先に#tab1を指定することでid=”tab1″の要素に対してスタイルを指定しています。

このサンプルだけなら直接tab-viewの要素を指定して、表示/非表示の切り替えを行うこともできます。 ただし、この方法だと後で装飾をする際に不都合が生じるため、上記の様なコードとなっています。

CSSセレクタ「~」

CSSセレクタの「~」は自分と同じ階層で自分よりも後ろにある要素を指定することができます。
今回は:targetの対象となるdiv要素とタブコンテンツをHTMLにて同じ階層にしておき、:targetの対象divの指定に応じてタブコンテンツの表示も切り替えられるようにしています。

#tab1:target ~ .tab-box > .tab-view1{
  display: block;
}

「URIで#tab1が指定されている時、#tab1要素の後ろにある要素.tab-boxの子要素#tabView1を表示状態にする」
という指定を行っています。

装飾を施す

このままだとアレなんで装飾を施しましょう。
以下がサンプルコードとなります。

◆HTML
<div class="tab-content">
  <div id="tab1" class="tab">
    <a href="#tab1">タブ1</a>
  </div><!--
--><div id="tab2" class="tab">
    <a href="#tab2">タブ2</a>
  </div><!--
--><div id="tab3" class="tab">
    <a href="#tab3">タブ3</a>
  </div>
  <div class="tab-box">
    <div class="tab-view1">コンテンツ1の内容が表示されます。コンテンツ1の内容が表示されます。</div>
    <div class="tab-view2">コンテンツ2の内容が表示されます。コンテンツ2の内容が表示されます。</div>
    <div class="tab-view3">コンテンツ3の内容が表示されます。コンテンツ3の内容が表示されます。</div>
  </div>
</div>
◆CSS
.tab {
  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 a {
  text-decoration: none;
  color: inherit;
}

.tab:hover,
.tab:target {
  color: #FFF;
  background-color: #009900;
}

.tab-box div {
  display: none;
}

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

#tab1:target ~ .tab-box > .tab-view1{
  display: block;
}

#tab2:target ~ .tab-box > .tab-view2{
  display: block;
}

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

HTMLの変更について

HTMLは基本的には変更していませんが、タブ要素用のdivの間にコメントタグを入れています。 読みづらくなりますが、前回も解説したようにインラインブロック要素を横並びにした時にできる余分な隙間を回避するためです。 回避する方法はいくつかあるのですが、今回は間にコメントを入れる形で対応しています。

radio版と:target版どっちがいい?

CSSのみでタブを表現する方法として、radioボタンを利用する方法(前回)と:targetを利用する方法を紹介しました。

お気づきかと思いますが、両者には決定的な違いがあります。 :targetを利用するとURIが変わるという事です。 URIが変わるため、戻るボタンを押すと前の画面ではなく、直前に選択していたタブに戻ります。 また、本記事のサンプルのタブを押したときに気づかれたかもしれませんが、スクロールできる画面の場合はタブをクリックするとスクロールしてしまいます。

このような点から今回紹介した:targetを利用したバージョンを使用する場合、 ページ全体をタブ切り替えするようなケースに向いていると思います。
逆に、ページ内の一部分でタブ切り替えのコンテンツを表示する場合はradioボタンを利用するバージョンが良いかと思います。

ケースによって使い分けましょう!