CSSだけでタブUIを作る

タブUI(ユーザーインターフェース)は、複数のページやセクションを一つの画面にまとめ、タブをクリックすることで内容を切り替えるインターフェースです。

これにより、縦に長くなってしまうコンテンツを適当なところでまとめ、ユーザーは直感的にそれらを切り替えて表示させることができるようになります。

WEBサイトやWEBアプリケーションでは特によく使われ、情報の整理とナビゲーションを簡単にします。

目次

方法1:ラジオボタンを使用する

特徴

HTMLのラジオボタンを利用してタブUIを作成する場合は、以下のような特徴があります。

  • 使いやすさ
    ラジオボタンとラベルを使ってタブを切り替える方法は、HTMLとCSSのみで簡単に実装できます。
  • 柔軟なスタイリング
    CSSを利用してラジオボタンやラベル、コンテンツに細かいスタイルを適用することができます。
  • 状態の保持
    ページをリロードすると選択されたタブの状態がリセットされます。
  • ユースケース
    シンプルなナビゲーションが必要な場合に適しています。

実際に書いてみる

実際にステップを追ってHTMLとCSSを作成してみます。

STEP
HTMLの構造

まず、タブのボタンとそれに対応するコンテンツをHTMLで構造化します。
各タブのボタンはラジオボタンとラベルで、コンテンツはそれぞれ対応するdiv要素に配置します。
ユーザーがラベル(タブ)をクリックすると、それに対応するラジオボタンが選択されます。

<div class="tabs">
  <input type="radio" name="tab" id="tab1">
  <label for="tab1">タブ1</label>
  <input type="radio" name="tab" id="tab2">
  <label for="tab2">タブ2</label>
  <input type="radio" name="tab" id="tab3">
  <label for="tab3">タブ3</label>

  <div class="content" id="content1">
    <h2>コンテンツ1</h2>
    <p>タブ1のコンテンツです。</p>
  </div>
  <div class="content" id="content2">
    <h2>コンテンツ2</h2>
    <p>タブ2のコンテンツです。</p>
  </div>
  <div class="content" id="content3">
    <h2>コンテンツ3</h2>
    <p>タブ3のコンテンツです。</p>
  </div>
</div>
コンテンツ1

タブ1のコンテンツです。

コンテンツ2

タブ2のコンテンツです。

コンテンツ3

タブ3のコンテンツです。

STEP
初期状態の設定

ページが表示された時に、最初のタブが選択されている状態を設定します。
これは、最初のラジオボタンにchecked属性を付けるだけでできます。

<div class="tabs">
  <input type="radio" name="tab" id="tab1" checked>
  <label for="tab1">タブ1</label>
  <input type="radio" name="tab" id="tab2">
  <label for="tab2">タブ2</label>
  <input type="radio" name="tab" id="tab3">
  <label for="tab3">タブ3</label>

  <div class="content" id="content1">
    <h2>コンテンツ1</h2>
    <p>タブ1のコンテンツです。</p>
  </div>
  <div class="content" id="content2">
    <h2>コンテンツ2</h2>
    <p>タブ2のコンテンツです。</p>
  </div>
  <div class="content" id="content3">
    <h2>コンテンツ3</h2>
    <p>タブ3のコンテンツです。</p>
  </div>
</div>
コンテンツ1

タブ1のコンテンツです。

コンテンツ2

タブ2のコンテンツです。

コンテンツ3

タブ3のコンテンツです。

STEP
CSSでのスタイルと表示制御

CSSを使用して、選択されたラジオボタンに対応するコンテンツを表示し、他のコンテンツを非表示にします。
また、ラジオボタン自体は表示しないようにし、ラベルにクリック可能なスタイルを適用します。

.tabs {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.tabs input[type="radio"] {
  display: none;
}

.tabs label {
  padding: 10px;
  cursor: pointer;
  background-color: #f1f1f1;
  margin-right: 5px;
}

.content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}
STEP
ユーザー操作時の動作

選択されたラジオボタンに対応するコンテンツが表示され、他のコンテンツは非表示になります。

.tabs input[type="radio"]:checked + label {
  background-color: #ddd;
}

#tab1:checked ~ #content1,
#tab2:checked ~ #content2,
#tab3:checked ~ #content3 {
  display: block;
  opacity: 1;
}

完成コード

<div class="tabs">
  <input type="radio" name="tab" id="tab1" checked>
  <label for="tab1">タブ1</label>
  <input type="radio" name="tab" id="tab2">
  <label for="tab2">タブ2</label>
  <input type="radio" name="tab" id="tab3">
  <label for="tab3">タブ3</label>

  <div class="content" id="content1">
    <h2>コンテンツ1</h2>
    <p>タブ1のコンテンツです。</p>
  </div>
  <div class="content" id="content2">
    <h2>コンテンツ2</h2>
    <p>タブ2のコンテンツです。</p>
  </div>
  <div class="content" id="content3">
    <h2>コンテンツ3</h2>
    <p>タブ3のコンテンツです。</p>
  </div>
</div>
.tabs {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.tabs input[type="radio"] {
  display: none;
}

.tabs input[type="radio"]:checked + label {
  background-color: #ddd;
}

.tabs label {
  padding: 10px;
  cursor: pointer;
  background-color: #f1f1f1;
  margin-right: 5px;
}

.content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

#tab1:checked ~ #content1,
#tab2:checked ~ #content2,
#tab3:checked ~ #content3 {
  display: block;
  opacity: 1;
}
.tabs {
  display: flex;
  flex-direction: column;
  align-items: flex-start;

  input[type="radio"] {
    display: none;

    &:checked + label {
      background-color: #ddd;
    }
  }

  label {
    padding: 10px;
    cursor: pointer;
    background-color: #f1f1f1;
    margin-right: 5px;
  }
}

.content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;

  &#content1,
  &#content2,
  &#content3 {
    @for $i from 1 through 3 {
      #tab#{$i}:checked ~ & {
        display: block;
        opacity: 1;
      }
    }
  }
}

動作の流れ

STEP
初期状態

HTMLが読み込まれると、最初のラジオボタン(id=”tab1″)がchecked状態になっているので、対応するコンテンツ(id=”content1″)が表示されます。

STEP
ユーザーがタブをクリック

ユーザーが他のタブ(例:タブ2)をクリックすると、そのタブに対応するラジオボタン(id=”tab2″)がchecked状態になります。

STEP
CSSによる表示制御

CSSセレクタ(例:#tab2:checked ~ #content2)が適用され、タブ2に対応するコンテンツが表示され、他のコンテンツ(id=”content1″やid=”content3″)が非表示になります。

STEP
アニメーションの適用

opacityプロパティとtransitionを使用して、表示・非表示のアニメーション(フェードイン・フェードアウト)が適用されます。

方法2:target疑似要素を使用する

特徴

CSSのtarget疑似クラスを利用してタブUIを作成する場合は、以下のような特徴があります。

  • URLフラグメントを利用
    URLのハッシュ部分を使用して、ページ内リンクとして機能します。
  • ブックマーク可能
    各タブに直接リンクできるため、ブックマークからページを開いた時に特定のタブを表示した状態にできます。
  • 状態の保持
    ページをリロードしても選択されたタブの状態が保持されます。
  • ユースケース
    特定のタブに直接リンクを張りたい場合に適しています。

実際に書いてみる

実際にステップを追ってHTMLとCSSを作成してみます。

STEP
HTMLの構造

まず、タブのボタンとそれに対応するコンテンツをHTMLで構造化します。
各タブのボタンはリンクのaタグで、コンテンツはそれぞれ対応するdiv要素に配置します。

<div class="tabs">
  <a href="#tab1">タブ1</a>
  <a href="#tab2">タブ2</a>
  <a href="#tab3">タブ3</a>

  <div id="tab1" class="tab-content">
    <h2>コンテンツ1</h2>
    <p>タブ1のコンテンツです。</p>
  </div>
  <div id="tab2" class="tab-content">
    <h2>コンテンツ2</h2>
    <p>タブ2のコンテンツです。</p>
  </div>
  <div id="tab3" class="tab-content">
    <h2>コンテンツ3</h2>
    <p>タブ3のコンテンツです。</p>
  </div>
</div>
タブ1 タブ2 タブ3
コンテンツ1

タブ1のコンテンツです。

コンテンツ2

タブ2のコンテンツです。

コンテンツ3

タブ3のコンテンツです。

STEP
初期状態の設定

ページが表示された時に、最初のコンテンツが選択されている状態を設定します。
これは、CSSで最初のコンテンツを表示にします。

.tab-content:first-of-type {
  display: block;
  opacity: 1;
}
STEP
CSSでのスタイルと表示制御

CSSを使用して、選択されたリンクに対応するコンテンツを表示し、他のコンテンツを非表示にします。

.tab-content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

.tabs a:target {
  background-color: #ddd;
}

.tab-content:target {
  display: block;
  opacity: 1;
}

完成コード

<div class="tabs">
  <a href="#tab1">タブ1</a>
  <a href="#tab2">タブ2</a>
  <a href="#tab3">タブ3</a>

  <div id="tab1" class="tab-content">
    <h2>コンテンツ1</h2>
    <p>タブ1のコンテンツです。</p>
  </div>
  <div id="tab2" class="tab-content">
    <h2>コンテンツ2</h2>
    <p>タブ2のコンテンツです。</p>
  </div>
  <div id="tab3" class="tab-content">
    <h2>コンテンツ3</h2>
    <p>タブ3のコンテンツです。</p>
  </div>
</div>
.tabs a {
  padding: 10px;
  cursor: pointer;
  background-color: #f1f1f1;
  margin-right: 5px;
  text-decoration: none;
  color: black;
}

.tabs a:target {
  background-color: #ddd;
}

.tab-content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

/* デフォルトで表示するタブのコンテンツ */
.tab-content:first-of-type {
  display: block;
  opacity: 1;
}

.tab-content:target {
  display: block;
  opacity: 1;
}
.tabs {
  a {
    padding: 10px;
    cursor: pointer;
    background-color: #f1f1f1;
    margin-right: 5px;
    text-decoration: none;
    color: black;

    &:target {
      background-color: #ddd;
    }
  }
}

.tab-content {
  display: none;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;

  &:first-of-type {
    display: block;
    opacity: 1;
  }

  &:target {
    display: block;
    opacity: 1;
  }
}

動作の流れ

STEP
初期状態

.tab-contentで、デフォルトでは全てのタブコンテンツを非表示(display: none)かつ透明(opacity: 0)に設定します。
.tab-content:first-of-typeで、デフォルトで表示したい最初のタブコンテンツを表示(display: block)し、透明度を設定(opacity: 1)します。

STEP
ユーザーがタブをクリック

.tab-content:targetで、選択されたタブのコンテンツを表示(display: block)し、透明度を設定(opacity: 1)します。

STEP
CSSによる表示制御

CSSセレクタ(例:.tab-content:target)が適用され、ターゲットに対応するコンテンツが表示され、他のコンテンツが非表示になります。

STEP
アニメーションの適用

opacityプロパティとtransitionを使用して、表示・非表示のアニメーション(フェードイン・フェードアウト)が適用されます。

まとめ

javascriptを使わずに、HTMLとCSSだけでタブUIを作成する方法をご紹介しました。

ザックリいうとラジオボタンを使ったほうがわかりやすいので、初心者のうちはラジオボタンを利用して作成したほうが良いかもしれません。
ですが別ページから、特定のタブが開いた状態でリンクを貼りたい、となったらtarget疑似クラスを使うことになると思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次