CSSだけで作るタブメニューとウィジェット
スペース的に最初から表示はしたくないけど、必要に応じて見せたいときに便利なタブメニュー。こちらをCSSだけで実装し、更にウィジェットと組み合わせて自由度の高いメニューを作ってみる方法を解説します。
ちなみに探してみましたが、スマートに導入できる既存のプラグインは見つけられませんでした。面倒なのでjavascript系も入れたくないという方にもおすすめです。
CSSでタブメニュー
わかりやすいのはこちらのサイト。
https://web.monogusa-note.com/flexible-tabs-only-css
仕組みとしてはHTMLでinputタグのラジオボタンを使っています。ラジオボタンは選択肢の中から1個だけ選べるタイプのフォームツール。選択されると<input>タグの中にcheckedがつくので、それをCSSで拾って表示/非表示を切り替えるというもの。CSSは隣接セレクタを使用していることが中々秀逸。
1 2 3 4 5 6 7 8 9 10 11 |
<nav class="tab-menu"> <input id="tabmenu-1" type="radio" name="tab_item" checked="checked"> <label class="tab_item" for="tabmenu-1">Info</label> <div class="tab">タブの中身1</div> <input id="tabmenu-2" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-2">Story</label> <div class="tab">タブの中身2</div> <input id="tabmenu-3" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-3">Menu</label> <div class="tab">タブの中身3</div> </nav> |
1 2 3 4 5 |
.tab-menu {display:flex;flex-wrap:wrap;} .tab-menu input{display:none;} .tab-menu label{order:-1;} .tab-menu .tab{display:none;} .tab-menu input:checked+label+.tab{display:block;width:100%;} |
一番外側のラップは<nav>タグでも<div>タグでもいいです。<input>タグは隠して<label>タグの隣接要素を表示するようにしています。CSSで最低限必要なのはこんな感じでしょうか。この場合はインプットとラベル、その中身が交互に来ていますが、<label>タグに{order:-1;}を指定することでラベルだけ先に表示します。後はマウスオーバー時の装飾だったり、必要なものを追加します。
1 2 3 4 5 6 7 8 9 10 11 |
<nav class="tab-menu"> <input id="tabmenu-1" type="radio" name="tab_item" checked="checked"> <label class="tab_item" for="tabmenu-1">Info</label> <input id="tabmenu-2" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-2">Story</label> <input id="tabmenu-3" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-3">Menu</label> <div id="tab-1">タブの中身1</div> <div id="tab-2">タブの中身1</div> <div id="tab-3">タブの中身1</div> </nav> |
1 2 3 4 5 6 7 |
.tab-menu {display:flex;} .tab-menu input{display:none;} .tab-menu label{} .tab-menu .tab{display:none;} .tab-menu input#tabmenu-1:checked~#tab-1{display:block;width:100%;} .tab-menu input#tabmenu-2:checked~#tab-2{display:block;width:100%;} .tab-menu input#tabmenu-3:checked~#tab-3{display:block;width:100%;} |
こちらは別パターン。ラベルを先に並べて、その中身を後に並べています。こちらの場合はタブの中身に1つずつ固有のIDかクラスをふっておかないと指定しにくいですが、一応これでも対応可能。
ちなみにこの表示の切り替え、visibility:hidden;でも同じようなことが出来ますし、そちらの方がアニメーション(Transition)も付けることが出来ますが、多めの折りたたみでは余計な余白がページ下部にできてしまうようで、今回はdisplay:none;としています。
ウィジェット化する
タブメニューができたら中身をウィジェットにしたいなと欲が出てきました。
やってみたのは3パターン。
①テーマ内でウィジェットエリアの記述の前にインプットとラベルを並べる
これは最終的な出力が上のコードで言うと下のパターンになるやり方です。とりあえずならこれが一番手っ取り早いですが、ウィジェットを設置するたびに、ウィジェットのはき出すタグを見て、CSSのIDかクラスを変更しないといけないので柔軟性が低いです。
②functions.php内でウィジェットのタグの出し方を指定
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php register_sidebar( array( 'name' => __( 'Sidebar name', 'theme_text_domain' ), 'id' => 'unique-sidebar-id', 'description' => '', 'class' => '', 'before_widget' => '<li id="%1$s" class="widget %2$s">', 'after_widget' => '</li>', 'before_title' => '<h2 class="widgettitle">', 'after_title' => '</h2>' )); ?> |
functions.php内でウィジェットエリアを定義するregister_sidebar()ではウィジェットの前後にはき出すタグをしてすることが出来ます。ここで<input>と<label>をくっつけてもOKです。これだと配置したウィジェットを自動的に指定するので、管理が現実的になります。ただし、1タブに1ウィジェットしか配置出来ません。1タブに更に複数のウィジェットを配置したい場合は次のパターンになります。
③タブごとにウィジェットエリアを指定する
1 2 3 4 5 6 7 8 9 10 11 |
<nav class="tab-menu"> <input id="tabmenu-1" type="radio" name="tab_item" checked="checked"> <label class="tab_item" for="tabmenu-1">Info</label> <ul class="tab-widget"><?php dynamic_sidebar('tab-widget1') ;?></ul> <input id="tabmenu-2" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-2">Story</label> <ul class="tab-widget"><?php dynamic_sidebar('tab-widget2') ;?></ul> <input id="tabmenu-3" type="radio" name="tab_item"> <label class="tab_item" for="tabmenu-3">Menu</label> <ul class="tab-widget"><?php dynamic_sidebar('tab-widget3') ;?></ul> </nav> |
ウィジェットじゃなくてウィジェットエリアを設定します。これでもっと使いやすくなりました。只今サイトのトップではこのような形で実装しています。
まとめ
ということでCSSだけでウィジェットエリアをタブメニュー化することが出来ました。意外と何でも出来ちゃいますね。ぜひお試しを。