「タブ切り替えを作りたいけど、JavaScriptを書くのはちょっと大げさかも…」
そんなときは、HTMLとCSSだけでもタブ切り替えを実装できます。
この記事では、ブラウザ対応の広い「:checked版」と、コードをスッキリ書ける「:has()版」の2つの方法を紹介します。
どちらもコピペで試せるサンプル付き。さらに、均等幅・吹き出し風・丸ボタン風などのカスタマイズ例や、WordPressで実装するときの注意点もまとめました。
まずは動くコードを試しながら、自分のサイトに合ったタブ切り替えを作ってみましょう。
HTMLとCSSだけで実現!タブ切り替えの実装方法
ここでは次の2つの方法を紹介します。
- :checked版 → ブラウザ対応が広く、実用向き
- :has版 → モダンな書き方でスッキリ
| 項目 | :checked版 | :has版 |
|---|---|---|
| 書き方 | input → label → content の順が必須 | 構造の自由度が高い |
| コード量 | 少し長い | スッキリ |
| ブラウザ対応 | 広い(古い環境でもOK) | モダンブラウザ |
| 実用度 | 高い(商用向け) | 今後の主流になる書き方 |
今なら基本的に :has() がおすすめです。古いブラウザ対応が必要な場合は :checked を選ぶと安心です。
CSSの基本やカスタマイズ方法については、こちらの記事で詳しく解説しています。
HTMLやCSSの編集場所がわからない方は、こちらの記事を参考にしてください。
方法① :checked を使う互換性重視版
ラジオボタンと :checked 擬似クラスを活用する方法。古めの環境も含めて幅広く対応するため、使いやすい方法です。
▶ DEMO(:checked版)
See the Pen タブ切り替え|基本スタイル by Turicco (@Turicco) on CodePen.
<div class="tab-switch">
<input type="radio" id="tab1" name="TAB" checked>
<label for="tab1">タブ①</label>
<div class="tab-content">タブ①の内容</div>
<input type="radio" id="tab2" name="TAB">
<label for="tab2">タブ②</label>
<div class="tab-content">タブ②の内容</div>
<input type="radio" id="tab3" name="TAB">
<label for="tab3">タブ③</label>
<div class="tab-content">タブ③の内容</div>
</div>
.tab-switch {
--cstm-tab-color:#92bac2;
display: flex;
flex-wrap: wrap;
max-width: 800px;
margin-inline: auto;
gap: 0 5px;
}
/* ラジオ非表示 */
.tab-switch input {
display: none;
}
/* タブボタン */
.tab-switch label {
padding: 0.7em 1em;
background:#eee;
cursor: pointer;
order: -1;
text-align: center;
}
/* コンテンツ非表示 */
.tab-content {
display: none;
width: 100%;
padding: 1.5em 0;
}
/* 選択されたタブ+コンテンツ表示 */
.tab-switch input:checked + label {
background: var(--cstm-tab-color);
color: #fff;
}
.tab-switch input:checked + label + .tab-content {
display: block;
}
HTML記述のポイント
- ラベルとラジオの紐づけ
→id="tab1" と for="tab1"この2行がタブ切り替えの要です。
<!-- タブ① -->
<input type="radio" id="tab1" name="TAB" checked>
<label for="tab1">タブ①</label>
<!-- タブ② -->
<input type="radio" id="tab2" name="TAB">
<label for="tab2">タブ②</label>
<!-- タブ③ -->
<input type="radio" id="tab3" name="TAB">
<label for="tab3">タブ③</label>
CSSのポイント
- ラジオボタンを非表示
→ ボタンそのものは見せずに、labelをタブとしてデザイン。
.tab-switch input {
display: none;
}
- 選択中のタブを強調
→:checked状態の直後にあるラベルを装飾。
.tab-switch input:checked + label {
background: var(--cstm-tab-color);
color: #fff;
}
- 選択中のコンテンツを表示
→ 選択中のラベルの直後にある.tab-contentだけ表示されます。
.tab-switch input:checked + label + .tab-content {
display: block;
}
方法② :has() を使うシンプル実装(モダンブラウザ向け)
:has() を使うと「子要素の状態を見て親要素の見た目を変える」ことができます。
今回は「選択されているラジオボタンを含む label」を判定して、アクティブなタブの色を変更しています。
▶ DEMO(:has版)
See the Pen タブ切り替え|外枠付き by Turicco (@Turicco) on CodePen.
<div class="tab-switch">
<label><input type="radio" name="TAB" checked>タブ①</label>
<div class="tab-content">タブ①の内容</div>
<label><input type="radio" name="TAB">タブ②</label>
<div class="tab-content">タブ②の内容</div>
<label><input type="radio" name="TAB">タブ③</label>
<div class="tab-content">タブ③の内容</div>
</div>
.tab-switch {
--cstm-tab-color:#dbb6a2;
display: flex;
flex-wrap: wrap;
max-width: 800px;
margin-inline: auto;
gap: 5px;
}
/* タブボタン */
.tab-switch label {
padding: 0.7em 1em;
background:#eee;
cursor: pointer;
order: -1; /* 上に表示 */
text-align: center;
}
/* ラジオ非表示 */
.tab-switch input {
display: none;
}
/* コンテンツ非表示 */
.tab-content {
display: none;
width: 100%;
padding: 1.5em 0;
}
/* 選択されたタブ+コンテンツ表示 */
.tab-switch label:has(:checked) {
background: var(--cstm-tab-color);
color: #fff;
}
.tab-switch label:has(:checked) + .tab-content {
display: block;
}
HTML記述のポイント
- ラジオボタンをラベル内に書く
→ ラベルをクリックするとinputが切り替わり、同時にCSSで状態を判定できます。
<label><input type="radio" name="TAB" checked>タブ①</label>
CSSのポイント
:has(:checked)で選択状態を判定
→labelの中に:checkedな input がある場合のみ、スタイルを適用。
.tab-switch label:has(:checked) {
background: var(--cstm-tab-color);
color: #fff;
}
- 隣接するコンテンツを表示
→ 選択されたラベルのすぐ後ろにある.tab-contentを表示します。
.tab-switch label:has(:checked) + .tab-content {
display: block;
}
タブのスタイル|カスタマイズ例
タブ切り替えは中身を切り替えるだけでなく、デザイン次第で見やすさも変わります。
ここからは実際によく使うカスタマイズ例を紹介します。
タブ均等幅
タブを横並びにして、均等に幅を分けたいときは flex: 1; を指定します。項目数が変わっても自動で幅が調整されるので便利です。
See the Pen タブ切り替え|input表示バージョン by Turicco (@Turicco) on CodePen.
.tab-switch label {
flex: 1; /* 均等幅 */
}
吹き出し風スタイル
選択中のタブに下向きの小さな三角形を付けて、吹き出し風に見せられます。
「今どのタブを選んでいるのか」を直感的に伝えられるデザイン。特にブログ記事の切り替えメニューなどにおすすめです。
See the Pen タブ切り替え|吹き出し風 by Turicco (@Turicco) on CodePen.
.tab-switch label {
position: relative;
}
/* 吹き出し */
.tab-switch label:has(:checked)::before {
content: '';
position: absolute;
top: calc(100% - 1px);
left: 50%;
transform: translateX(-50%);
width: 18px;
height: 9px;
background-color: var(--cstm-tab-color);
clip-path: polygon(0 0, 100% 0, 50% 100%);
}
丸・白抜きスタイル
タブをボタン風にしたい場合は、丸みをつけた白抜きデザインがおすすめです。
See the Pen タブ切り替え|丸み by Turicco (@Turicco) on CodePen.
.tab-switch label {
border: 1px solid var(--cstm-tab-color); /* 枠線 */
border-radius: 30px; /* 丸み */
}
枠線の色を var(--cstm-tab-color) にしておけば、サイト全体のテーマカラーに合わせて統一感を出せます。
タブ切り替えを 同ページに複数セット(2つ以上)置く場合
タブ切り替えを1ページに複数セット置く場合は、いくつか注意点があります。
- ラジオボタンの
name属性はグループごとに固有にする
ラジオボタンは 同じname を持つと1つしか選べない特性があるため、1つのタブセットごとに違う名前にします。
<!-- タブセット1 -->
<input type="radio" name="TAB1" id="tab1-1" checked>
<input type="radio" name="TAB1" id="tab1-2">
<!-- タブセット2 -->
<input type="radio" name="TAB2" id="tab2-1" checked>
<input type="radio" name="TAB2" id="tab2-2">
idとfor属性も重複させない<label for="id名">は対応する<input>と結びつきます。- ページ内で同じ
idを複数使うと正しく動作しないので、タブセットごと別のidを付けます。
WordPressでタブ切り替えを実装する場合の注意点
WordPressでは、<p> や <br>が自動挿入されることがあります。
タブ切り替えは「input → label → .tab-content」のような隣接関係を利用しているので、間に不要なタグが入ると正しく動作しません。
うまく切り替わらない場合は、次を確認してください。
- カスタムHTMLブロック内にまとめて記述しているか
- 不要な改行が入っていないか
- ブロックエディタで自動的に段落が追加されていないか
特にクラシックエディタでは自動整形が有効になっていることが多く、このケースが発生しやすい傾向があります。

実際に、この不具合でお問い合わせいただいた方のほとんどがクラシックエディタを使っていました。
→ CSSが反映されない原因と対策をチェック
Cocoonの「タブ」ブロックと活用例
ここまでで、HTMLとCSSだけでタブ切り替えを実装する方法を紹介しました。
- 「Cocoonでコードを書かずに実装したい」
- 「ブロックで完結させたい」
という方は、Cocoon標準のタブブロックを使う方法がおすすめです。実際に当サイトでは、Cocoonのタブブロックをベースにデザインを調整して使っています。
ブロック操作で簡単なタブ切り替えの作りから、デザインをワンクリックで選べる便利なカスタマイズまで詳しく解説しています。
タブをトップページや固定ページで活用したい方はこちらの記事もおすすめです。サイト型トップページの中でタブを使うと、記事一覧や更新情報を見やすく整理できます。
タブ切り替えまとめ
HTMLとCSSだけで、シンプルかつ機能的なタブ切り替えを実装できました。
:checked方式 → 互換性が高く、古いブラウザでも動作:has()方式 → より直感的に書けるが、モダンブラウザ向け
迷ったらまずは :has() 版がおすすめです。
コードがシンプルで管理しやすく、現在の主要ブラウザでも問題なく動作します。
一方で、古いブラウザ対応が必要な場合は :checked 版を選びましょう。








Comment 記事の感想を書き込んでいただけると幸いです
返信ありがとうございます。
Cocoonではないのでショートコードは使えないのですが、記事拝見させて頂きました。
色々と試みてみたのですが、結局、素人にはどの要素をいれるとカテゴリーの記事一覧が表示されるのかわからずでした…
もう少し頑張ってみます。
コメント失礼します。
HTMLにある「コンテンツをここに入れる」には何を入れたら良いのでしょうか?
タブ自体は奇麗に表示されていますが、各タブの下にカテゴリーを表示したいのですが、URLなどを入力するようなものではないようですし…
他のサイトも拝見したのですが、ここに何を入れるとカテゴリーや記事が表示されるのかわからず質問させて頂きました。
新着記事や人気記事を表示したいならこちらの記事に書いたショートコード(Cocoon独自のものです)を使いますが、
カテゴリーを表示したいということであれば、トップページの作り方という記事を更新しましたのでこちらが参考になるかと思います^^