タブメニューをCSSだけで作る方法

はじめに

以前コーディングを担当した案件でCSSでタブメニューを作ったことがあります。

しかし最近はタブメニューを作る機会が無く、このまま時間が経つと作り方を忘れてしまいそうだったので自分のために作り方をまとめました。

仕上がりイメージ

1つめのコンテンツ

2つめのコンテンツ

目次

タブメニューの仕組みと制作の流れ

CSSで作るタブメニューの仕組みは以下のとおりです。

  • タブ(label)をクリックする
  • タブに連動したラジオボタンにチェックが入る
  • チェックが入ったラジオボタンに連動したコンテンツが表示される
  • それ以外のコンテンツは非表示

制作の流れは以下のような感じになります。

  • ラジオボタン<input type="radio">をタブの数だけ作る
  • タブ(label)を必要な数だけ作る
  • コンテンツをタブと同じ数だけ作る
  • タブをクリックするとラジオボタンにチェックが入るようHTMLを設定する
  • チェックが入ったタブのコンテンツのみ表示するよう、CSSを設定する

説明するより実際にソースを見て頂いた方が分かりやすいと思いますので以下のソースをご確認下さい。

HTML

<input id="radio01" type="radio" class="p-radio" name="tabmenu" checked>
<input id="radio02" type="radio" class="p-radio" name="tabmenu">
<div class="p-tabmenu_head">
	<label for="radio01" class="p-tab_btn01">ボタン1</label>
	<label for="radio02" class="p-tab_btn02">ボタン2</label>
</div>
<div class="p-tabmenu_body">
	<div class="p-tab_cont01">
		<p>1つめのコンテンツ</p>
	</div>
	<div class="p-tab_cont02">
		<p>2つめのコンテンツ</p>
	</div>
</div>

次にもう少し細かく分割して説明します。

タブ部分を作る

上記HTMLのボタン部分にフォーカスして見て下さい。

ソースをなるべくシンプルに見せたいので、いったんClassを外してみます。

HTML(Classを削除)

<input id="radio01" type="radio" name="tabmenu" checked>
<input id="radio02" type="radio" name="tabmenu">
<div>
	<label for="radio01">ボタン1</label>
	<label for="radio02">ボタン2</label>
</div>

それぞれのラジオボタンにidを設定し、<label for="radio0*">labelをクリックすると連動したidにチェックが入るようにします。

id="radio01"のラジオボタンにcheckedを設定し、初期でコンテンツが表示されるようにします。

できあがったもの

CSSで装飾していないのでデザイン的に少し分かりにくいですが、「ボタン1」「ボタン2」をクリックすると、それと連動したラジオボタンにチェックが入ります。

次に、ボタンをクリックすると連動するコンテンツが表示されるようにします。

タブメニューとコンテンツの表示・非表示を調整する

最初に記述したHTMLを改めて記述しておきます。

HTML

<input id="radio01" type="radio" class="p-radio" name="tabmenu" checked>
<input id="radio02" type="radio" class="p-radio" name="tabmenu">
<div class="p-tabmenu_head">
	<label for="radio01" class="p-tab_btn01">ボタン1</label>
	<label for="radio02" class="p-tab_btn02">ボタン2</label>
</div>
<div class="p-tabmenu_body">
	<div class="p-tab_cont01">
		<p>1つめのコンテンツ</p>
	</div>
	<div class="p-tab_cont02">
		<p>2つめのコンテンツ</p>
	</div>
</div>

上記HTMLをもとに、改めて行いたい処理は以下のとおりです。

  • id="radio01"のラジオボタンにチェックが入ったらp-tab_cont01を表示させる
  • id="radio02"のラジオボタンにチェックが入ったらp-tab_cont02を表示させる
  • チェックが入っていないコンテンツは非表示にする

これを実現させるには、CSSを以下のように設定します。

CSS

/*初期段階ではチェックが入っていないコンテンツは非表示*/
.p-tab_cont01,
.p-tab_cont02 {
	display: none;
}
/*チェックが入っているIDに連動したコンテンツを表示する*/
#radio11:checked ~ .p-tabmenu_body .p-tab_cont01,
#radio12:checked ~ .p-tabmenu_body .p-tab_cont02 {
	display: block;
}
/*チェックが入っているボタンの色を変更する*/
#radio11:checked ~ .p-tabmenu_head .p-tab_btn01,
#radio12:checked ~ .p-tabmenu_head .p-tab_btn02 {
	background: #333;
	color: #fff;
}

こんな感じです。

上記のCSSだけを設定すると以下のようになります。

できあがったもの

1つめのコンテンツ

2つめのコンテンツ

これで、チェックが入ったラジオボタンに連動したコンテンツのみが表示されるようになりました。

あとはCSSで全体を整えれば完成です。

CSSで全体を整える

以下のようにCSSを設定しました。

CSS

/*ラジオボタンは非表示にする*/
.p-radio {
	display: none;
}
/*タブメニュー全体の配置*/
.p-tabmenu_head {
	display: flex;
	align-items: stretch;
	justify-content: center;
	gap: 1rem;
}
/*タブメニューのボタンの装飾*/
.p-tabmenu_head .p-tab_btn01,
.p-tabmenu_head .p-tab_btn02 {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 200px;
	height: 40px;
	color: #444;
	background: #ddd;
	cursor: pointer; /*デフォルトではマウスオーバーでマウス表示が切り替わらない*/
	user-select: none;
}
/*コンテンツ部分の大枠の設定*/
.p-tabmenu_body {
	border: 4px solid #ccc;
	padding: 20px;
	box-sizing:border-box;
}
/*チェックが入っていないコンテンツは非表示*/
.p-tab_cont11,
.p-tab_cont12 {
	display: none;
}
/*チェックが入っているIDに連動したコンテンツを表示する*/
#radio11:checked ~ .p-tabmenu_body .p-tab_cont01,
#radio12:checked ~ .p-tabmenu_body .p-tab_cont02 {
	display: block;
}
/*チェックが入っているボタンの色を変更する*/
#radio11:checked ~ .p-tabmenu_head .p-tab_btn01,
#radio12:checked ~ .p-tabmenu_head .p-tab_btn02 {
	background: #333;
	color: #fff;
}

上記設定をしたタブメニューが以下のとおりです。

できあがったもの

1つめのコンテンツ

2つめのコンテンツ

注意点

注意点といいますか、私が初めてタブメニューを作った時、どうしてもボタンと表示の連動が上手くいかなくて苦労しました。

試行錯誤して分かったのですが、CSSにある~(一般兄弟結合子)がクセ者で、これがあると兄弟要素内(同じディレクトリ)の要素でないとCSSが適用されません。

「じゃあ一般兄弟結合子を外したら良いじゃない」と思いますが、これを外すと関係のないタブメニューが誤作動してしまうのではないかと思います(試してないけど)。

自分なりにアレンジしたらタブメニューの実装ができなくなった場合は、input等のディレクトリを調整すると上手くいくかもしれません。