【CSS】タブメニューをCSSだけでシンプルに作る【動作実例付き】


タブメニュー をJavaScriptを使わず、CSSだけで作ってみます。
また、わかりやすいよう 体裁に凝らず、なるべくミニマムな設定で、
幹の部分だけ書いて実現してみます。

また、動作イメージ(アニメーション付き)や 想定イメージ
も用意しています。

外観構成

タブタグ、その下に中身のタグがあると想定します。 その2つを .全体のタグで囲みます。

全体
タブ見出し タブ見出し タブ見出し
中身

やりかた

マウスをタブ見出しに置いたら中身が見えるやり方と、
クリックした時に中身が見えるやり方があると思います。

それをCSSで実現するには、チェックした時に、内容を書いた段落が消えたり、出たりするようにするため、 ページのタブ見出しと中身が親子か兄弟の関係にある必要があります。

タブ見出しクリックしたら、タブ見出しの色を変えたいので、クリック方式を考えてみようと思います。

その1 ラジオボタン方式

設計ポイント

クリックに反応させる

そのために、 radioを使う。さらにラジオボタン自体は非表示にし、radioに対応するlabelを使ってタブの見出しを表示します。 最近のcssには:targetというタグもあるので、それを使うと radioを使わなくても楽にできますが、:focusタグが aの部分しかできないため、タブ見出しの見た目の制御が難しいです。それを気にしなければ、一番シンプルかもしれません。

中身は、見えないようにして、クリックしたら表示させる

visibilityで切り替えます。合わせて背景色も切り替えます。z-index (大きい方が上)は、必要ないので使わずに 代わりにわかりやすい表示切替ON/OFFのプロパティを使います。 3つ以上の順序を意識して重ねあわせる必要ないですからね。

チェックしたかに合わせて表現する

:check を使います。また :checkと関連のある タグを + や~を使って兄弟関係となる中身(content)を指定します。

以上の構成を満たすためのHTMLを考える。

タブ見出しを liにし、タブ見出しごとliの中に radio , label , 中身(content)の3つを用意します。

 ひとつのリスト: li
input radio (見せない)

タブ見出し label

中身 content
 ひとつのリスト: li
input radio (見せない)

タブ見出し label

中身 content
 ひとつのリスト: li
input radio (見せない)

タブ見出し label

中身 content

おまけでアニメーションを使う。

表示非表示を displayではなく、visiblityにし、 absolute のpositionで位置を重ねます。(デメリットとしては、内容の部分の高さが下のコンテンツに重なるため、一定量空白が必要になります(マージンや改行等で調整)。top ,left で 中身(content)の部分を微調整します。 check前後で背景色を変えています。

実行例

  • ~~~~~~~~~~
    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
  • page2 aaaaaaaaaaa ~~~~~~~~~~
    ~~~~~DDDDDDDDDDDDD~~~~ ~~~~~~OOOOOOOO
    ~~~~~~~~~~~~~
    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
  • page3 AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
    ~~~~~~~~~~
    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
  • page4 ~~~~~~~~~~
    ~~~~~HHHHHHHHHHHHHH~~~~ ~~~~~~LLLLL~~~~~~~~~~~~
    AADDD OOOOOOOOO ``````````AA

cssとHTMLソースを以下に示します。

          
            tabs. * {
                margin: 0;
                padding: 0;
            }
            .tabs li{
                float:left;
                list-style: none;
            }
            .tabs{
                position:relative;
            }
            .tabs input[type="radio"]{
                display:none;
            }
            .tabs label{
                background: #7a7;
                transition: all 0.7s;
                margin:3pt;
                padding:3pt;
            }
            .tabs label:hover{
                background: #aea;
            }
            .tabs .content {
                position:absolute;
                top:24px;
                left:0;
                width:75%;
                visibility: hidden;
                opacity :0.15;
                background: #cfc;
                transition: opacity 1s;
            }

            .tabs [id^="page"]:checked + label {
                background: #cfc;
            }
            .tabs [id^="page"]:checked ~ [class^="content"] {
                visibility: visible;
                opacity:1.0;
            }

    
      <ul class="tabs">
          <li>
            <input type="radio" name="tabs" id="page1" checked/>
            <label for="page1">Page1</label>
            <div class="content" id="page1">
                                    ~~~~~~~~~~<br>
                    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
            </div>
          </li>
          <li>
            <input type="radio" name="tabs" id="page2"/>
            <label for="page2">Page2</label>
            <div  class="content" id="page2">
                     page2       aaaaaaaaaaa    ~~~~~~~~~~<br>
                    ~~~~~DDDDDDDDDDDDD~~~~ ~~~~~~OOOOOOOO<br>
                    ~~~~~~~~~~~~~<br>
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
            </div>
          </li>
          <li>
            <input type="radio" name="tabs" id="page3"/>
            <label for="page3">Page3</label>
            <div  class="content" id="page3">
                    page3 
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                                   ~~~~~~~~~~<br>
                    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
            </div>
          </li>                            
          <li>
            <input type="radio" name="tabs" id="page4"/>
            <label for="page4">Page4</label>
            <div  class="content" id="page4">
                         page4           ~~~~~~~~~~<br>
                    ~~~~~HHHHHHHHHHHHHH~~~~ ~~~~~~LLLLL~~~~~~~~~~~~<br>
                    AADDD  OOOOOOOOO ``````````AA<br>
            </div>
          </li>
     </ul>

その2 マウスオーバ(hover)を使う

設計ポイント

やりかたは 上記のchecked を hoverにするだけです。

あとは中身となるcontent自体に hoverで反応するようにし、
タブ見出しと contentをぴったり隣り合わせに調整します(そうしないと、タブからcontentに移動した時にcontentが消え、マウスオーバできなくなる)。

radio周りはHTML/cssとも削除しても動くと思います。

            .tabs [id^="page"]:hover + label {
                display: block;
                background: #7a7;
            }
            .tabs label:hover ~ [class^="content"] {
                visibility: visible;
                opacity:1.0;
            }
            div.content:hover{
                visibility: visible;
                opacity:1.0;            
            }

実行例

    • ~~~~~~~~~~
      ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
      AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
    • page2 aaaaaaaaaaa ~~~~~~~~~~
      ~~~~~DDDDDDDDDDDDD~~~~ ~~~~~~OOOOOOOO
      ~~~~~~~~~~~~~
      AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
    • page3 AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
      ~~~~~~~~~~
      ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
    • page4 ~~~~~~~~~~
      ~~~~~HHHHHHHHHHHHHH~~~~ ~~~~~~LLLLL~~~~~~~~~~~~
      AADDD OOOOOOOOO ``````````AA

その3 リストを使わない見た目とHTML構成を合わせる。

今回はHTMLのソース上タブ見出しを上に並べ、本文を下に固めます。HTMLソース上長ったらしかったのが、今回の修正で、構成が見やすくなります。
表示上は、liでタブ見出しが横に並んでいるのですが、中身はその下にあります。HTML側ではタブ見出しとセットなので、ちょっと複雑でメンテナンス性が悪いです(やり方次第ですが)。

また、radio で先ほど実現した方式では、下がうまくレイアウトされずに重なってしまいます。今回のケースだと、次の兄弟とのオーバーラップを気にしないで済みます。

そこで、最近のcssでは兄弟関係を表現できるようになったので、タブ見出しと本文を並列に要素を並べてみます。

設計ポイント

リストをやめ、divを並列にする。
absolute要素をやめる。メニューの中身が下側で重ならないようになる。

上記の変更に対応するため、
checkされた div要素だけ 表示するようにする。 (cssの~ で並列要素を指定)
(残念ながらdisplay noneにするためアニメーションがなくなる)

実行例

~~~~~~~~~~
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
page2 aaaaaaaaaaa ~~~~~~~~~~
~~~~~DDDDDDDDDDDDD~~~~ ~~~~~~OOOOOOOO
~~~~~~~~~~~~~
AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
page3 AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA
~~~~~~~~~~
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
page4 ~~~~~~~~~~
~~~~~HHHHHHHHHHHHHH~~~~ ~~~~~~LLLLL~~~~~~~~~~~~
AADDD OOOOOOOOO ``````````AA

コード:主な変更点

            .tabs .content {
                visibility: collapse;
                top:24px;
                left:0;
                width:80%;
                display:none;
                opacity :0.15;
                background: #ffeeee;
                transition: opacity 1s;
                margin:3pt;
                padding:3pt;
            }

            .tabs [id^="page"]:checked + label {
                background: #ffeeee;
            }
            .tabs [id="page1"]:checked ~ [id="page1"] {
                display:block;
            }
            .tabs [id="page2"]:checked ~ [id="page2"] {
                display:block;
            }
            .tabs [id="page3"]:checked ~ [id="page3"] {
                display:block;
            }
            .tabs [id="page4"]:checked ~ [id="page4"] {
                display:block;
            }
              
    
      <div class="tabs">
            <input type="radio" name="tabs" id="page1" checked/>
            <label for="page1">Page1</label>
            <input type="radio" name="tabs" id="page2"/>
            <label for="page2">Page2</label>
            <input type="radio" name="tabs" id="page3"/>
            <label for="page3">Page3</label>
            <input type="radio" name="tabs" id="page4"/>
            <label for="page4">Page4</label>
            <br>
            
            <div class="content" id="page1">
                                    ~~~~~~~~~~<br>
                    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
            </div>
            <div  class="content" id="page2">
                     page2       aaaaaaaaaaa    ~~~~~~~~~~<br>
                    ~~~~~DDDDDDDDDDDDD~~~~ ~~~~~~OOOOOOOO<br>
                    ~~~~~~~~~~~~~<br>
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
            </div>
            <div  class="content" id="page3">
                    page3 
                    AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                                   ~~~~~~~~~~<br>
                    ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
            </div>
            <div  class="content" id="page4">
                         page4           ~~~~~~~~~~<br>
                    ~~~~~HHHHHHHHHHHHHH~~~~ ~~~~~~LLLLL~~~~~~~~~~~~<br>
                    AADDD  OOOOOOOOO ``````````AA<br>
            </div>
         </div>

その4 リンク(:target)制御

タブ見出しを a にすると  :targetを使って、 リンク先(id)をcss指定することができます。

こちらは、HTML構成を考える必要はそれほどありません。ただ、リンク元のタブ見出しが制御しづらいのと、aタグを使う必要が有るため、そこが見た目がちょっとよくありません。更にスクロール制御する必要が出てきます。

実行例

コード:主な変更点

      <table border=0>
          <tr>
              <td><a href="#page1">Page1</a></td>
              <td><a href="#page2">Page2</a></td>
              <td><a href="#page3">Page3</a></td>
              <td><a href="#page4">Page4</a></td>
          </tr>
         <tr id="" >
              <td colspan=4>
                  <div id="page1">
                                        ~~~~~~~~~~<br>
                  ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                  AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                  </div>
                  <div id="page2">
                  page2                      ~~~~~~~~~~<br>
                  ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                  AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                  </div>
                  <div id="page3">
                   page3                 ~~~~~~~~~~<br>
                  ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                  AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                  </div>
                  <div id="page4">
                    page4                ~~~~~~~~~~<br>
                  ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~<br>
                  AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA<br>
                  </div>
              </td>
          </tr> 

      </table>

            :target {
                display: block !important;
                background-color : #ffeeee;            
            }
            :active {
                background-color: #ffeeee;
            }
            table tr td {
                background-color: #eeaaaa;
            }
            table tr td a{
                width :100%;
            }
            #page1,#page2,#page3,#page4 {
                display: none;
            }      

もう少し制御するには、absoluteを指定しますが、その1と同じように下に分が続く制御がまた別途必要になります。

まとめ

1番目のやり方だと、ギャップが出てしまうので、ul等でマージンを下に取る必要がありますが一通り制御可能です。
2番目,4番目のやり方だと、クリックした情報がなくなるので、タブの色がうまく制御できませんが、作りがシンプルです。
3番目のやり方だと、コンテンツのアニメーションがなくなってしまいますが、見た目とのギャップがそれほど違いがなく、他の人でもメンテしやすいです。cssはいまいちメンテが面倒です。

もう少し、発展形が必要かもしれませんね。

関連ページリンク

【かっこいい】よく見る商品紹介ページのダイナミックなスクロール表示をCSSだけでシンプルに試す【実例付き】

画像見出しの上に、キャプションを透明ラベルでオーバラップする方法【CSS】

CSSでカードレイアウトがどこまで出来るか試してみた

CSSだけでモーダルダイアログをシンプルに実現してみる

【CSS】CSSだけで 和風の絵を描いてみる

おまけ

Document
◆Document1
XXX
◆Document2
YYY
◆Document3
ZZZ
◆Document4
KKK
--- github
Delicious にシェア
Digg にシェア
reddit にシェア
LinkedIn にシェア
LINEで送る
email this
Pocket

7,561 views.



One thought on “【CSS】タブメニューをCSSだけでシンプルに作る【動作実例付き】

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です