タブ切り替えをHTMLとCSSだけで実装する方法
公開:2025.09.05

ボタンをクリックすると、表示されるコンテンツを切り替えるタブ切り替えの機能をHTMLとCSSだけで実装します。
JavaScriptでクリックしたらクラスを付与して…のようなことはしません。なぜなら、私はJavaScriptが苦手だからです!(恥)
むやみやたらにJavaScriptを増やして競合されるのが怖いので、可能な限り使わないようコーディングしてきました。
簡単にタブ切り替えできる方法はないものか…と探して見つけた方法です。
次のような仕上がりになります。
使用するHTMLとCSS
では、どのように実装しているか、HTMLとCSSを見ていきましょう。
簡単に説明すると、ラジオボタンを押したらlabel要素に隣接するdiv要素を表示する、という仕組みでタブ切り替えをしています。
※このホームページでは「html」に設定されている「font-size」が10px程度の状態になっています。
※コードを利用される環境によって、単位が「em」指定されているもののサイズが変わります。
<div class="tab-contents-wrap">
<input id="tc01" type="radio" class="tab-contents-input" name="tab" checked="checked">
<label class="tab-contents-label" for="tc01">Aのボタン</label>
<div class="tab-contents-main">
Aのコンテンツを表示します。
</div>
<input id="tc02" type="radio" class="tab-contents-input" name="tab">
<label class="tab-contents-label" for="tc02">Bのボタン</label>
<div class="tab-contents-main">
Bのコンテンツを表示します。
</div>
<input id="tc03" type="radio" class="tab-contents-input" name="tab">
<label class="tab-contents-label" for="tc03">Cのボタン</label>
<div class="tab-contents-main">
Cのコンテンツを表示します。
</div>
</div>
.tab-contents-wrap {
display: flex;
flex-wrap: wrap;
}
.tab-contents-label {
text-align: center;
order: -1;
cursor: pointer;
flex: 1;
transition: 0.3s;
background-color: #000000;
color: #fff;
border: 2px #000000 solid;
padding: 0.5em 0.8em;
}
.tab-contents-main {
width: 100%;
height: 0;
overflow: hidden;
opacity: 0;
transition: opacity 0.3s;
visibility: hidden;
background-color: #fff;
padding-right: 2em;
padding-left: 2em;
position: relative;
top: -2px;
}
.tab-contents-input {
display: none;
}
.tab-contents-input:checked + .tab-contents-label {
background-color: #fff;
color: #000000;
border-bottom-color: #fff;
}
.tab-contents-input:checked + .tab-contents-label + .tab-contents-main {
height: auto;
opacity: 1;
visibility: visible;
border-right: 2px #000000 solid;
border-left: 2px #000000 solid;
border-bottom: 2px #000000 solid;
padding-top: 2.6em;
padding-bottom: 2.6em;
}
HTMLの解説
全体を囲む「tab-contents-wrap」というクラスがついた要素の中に、ラジオボタンの「input(tab-contents-inputのクラス付き)」と「label(tab-contents-labelのクラス付き)」を入れています。「id」と「for」が同じになっているものがセットです。
そのlabelに隣接するように、「tab-contents-main」というクラスが付いたdiv要素を配置しました。
「input」~「tab-contents-main」が1つのグループです。

★ポイント
このとき、それぞれの「input」の「id」と、inputに隣接する「label」の「for」が同じになるようにしておきます。これで、どのinputとlabelがセットになっているか関連付けています。
タブ切り替えをしますので、複数の「input」と「label」があります。1つのinputと、それに隣接するlabelがセットです。セットになっている「id」と「for」は同じにし、ページ内にある他のセットと、idとforが被らないように注意してください。
今回のHTMLの場合、Aのコンテンツは「tc01」、Bのコンテンツは「tc02」…と変更しています。
<input id="tc01" type="radio" class="tab-contents-input" name="tab" checked="checked">
最初に表示しておくコンテンツの「input」には「checked=”checked”」を指定します。
そうすると、これが今選択されているラジオボタンだよ~ということになります。
もしページ内に複数のタブ切り替えコンテンツを入れるのであれば、「name=”tab”」の部分を変更しましょう。「name」が一緒のinputは、ラジオボタンのクリックによって切り替わる、同じタブ切り替えのグループになります。
画像で説明するとこんな感じです。

CSSの解説
CSSが適用されていない状態の、タブ切り替えのスクリーンショットがこちらです。

①が「input(tab-contents-inputのクラス付き)」
②が「label(tab-contents-labelのクラス付き)」
③が「tab-contents-main」
です。
この①~③が1つのグループになっています。
「Aのボタン」「Bのボタン」とか横並びになるの?って感じですが、最終的にうまいこと並びます。
では、CSSを詳しく見ていきましょう。
.tab-contents-wrap {
display: flex;/* flexを指定 */
flex-wrap: wrap;/* 中の要素が折り返すように */
}
.tab-contents-label {
text-align: center;
order: -1;/* label要素のが最初に表示されるよう、順番変更 */
cursor: pointer;
flex: 1;
transition: 0.3s;
background-color: #000000;
color: #fff;
border: 2px #000000 solid;
padding: 0.5em 0.8em;
}
.tab-contents-main {
width: 100%;/* 100%を指定 */
height: 0;/* 高さなし */
overflow: hidden;/* はみ出す要素を消す */
opacity: 0;/* 透明にする */
transition: opacity 0.3s;
visibility: hidden;/* 見えないように、中の要素を選択できないように */
background-color: #fff;
padding-right: 2em;
padding-left: 2em;
position: relative;
top: -2px;
}
「tab-contents-wrap」には「display:flex」を指定します。これが「Aのボタン」などのlabelを横並びにさせるコツです。
各labelに「order:1」を指定して、「tab-contents-wrap」の並び替えをします。これでlabel要素を最初の方に移動させて、横並びで表示されるようになります。
「tab-contents-main」には「width:100%」を指定して、labelの横に回り込んだりしないようにしておきます。
「tab-contents-main」はcheckedになっていないときに非表示にするため、「opacity:0」と「visivility:hidden」、更に「height:0」を指定します。さらに、「height:0」にすると中の要素がはみ出してしまうため、一応「overflow: hidden;」を指定しました。
★ポイント
「checked」になっていないときの「.tab-contents-main」には、「padding-top」「padding-bottom」「margin-top」「margin-bottom」は指定しないでください。
コンテンツは非表示の状態ですが、paddingやmargin分の高さが出てしまい、謎の隙間ができてしまいます。ですので、上下のpaddingやmarginは「checked」になったときに指定してください。「padding-right」「padding-left」は高さに影響しないので、「checked」になっていなくても指定できます。
.tab-contents-input {
display: none;
}
「input」はデザイン的にいらないので「display:none」を指定して消します。
.tab-contents-input:checked + .tab-contents-label {
background-color: #fff;
color: #000000;
border-bottom-color: #fff;
}
次に、ラジオボタンをクリックしたときのタブ切り替え部分のCSSを詳しく見ていきましょう。
inputに付けたクラス「.tab-contents-input」に「:checked」を追加して、ラジオボタンが選択された状態になったとき、という指定をします。
これを利用して、ラジオボタンが選択されているときのボタンの見た目を変更します。
ボタンとして利用するのがlabel要素になるため、ラジオボタンが選択されたときのlabel要素に対してCSSが適用されるようにする指定が、「.tab-contents-input:checked+.tab-contents-label」部分ですね。
「+」の記号は、「Aの要素に隣接する要素B」のように、どの要素同士が隣り合う状態になっているか指定できます。
今回は、ラジオボタンが選択されているとき、「:checked」が付いたinput要素に隣接するlabel要素に対しての指定です。
視覚的に選択されているボタンがわかりやすいように、選択されたボタンは色が変わるようにしています。
.tab-contents-input:checked + .tab-contents-label + .tab-contents-main {
height: auto;/* 高さあり */
opacity: 1;/* 不透明にする */
visibility: visible;/* 見えるし、中の要素を選択できるように */
border-right: 2px #000000 solid;
border-left: 2px #000000 solid;
border-bottom: 2px #000000 solid;
padding-top: 2.6em;
padding-bottom: 2.6em;
}
ラジオボタンが選択されたらコンテンツを開く指定が、
「.tab-contents-input:checked+.tab-contents-label+.tab-contents-main」
の部分です。
先ほど指定したlabel要素に隣接する「.tab-contents-main」と指定して、ラジオボタンが選択されたときに「.tab-contents-main」を表示するよう指定しました。
最後に、このHTMLとCSSで作ったタブ切り替え機能がこちら
以上がjsを使用せずにタブ切り替え機能を実装する方法です。
今回のまとめ
- jsなしでタブ切り替えをするために、ラジオボタンを利用する
- ①「input」②「label」③「開閉するコンテンツ」の順番で隣り合わせに配置する
※これで1つのグループになる - ①「input」の「id」と②「label」の「for」は同じものを入力する
※これで1セット
他のセットと「id」と「for」が被らないようにする - 「input」要素はデザイン的に不要なので「display:none」を指定
- 全体を囲む要素は「display:flex」にして、「label」要素に「order:-1」を指定し、ボタンの表示順を変更する
- ③「開閉するコンテンツ」は、初期状態で非表示になるよう「opacity:0」「visivility:hidden」「height:0」を指定する
- 最初に表示しておくコンテンツの①「input」には、「checked=”checked”」を指定する
- ラジオボタンがチェックされたときのCSS指定は、①「input」要素に「:checked」を付ける
- 「:checked」がついた①「input」要素に隣接する②「label」、更にその要素に隣接する③「開閉するコンテンツ」と指定して、コンテンツの開閉を実装する
「jsを使わなくてもタブ切り替えできるコンテンツ作れるんだー!」と、発見した当時の私には革命的な機能でした。
今回はラジオボタンだったので表示できるコンテンツは1つだけでした。ですが、チェックボックスを利用すると同時に複数のコンテンツを開くことができます。
チェックボックス版も、基本的な原理は今回のラジオボタン版と同じですので、ぜひ一度お試しあれ。