Bootstrap 5入門 - タブUIの作り方

33

Twitter社製のCSSフレームワークBootstrapを用いると、レスポンシブでモバイルファーストなユーザーインターフェイス(UI)を素早く作成できます。本記事では、Bootstrapの入門編として、HTMLコーディングのみでタブを作る方法を紹介します。

※本記事は2022年4月現在のBootstrap 5で解説しています。

▼ Bootstrapを使ったタブの作例。上部のタブにより猫の写真が切り替わる

▼ 操作の様子を動画で確認する

完成系のコードは次の通りです。

本記事では初級者向けに、手軽にタブUIを作る方法に焦点をあてて説明します。また、中・上級者向けに、ウェブアクセシビリティの対策方法も説明しています。

Bootstrapの基本単位はコンポーネント

Bootstrapの各要素の基本単位は「コンポーネント」 と呼ばれます。今回はタブ用コンポーネントを用います。

Bootstrapを使うための準備

BootstrapによるUI構築のために、CSSを読み込みます。HTMLコードの<head>タグ内に次のコードを記述します。

▼ Bootstrap用CSSの読み込み

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <!-- Bootstrap用CSSの読み込み -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />

  <!-- 以降省略 -->

タブの切り替え、モーダルの表示などの「動き」の制御をするには、JavaScriptが必要です。BootstrapのJavaScriptも読み込みます。各JavaScriptを次のように読み込みましょう。

▼ Bootstrapに必要なJavaScriptの読み込み

<!-- 中略 -->
  <head>
  <!-- 中略 -->
    <!-- Bootstrap用JavaScriptの読み込み -->
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
      crossorigin="anonymous"
    ></script>
  </head>

CDN経由以外でBootstrapを読み込む方法

CDN経由以外にもBootstrapを読み込む方法はあります。たとえばソースファイルで読み込む方法や、パッケージマネージャー(npmyarn)を使う方法などです。プロジェクトの性質にあわせて読み込み方法を選択するとよいでしょう。詳しくは公式ドキュメントのDownloadページを参照ください。

タブ部分の実装

Bootstrapの使用準備が終わったので、タブの部分を実装しましょう。

▼ タブの部分

タブを囲う親要素にnavクラスとnav-tabsクラスを設定します。

▼ タブの親要素のためのHTMLコード

<ul class="nav nav-tabs">
  <!-- ここに要素を追加していきます -->
</ul>

1つのタブはnav-itemクラスで設定します。<a>タグとnav-linkを使ってタブの中のリンクを設定します。

▼ タブ1つのHTMLコード

<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link">タブ1</a>
  </li>
</ul>

4つのタブ用のHTMLコードを記述します。また、最初のタブを選択状態にするため1つ目のタブにactiveクラスを設定します。タブの全体コードは次のとおりになります。

▼ 4つのタブ用HTMLコード

<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link active">タブ1</a>
  </li>
  <li class="nav-item">
    <a class="nav-link">タブ2</a>
  </li>
  <li class="nav-item">
    <a class="nav-link">タブ3</a>
  </li>
  <li class="nav-item">
    <a lass="nav-link">タブ4</a>
  </li>
</ul>

ここまでのコードの実行結果はスクリーンショットのとおりです。

▼ 4つのタブを作成した状態

4枚の写真部分の実装

続いて、タブを押したときに切り替わる4枚の写真部分を実装しましょう。

▼ 4枚の写真部分

4枚の写真部分のHTML要素にtab-contentクラスを設定します。tab-contentというクラス名は、「タブで表示が切り替わるコンテンツ」というようなニュアンスです。

▼ 4枚の写真部分のHTML要素

<div class="tab-content">
</div>

今回は4つのタブがあり、それに応じて写真が4枚表示されます。各写真要素にtab-paneクラスを設定することで、表示の切り替わる要素として機能させます。具体的には次のようにHTMLコードを記述します。

▼ 4つの写真のうちの1つの写真

<div class="tab-pane">
  <img src="images/photo1.jpg" alt="" class="img-fluid" />
</div>

img-fluidクラスは必須でないですが、画像のレスポンシブ対応ができる便利なクラスなので覚えておくとよいでしょう

写真を4枚表示するためにHTMLコードを記述します。注意点として、tab-contentで指定される要素はデフォルトで非表示になっています。1枚目の写真は最初から表示させたいので、activeクラスを設定します。次のコードを参照ください。

▼ 4つの写真部分HTMLコード

<div class="tab-content">
  <div id="photo1" class="tab-pane active">
    <img src="images/photo1.jpg" class="img-fluid" alt="" />
  </div>
  <div id="photo2" class="tab-pane">
    <img src="images/photo2.jpg" class="img-fluid" alt="" />
  </div>
  <div id="photo3" class="tab-pane">
    <img src="images/photo3.jpg" class="img-fluid" alt="" />
  </div>
  <div id="photo4" class="tab-pane">
    <img src="images/photo4.jpg" class="img-fluid" alt="" />
  </div>
</div>

ここまでのコードの実行結果は、次のスクリーンショットのようになります。

▼ ここまでのコードの実行結果

要素の周りに余白を設ける

ここまでのコードの実行結果を見ると、要素が画面左上に寄ってしまっています。要素の周りに適切な余白を設けましょう。Bootstrapではクラス1つで余白が設定できます(参考「Spacing · Bootstrap」)。今回は上下左右に規定の余白を設定するp-3クラスを用います。

<main class="p-3">
  <ul class="nav nav-tabs">
    <!-- 中略 -->
  </ul>

  <!--写真部分-->
  <div class="tab-content">
    <!-- 中略 -->
  </div>
</main>

余白が設定された状態のスクリーンショットは次のとおりです。

▼ 要素の余白が設定された

タブ切り替え機能の実装

さて、見た目は実装できましたが、タブを押しても何の反応もありません。「タブを押した時に、対応した写真を表示する」という処理を実装していないためです。本来ならJavaScriptコードを書いて実装するところですが、BootstrapではHTMLの属性の設定だけで切り替え機能を実装できます

まずはタブ側の設定です。それぞれのリンクにhref属性を使って「どのIDのコンテンツを表示するか」という設定をします。そして、タブ切り替え機能を有効にするためdata-bs-toggle="tab"を指定します。

▼ タブの切り替えのためのコード

<ul class="nav nav-tabs">
  <li class="nav-item">
    <a href="#photo1" class="nav-link active" data-bs-toggle="tab">タブ1</a>
  </li>
  <!--(省略)-->

続いて写真側の設定を行います。id属性を使って各写真に固有のIDを設定し、タブを押した時に切り替える仕組みを作ります。

▼ 写真のためのコード

<div class="tab-content">
  <div id="photo1" class="tab-pane active">
    <!--(省略)-->
  </div>
</div>

各設定を、タブ・写真4つそれぞれに設定することで、切り替え機能は完成します。

実行結果は次のとおりです。

▼ タブの切り替えが有効化された

完成コード

本記事で作成したコードを確認しましょう。CSS・JavaScriptのコードを記述することなく、タブ機能が実装できました。一部抜粋しているので、完全版はGitHubのコードをご覧ください。

▼ 全体コード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>Bootstrap タブUIのデモ(シンプル版)</title>
    <!-- Bootstrap用CSSの読み込み -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />
    <!-- Bootstrap用JavaScriptの読み込み -->
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <main class="p-3">
      <!-- 4個分のタブUI -->
      <ul class="nav nav-tabs">
        <li class="nav-item">
          <a href="#photo1" class="nav-link active" data-bs-toggle="tab">タブ1</a>
        </li>
        <!-- 中略 -->
      </ul>

      <!-- 写真部分 -->
      <div class="tab-content">
        <div id="photo1" class="tab-pane active">
          <img src="images/photo1.jpg" class="img-fluid" alt="" />
        </div>
        <!-- 中略 -->
      </div>
    </main>
  </body>
</html>

ウェブアクセシビリティーの対策も必要

見栄えをつくるだけならここまで完成していますが、ウェブサイトのアクセシビリティーを対応するには、もう少し属性を追加したほうが望ましいです。role属性やaria-selected属性を適切に指定することで、スクリーンリーダーでの音声読み上げの精度が向上します。

次の図版は、アクセシビリティー対応をしなかった場合と、した場合の比較です。右側のほうが、スクリーンリーダーで読み上げられている情報が多くなっています。音声情報の手がかりが増えるので、視覚障害者にとってウェブページを操作しやすくなります。

コーディングで気をつける要所は次のとおりです。

  • タブUIの親にはrole="tablist"属性が必要
  • タブUIの子にはrole="tab"属性が必要
  • タブUIの子にはaria-selected="true"属性が必要
    • タブのどれが選択された状態であるかを示すことができる
  • タブパネル側にはrole="tabpanel"属性が必要
  • タブパネルにはaria-labelledby属性を使い、タブUIとの紐付けを行う

これを考慮したコードは以下の通りとなります。一部抜粋しているので、完全版はGitHubのコードをご覧ください。

<!DOCTYPE html>
<html lang="ja">
  <!-- 中略 -->
  <body>
    <main class="p-3">
      <!-- 4個分のタブ -->
      <ul class="nav nav-tabs" role="tablist">
        <li class="nav-item" role="presentation">
          <a href="#photo1" id="tab1" class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true">
            タブ1
          </a>
        </li>
        <!-- 中略 -->
      </ul>

      <!-- 写真部分 -->
      <div class="tab-content">
        <div id="photo1" class="tab-pane active" role="tabpanel" aria-labelledby="tab1">
          <img src="images/photo1.jpg" class="img-fluid" alt="猫の写真1" />
        </div>
        <!-- 中略 -->
      </div>
    </main>
  </body>
</html>

まとめ

本記事ではBootstrapの入門編として、HTMLコードのみでタブUIを実装しました。タブUIはウェブページ内の情報を整理するのに活用できるUIです。Bootstrapを利用してウェブページの情報整理に役立てましょう。

関連記事の紹介

実際の案件でタブ機能を使用する場合は、デザインのカスタマイズが必要になります。関連記事『webpack入門 - Bootstrapをバンドルする方法』では、webpackやSassなどのフロントエンド技術と連携してBootstrapのデザインをカスタマイズする方法を紹介します。あわせて参照くださいませ。

また、ReactやVue、Angular等のJavaScriptライブラリでのタブUIの解説記事もあります。こちらはBootstrapを利用していませんが、aria-selected属性等の指定が手軽になるという観点で説明しています。JavaScriptを得意とするフロントエンドエンジニアは以下の記事を参考ください。

※この記事が公開されたのは2年前ですが、 今年4月に内容をメンテナンスしています。