【JSなし】CSSだけでタブ切り替えをする方法

HTML&CSS

こんにちはtakosanです。

今回はJSなどを使わずCSSのみでタブの切替表示を行う方法を紹介します。

CSSだけで作成するタブ切替

まずは完成品をご覧ください。

See the Pen Tabs_only_CSS by yukiwebcreate (@Yukiwebcreate) on CodePen.

今回作成したのはこのようなタブで切り替えられるコンテンツです。

作り方

コードはコピペすれば動きます。

ですがその仕組みを理解していないと、自分で1から作る時や、

カスタマイズにも苦戦してしまいます。

わかっといた方がいいよね!

というわけで丁寧に解説します。

1.inputとlabel

まず最初の壁はここ。

  <input id="a" type="radio" name="tab-item" checked>
  <label class="tab-item" for="a">A</label>
  <input id="b" type="radio" name="tab-item">
  <label class="tab-item" for="b">B</label>
  <div id="a-content" class="tab-content">
    Aの内容です。
  </div>
  <div id="b-content" class="tab-content">
    Bの内容です。
  </div>

ここの仕組みをまずは解説します。

<input id="a" type="radio" name="tab-item" checked>
  <label class="tab-item" for="a">A</label>

一つずつに分割して見てみるとわかりやすいです。

inputはラジオボタンのtypeにしています。

これはAかBのタブは同時にどちらかしか選ばれないためラジオボタンを利用しています。

そしてlabelのfor=””にある”a”は、labelを押した時、”a”のinputを押下したことにするために

for=”a”

と設定されています。

2.CSSの全体を見てみよう

CSSの全体は下記のようになります。(コメントつけてるからわかりやすいはず)

/* 全体を覆うdiv */
.tab-container {
  width: 500px;
  border: 1px solid #57ccbc;
}
/*タブ(label)のスタイル*/
.tab-item {
  width: 50%;
  height: 50px;
  line-height: 50px;
  background-color: lightgray;
  text-align: center;
  display: block;
  float: left;
  flex-wrap: nowrap;
  color: gray;
  text-align: center;
  transition: all 0.2s;
  font-weight: bold;
}

/* inputボタンは目には見えないところで働いてもらう */
input[name="tab-item"] {
  display: none;
}

/* タブで切り替えたいコンテンツの部分。ここはお好みで */
.tab-content {
  display: none;
  padding: 40px 0;
  overflow: hidden;
  clear: both;
  text-align: center;
}

/* 選択されているタブのコンテンツを表示させる */
#a:checked ~ #a-content,
#b:checked ~ #b-content {
  display: block;
}

/* 選択されていることがわかるように、選択されているタブはスタイルを変える */
.tab-container input:checked + .tab-item {
  background-color: #57ccbc;
  color: #fff;
}

ここでのポイントは大きく分けて2箇所です。

1つはこちらの、inputをdisplay:none;にすること。

/* inputボタンは目には見えないところで働いてもらう */
input[name="tab-item"] {
  display: none;
}

2つめはこちらの、選んでいるタブだけ表示させることです。

/* 選択されているタブのコンテンツを表示させる */
#a:checked ~ #a-content,
#b:checked ~ #b-content {
  display: block;
}

3.inputをdisplay:none;にする理由

inputをdisplay:noneにする訳は、簡単にいうと、

制御としてはラジオボタンの機能を使いたいが、ラジオボタンが見えてるのはダサい。

ってことです。

そういうわけでinputのラジオボタンにはdislay:none;で姿を消してもらい、

前述のlabelを押したときに、inputが押されたような挙動にだけしているということです。

4.選択しているタブのコンテンツだけ表示する

ここがおそらくタブ切替えのもっとも重要なパートです。

/* 選択されているタブのコンテンツを表示させる */
#a:checked ~ #a-content,
#b:checked ~ #b-content {
  display: block;
}

#aや#bはlabelに振ってあるidです。そして間に見える「~」という記号は

間接セレクタ」と呼ばれるものです。

これを使うことで#aを押した時に別の要素のCSSを変更できるのです。

例えばここでいうと、#aがcheckedになった時に

連動して#a-contentのスタイルがdisplay:block;になるよ。

という使い方ができるわけです。

ちなみにセレクタにはいくつか種類があり、

  • 隣接セレクタ( + )
  • 間接セレクタ( ~ )
  • 直下セレクタ( > )

があります。これらを使うことで兄弟要素や子要素などにCSSを反映させることができます。

隣接セレクタについてはこちらの記事で詳しく解説しています↓

ここに注意!

htmlの方の1個目のinputにご注目ください。

 <input id="a" type="radio" name="tab-item" checked>
  <label class="tab-item" for="a">A</label>
  <input id="b" type="radio" name="tab-item">
  <label class="tab-item" for="b">B</label>

1個目の方だけ「checked」がついてますよね?

そしてCSSではtab-contentに一旦display:none;がついています。

/* タブで切り替えたいコンテンツの部分。ここはお好みで */
.tab-content {
  display: none;
  padding: 40px 0;
  overflow: hidden;
  clear: both;
  text-align: center;
}


/* 選択されているタブのコンテンツを表示させる */
#a:checked ~ #a-content,
#b:checked ~ #b-content {
  display: block;
}

この理由は、タブで選択されているものだけを表示したいという設計なので、

最初に初期設定としてコンテンツ部分はdisplay:none;にしておいて、

checkedがついているコンテンツだけをdisplay:block;を当てた方が良いので

こういう書き方になっています。

ページを読み込んだ時、最初に表示していたいコンテンツがAであれば、

inputのAの方にcheckedをつける。

Bを最初に表示したいならBのinputにcheckedを書く、

ということをするために先程のhtmlでは、aの方に

  <input id="a" type="radio" name="tab-item" checked>
  <label class="tab-item" for="a">A</label>

checkedがついているわけです。

また、何も表示したくないなら、どちらからもcheckedは外しておいてください

逆に、どちらにもcheckedをつけるとバグの元なので、気をつけましょう。

最後に

初見では難しそうに見えますが、

ボタンを押したらコンテンツ部分のdisplayが変わる。

っていうのを長〜く書いてるだけです。

JSやjQueryをあまり多用したくない、CSSだけでなんとかしたいという方には

打って付けではないでしょうか?

ボタンを増やしたりカスタマイズも簡単ですので、ぜひ使ってみてください。

タイトルとURLをコピーしました