いくつかやり方がありますが、結論から言ってしまうと、ボタンのカレントやアンカーの問題、マークアップの自由度を考えると、JavaScriptを使うことをお勧めいたします。 それでも「CSSでやりたい!」という状況があると思うので、まとめてみました。

CSSのタブ切り替えは、2種類

CSSで行えるタブ切り替えの方法は、2種類あります。

  • 「:checked」を使用したもの
  • 「:target」を使用したもの

どちらもIE9以降から使えます。 (:checkedの方は、Androidで問題があるという話を聞きましたが、シミュレータのAndroid4.4では大丈夫でした) 仕様としては、一長一短といったところがあります。 見ていきましょう。

checked

radioボタンと:checkedを利用して、タブ切り替えを行います。 radioボタンの代わりにlabelを使うと、良い感じで押せるようになります。 デモはここから ポイントはradioボタンの:checkedに関連した要素を、隣接セレクタ (E + F)と間接セレクタ (E ~ F)で、スタイルを変えるところです。 細かい部分は、デモを参考にしてください。 マークアップは、radioボタンごとにそれに関する要素を近づけることです。

<ul class="tabsetIn checktab">
    <li>
        <input id="tab1" type="radio" name="radio" value="" checked="checked" />
        <label class="btn" for="tab1">名前1</label>
        <div class="contents">内容1</div>
    </li>
    <li>
        <input id="tab2" type="radio" name="radio" value="" />
        <label class="btn" for="tab2">名前2</label>
        <div class="contents">内容2</div>
    </li>
    <li>
        <input id="tab3" type="radio" name="radio" value="" />
        <label class="btn" for="tab3">名前3</label>
        <div class="contents">内容3</div>
    </li>
</ul>
.checktab > li{float:left; margin-right: 5px;}

.checktab .btn{display: block; width: 80px; line-height: 30px; padding: 10px; background-color: #ccc; cursor:pointer;}
.checktab .btn:hover{background-color: #000; color: #fff;}
.checktab input[type="radio"]{ display: none;}
.checktab input[type="radio"]:checked ~ .contents{display:block;}
.checktab input[type="radio"]:checked + .btn{background-color:#fff; cursor:default; color: #000;}
.checktab .contents{position: absolute; top: 50px ; left: 0; display: none;}

メリット あらかじめHTML内にchecked=”checked”(もしくはcheckedのみでも可)と入れておくことで、カレント表示を設定できるのが便利。 マークアップに気を付ければ、シンプルに実装できる。 デメリット checkedを使うためには、radioボタンの兄弟、子、子孫にボタンやコンテンツを配置しなくてはならず、マークアップに制限が出てしまう。 その場合、絶対配置でレイアウトする可能性が高いため、高さを明示的に指定しないと、後に続く要素を配置できない。

target

アンカーを切り替えた時、targetを使って、選ばれたアンカーIDを元にスタイルを変更します。 また、履歴として登録されるので、ブラウザのバックボタンでタブが切り替わります。 デモはここから こちらは、ボタンとコンテンツを別にマークアップすることができます。 切り替えるためのアンカーIDを入れ子にすることで、子孫セレクタ(E F)の優先度を利用して、カレントのボタンを設定することができます。 細かい部分は、デモを参考にしてください。

<div class="tabsetIn targettab">
    <div class="tabnav" id="tabnav1">
    <div class="tabnav" id="tabnav2">
    <div class="tabnav" id="tabnav3">

        <div class="tabgroup targettab1">
            <div class="btn"><a href="#tabnav1">名前1</a></div>
            <div class="contents">内容1</div>
        </div>
        <div class="tabgroup targettab2">
            <div class="btn"><a href="#tabnav2">名前2</a></div>
            <div class="contents">内容2</div>
        </div>
        <div class="tabgroup targettab3">
            <div class="btn"><a href="#tabnav3">名前3</a></div>
            <div class="contents">内容3</div>
        </div>
        
    </div>
    </div>
    </div>
</div>
.targettab .btn{ float: left; margin:0 5px -1px 0; width: 100px;}

.targettab #tabnav2:target .targettab1 .btn a,
.targettab #tabnav3:target .targettab1 .btn a,
.targettab .btn a{display: block; line-height: 30px; padding: 10px; background-color: #ccc; cursor:pointer; }

.targettab #tabnav2:target .targettab1 .btn a:hover,
.targettab #tabnav3:target .targettab1 .btn a:hover,
.targettab .btn a:hover{background-color: #000; color: #fff;}

.targettab .targettab1 .btn a,
.targettab #tabnav1:target .targettab1 .btn a,
.targettab #tabnav2:target .targettab2 .btn a,
.targettab #tabnav3:target .targettab3 .btn a{background-color:#fff; cursor:default; color: #000;}

.targettab .contents{display: none; position: absolute; left: 0; top:50px;}

.targettab .targettab1 .contents{display: block;}

.targettab #tabnav1:target .targettab1 .contents,
.targettab #tabnav2:target .targettab2 .contents,
.targettab #tabnav3:target .targettab3 .contents{ display: block;}

メリット checkedと比べて比較的マークアップが自由。 デメリット 指定したアンカーIDのタグを入れ子にしないと、カレント表示の設定が面倒。 スクロール位置が変わり、URLでぺージを管理しているサイトだと使いにくい。

まとめ

高さの変化に問題が無ければ、checkedが良いです。 targetはマークアップの観点から見ると悪くないですが、アンカーの切り替わりによるデメリットが大きいです。 それが問題ない状況であれば、targetでも問題ないでしょう。 細かい調整をしたいのであれば、残念ながらJavaScriptを使ったほうが早そうです。 では、そんな感じで、またねー。

6ステップでマスターする 「最新標準」HTML+CSSデザイン
エビスコム
マイナビ出版 (2016-08-30)
売り上げランキング: 129,614