htmxで作る動的タブUI – シンプルで高速な実装テクニック

htmxで作る動的タブUI - シンプルで高速な実装テクニック プログラミング

タブUIは、限られたスペースで多くの情報を整理し、ユーザーに提供するのに便利なデザインパターンです。
しかし、従来のタブUIの実装には、JavaScriptによる複雑な処理が必要でした。

htmxを使えば、シンプルなHTMLの属性だけで動的なタブUIを実現できます。
この記事では、htmxを使ってタブUIを実装する方法を詳しく解説します。

本記事の内容

  • タブUIのHTML構造
  • タブコンテンツの動的生成
  • アニメーション効果の追加
  • アクセシビリティの考慮
  • サンプルコード
  • まとめ

それでは、上記に沿って解説していきます。

タブUIのHTML構造

htmxについてよくわからない場合は、次の記事からご覧ください。

まず、タブUIのHTML構造を定義します。
タブボタンとタブコンテンツを以下のように配置します。

<div class="tab-container" role="tablist">
  <div class="tab-buttons">
    <button class="tab-button" role="tab" aria-controls="tab-content" aria-selected="true" hx-target="#tab-content" hx-trigger="click" hx-get="tab1.php">タブ1</button>
    <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab2.php">タブ2</button>
    <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab3.php">タブ3</button>
  </div>
  <div id="tab-content" role="tabpanel"></div>
</div>

各タブボタンには、hx-target、hx-trigger、hx-getの属性を設定します。
これにより、ボタンのクリックイベントが発火した際に、指定したPHPファイルからコンテンツを取得し、#tab-content要素に挿入するようになります。

タブコンテンツの動的生成

次に、PHPを使ってタブコンテンツを動的に生成します。
tab1.php、tab2.php、tab3.phpというPHPファイルを作成し、以下のようなコードを記述します。

<!-- tab1.php -->
<?php
$title = 'タブ1のコンテンツ';
$content = 'これはタブ1の動的に生成されたコンテンツです。';
?>

<div>
  <h2><?= $title ?></h2>
  <p><?= $content ?></p>
  <p>現在の時刻は <?= date('Y-m-d H:i:s') ?> です。</p>
</div>
<!-- tab2.php -->
<?php
$title = 'タブ2のコンテンツ';
$content = 'これはタブ2の動的に生成されたコンテンツです。';
?>

<div>
  <h2><?= $title ?></h2>
  <p><?= $content ?></p>
  <p>現在の時刻は <?= date('Y-m-d H:i:s') ?> です。</p>
</div>
<!-- tab3.php -->
<?php
$title = 'タブ3のコンテンツ';
$content = 'これはタブ3の動的に生成されたコンテンツです。';
?>

<div>
  <h2><?= $title ?></h2>
  <p><?= $content ?></p>
  <p>現在の時刻は <?= date('Y-m-d H:i:s') ?> です。</p>
</div>

これらのPHPファイルでは、$titleと$contentという変数を使ってタブコンテンツを動的に生成しています。
また、date(‘Y-m-d H:i:s’)を使って現在の時刻を表示することで、ページが動的に生成されていることを強調しています。

htmxは、これらのPHPファイルをAjaxで取得し、#tab-content要素に挿入します。
これにより、タブを切り替えるたびに、対応するコンテンツが動的に表示されます。

アニメーション効果の追加

タブ切り替えのアニメーションを追加することで、よりスムーズで洗練された印象を与えることができます。
以下のようなCSSを使って、アニメーションを実装します。

.tab-content {
  opacity: 0;
  transition: opacity 0.5s;
}

.tab-content.htmx-settling {
  opacity: 1;
}

htmx-settlingクラスは、htmxがコンテンツの挿入を完了した直後に要素に追加されます。
これを利用して、コンテンツの表示をフェードインさせます。

アクセシビリティの考慮

タブUIをアクセシブルにするために、WAI-ARIAの属性を使います。

<div class="tab-container" role="tablist">
  <div class="tab-buttons">
    <button class="tab-button" role="tab" aria-controls="tab-content" aria-selected="true" hx-target="#tab-content" hx-trigger="click" hx-get="tab1.php">タブ1</button>
    <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab2.php">タブ2</button>
    <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab3.php">タブ3</button>
  </div>
  <div id="tab-content" role="tabpanel"></div>
</div>

role属性を使って、タブボタンとタブコンテンツの役割を明示します。
また、aria-controls属性でタブボタンとタブコンテンツの関連付けを行います。
aria-selected属性で、現在選択されているタブを示します。

さらに、キーボードでのタブ操作を可能にするために、JavaScriptを使って以下のような処理を追加します。

const tabButtons = document.querySelectorAll('.tab-button');

tabButtons.forEach((button, index) => {
  button.addEventListener('keydown', (event) => {
    if (event.key === 'ArrowLeft') {
      tabButtons[(index - 1 + tabButtons.length) % tabButtons.length].focus();
    }
    if (event.key === 'ArrowRight') {
      tabButtons[(index + 1) % tabButtons.length].focus();
    }
  });
});

これで、左右の矢印キーを使ってタブを切り替えられるようになります。

サンプルコード

以上の内容を組み合わせた完全なサンプルコードは以下の通りです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>htmxで作る動的タブUI</title>
  <script src="https://unpkg.com/htmx.org@1.7.0"></script>
  <style>
    .tab-content {
      opacity: 0;
      transition: opacity 0.5s;
    }

    .tab-content.htmx-settling {
      opacity: 1;
    }
  </style>
</head>
<body>
  <div class="tab-container" role="tablist">
    <div class="tab-buttons">
      <button class="tab-button" role="tab" aria-controls="tab-content" aria-selected="true" hx-target="#tab-content" hx-trigger="click" hx-get="tab1.php">タブ1</button>
      <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab2.php">タブ2</button>
      <button class="tab-button" role="tab" aria-controls="tab-content" hx-target="#tab-content" hx-trigger="click" hx-get="tab3.php">タブ3</button>
    </div>
    <div id="tab-content" role="tabpanel"></div>
  </div>

  <script>
    const tabButtons = document.querySelectorAll('.tab-button');

    tabButtons.forEach((button, index) => {
      button.addEventListener('keydown', (event) => {
        if (event.key === 'ArrowLeft') {
          tabButtons[(index - 1 + tabButtons.length) % tabButtons.length].focus();
        }
        if (event.key === 'ArrowRight') {
          tabButtons[(index + 1) % tabButtons.length].focus();
        }
      });
    });
  </script>
</body>
</html>

このコードを実行すると、シンプルで高速な動的タブUIが実現されます。

まとめ

この記事では、htmxとPHPを組み合わせて動的なタブUIを実装する方法を解説しました。
htmxのhx-target、hx-trigger、hx-get属性を使うことで、シンプルなHTMLだけで動的なタブ切り替えを実現できます。
また、PHPを使ってタブコンテンツを動的に生成することで、より柔軟で応用の効くUIが作成できます。

htmxとサーバーサイドの処理を連携させることで、高速で洗練されたタブUIを実装できます。
この記事で紹介したテクニックを活用し、さらに発展させることで、ユーザーにとって使いやすく魅力的なタブUIを作成しましょう。

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