htmxのhx-indicatorとTailwind CSSでスケルトンスクリーンを実現する

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxのhx-indicatorとTailwind CSSを組み合わせてスケルトンスクリーンを実現する方法をご紹介します。

ケルトンスクリーンとは

ケルトンスクリーンは、読み込み中にコンテンツの代替となる図形を表示して、処理が実行中であることなどをユーザーに示すUXテクニックの一つです。

読み込み中はコンテンツの代替となる図形を表示する

Tailwind CSSでスケルトンスクリーンをスタイリングする

Tailwind CSSでは、スケルトンスクリーン用のアニメーションが標準搭載されており、簡単にスタイリングできます。

スタイリングについては、以下の記事で詳しく説明しておりますので本稿では割愛します。

tech.excite.co.jp

htmxでリクエスト中のみ特定の要素を可視化するhx-indicator

htmxでは、リクエスト中のみ特定の要素を可視化する機能として、hx-indicator属性が用意されています。

hx-indicatorの基本

hx-getなどのAJAXリクエストをする属性が付与された要素に、hx-indicator属性を追加して値にはリクエスト中に可視化したい要素のidかclassを指定します。

また、可視化したい要素のclassにhtmx-indicatorを指定します。

<div>
  <button type="button" hx-get="..." hx-indicator="#loading">Request</button>
  
  <!-- リクエスト中は以下の要素が表示される -->
  <div id="loading" class="htmx-indicator">...</div>
</div>

仕組みは単純です。

hx-indicatorを使用すると、htmxによって自動的に以下のスタイルがhtmlに挿入されます。

<style>
  .htmx-indicator{
    opacity:0;
    transition: opacity 500ms ease-in;
  }
  .htmx-request .htmx-indicator{
    opacity:1;
  }
  .htmx-request.htmx-indicator{
    opacity:1;
  }
</style>

処理の流れは次の通りです。

  1. htmx-indicatoropacity:0;(不透明度0%)が指定されている
  2. リクエスト中にはclassにhtmx-requestが加えられる
  3. htmx-requestと同居する場合はhtmx-indicatoropacity:1;(不透明度100%)になり要素が可視化される

Tailwind CSSと組み合わせる

リクエスト中にTailwind CSSでスタイリングしたスケルトンスクリーンを表示させたいとします。

See the Pen Untitled by AyumuSaito (@ayumusaito-excite) on CodePen.

<button type="button" hx-get="..." hx-indicator="#loading">Request</button>

<!-- リクエスト中は以下の要素を表示させたい -->
<div id="loading" class="htmx-indicator">
  <div class="p-4 rounded bg-white border border-slate-300">
    <div class="animate-pulse flex gap-3">
      <div class="w-12 h-12 aspect-square rounded-full bg-slate-300"></div>

      <div class="flex flex-col gap-2">
        <div class="h-6 w-24 rounded bg-slate-300"></div>
        <div class="h-6 w-40 rounded bg-slate-300"></div>
        <div class="h-6 w-80 rounded bg-slate-300"></div>
      </div>
    </div>
  </div>
</div>

注意点

この時に注意が必要です。

というのも、標準のhx-indicatorのスタイルはopacityを使用して要素の可視化を行うため、スケルトンスクリーン用の要素のスペースが常に確保されてしまいます。

確保されたスケルトンスクリーン用の要素のスペース

そのため、hx-indicator用のスタイルを独自定義する必要があります。

スペースの確保を回避するためには、opacityではなくdisplayを用いて制御するようにします。

独自定義するスタイルのclass名はhtmx-indicator以外を使用します。

<style>
  .my-indicator{
    display:none;
  }
  .htmx-request .my-indicator{
    display:block;
  }
  .htmx-request.my-indicator{
    display:block;
  }
</style>

完成形

先に述べた独自定義のスタイルを使用した完成形は以下の通りです。

<head>
  ...

  <!-- displayを使用するように独自定義したhx-indicator用のスタイル -->
  <style>
    .my-indicator{
      display:none;
    }
    .htmx-request .my-indicator{
      display:block;
    }
    .htmx-request.my-indicator{
      display:block;
    }
  </style>
</head>

<body>
  <button type="button" hx-get="..." hx-indicator="#loading">Request</button>
  
  <!-- リクエスト中は以下の要素が表示される -->
  <div id="loading" class="my-indicator">
    <div class="p-4 rounded bg-white border border-slate-300">
      <div class="animate-pulse flex gap-3">
        <div class="w-12 h-12 aspect-square rounded-full bg-slate-300"></div>
  
        <div class="flex flex-col gap-2">
          <div class="h-6 w-24 rounded bg-slate-300"></div>
          <div class="h-6 w-40 rounded bg-slate-300"></div>
          <div class="h-6 w-80 rounded bg-slate-300"></div>
        </div>
      </div>
    </div>
  </div>
</body>

hx-indicatorとTailwind CSSを組み合わせたスケルトンスクリーン

さいごに

今回は、htmxのhx-indicatorとTailwind CSSを組み合わせてスケルトンスクリーンを実現する方法をご紹介しました。

実装が手間なスケルトンスクリーンですが、htmxを使用することにより、JSを書かずにマークアップと同じ感覚で実現できます。

htmx、Tailwind CSSを使用される方の一助となれば幸いです。

ご精読ありがとうございました。