# Tailwind CSS でアニメーション付きのローディングスケルトンを作る

> シマー効果を使って Tailwind CSS でアニメーション付きのローディングスケルトンを作り、実際のコンテンツを読み込んでいる間にプレースホルダー UI を表示できるようにします。

著者 Shodipo Ayomide、2022年7月18日 公開。Web 版：https://blog.shodipoayomide.com/ja/animated-loading-skeletons-with-tailwind

<div className="grid grid-cols-2 gap-6 sm:grid-cols-3">
  <div>
    
  </div>
  <div>
    
  </div>
  <div className="hidden sm:block">
    
  </div>
</div>

# スケルトン

- Tailwind の豊富なユーティリティクラスを使って、これから読み込むコンテンツにおおまかに似せたスケルトンを作ります。

<div className="space-y-2">
  <div className="flex justify-center rounded-lg bg-rose-100/[1%] p-8 ring-1 ring-inset ring-rose-100/[3%]">
    <div className="w-[200px] space-y-5 rounded-2xl bg-white/5 p-4">
      <div className="h-24 rounded-lg bg-rose-100/10"></div>
      <div className="space-y-3">
        <div className="h-3 w-3/5 rounded-lg bg-rose-100/10"></div>
        <div className="h-3 w-4/5 rounded-lg bg-rose-100/20"></div>
        <div className="h-3 w-2/5 rounded-lg bg-rose-100/20"></div>
      </div>
    </div>
  </div>
  ```html
  <div class="space-y-5 rounded-2xl bg-white/5 p-4">
    <div class="h-24 rounded-lg bg-rose-100/10"></div>
    <div class="space-y-3">
      <div class="h-3 w-3/5 rounded-lg bg-rose-100/10"></div>
      <div class="h-3 w-4/5 rounded-lg bg-rose-100/20"></div>
      <div class="h-3 w-2/5 rounded-lg bg-rose-100/20"></div>
    </div>
  </div>
  ```
</div>

# グラデーションオーバーレイ

- Tailwind のグラデーションカラーストップを使って、透明から白へ、そして再び透明へとフェードするグラデーションを作ります。

<div className="space-y-2">
  <div className="flex justify-center rounded-lg bg-rose-100/[1%] p-8 ring-1 ring-inset ring-rose-100/[3%]">
    <div className="w-[200px]">
      <div className="h-48 bg-gradient-to-r from-transparent via-rose-100/20 to-transparent"></div>
    </div>
  </div>
  ```html
  <div
    class="
      [...]
      bg-gradient-to-r from-transparent via-rose-100/10 to-transparent"
  ></div>
  ```
</div>

# アニメーション

- `tailwind.config.js` の extend 内にある keyframes オブジェクトに、要素を右方向へ 100% 移動させる CSS キーフレームアニメーションを定義します。
- Tailwind の任意値（arbitrary values）を使って、オーバーレイ要素にキーフレームアニメーションを適用します。

<div className="space-y-2">
  <div className="flex justify-center rounded-lg bg-rose-100/[1%] p-8 ring-1 ring-inset ring-rose-100/[3%]">
    <div className="w-[200px]">
      <div className="relative h-48 -translate-x-full animate-[shimmer_2s_infinite] bg-gradient-to-r from-transparent via-rose-100/20 to-transparent"></div>
    </div>
  </div>
  ```json
  {
    "keyframes": {
      "shimmer": {
        "100%": {
          "transform": "translateX(100%)",
        },
      },
    }
  },
  ```
  ```html
  <div class="[...] -translate-x-full animate-[shimmer_2s_infinite]"></div>
  ```
</div>

# スケルトンとオーバーレイのアニメーションを組み合わせる

- Tailwind の `before:` モディファイアを使って、スケルトンのラッパーの疑似要素にオーバーレイを追加します。

<div className="space-y-2">
  <div className="flex justify-center rounded-lg bg-rose-100/[1%] p-8 ring-1 ring-inset ring-rose-100/[3%]">
    <div className="w-[200px]">
      <div className="relative space-y-5 rounded-2xl bg-white/5 p-4 before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-rose-100/10 before:to-transparent">
        <div className="h-24 rounded-lg bg-rose-100/10"></div>
        <div className="space-y-3">
          <div className="h-3 w-3/5 rounded-lg bg-rose-100/10"></div>
          <div className="h-3 w-4/5 rounded-lg bg-rose-100/20"></div>
          <div className="h-3 w-2/5 rounded-lg bg-rose-100/20"></div>
        </div>
      </div>
    </div>
  </div>
  ```html
  <div
    class="
      [...]
      relative 
      before:absolute before:inset-0
      before:-translate-x-full
      before:animate-[shimmer_2s_infinite]
      before:bg-gradient-to-r
      before:from-transparent before:via-rose-100/10 before:to-transparent"
  >
    [...]
  </div>
  ```
</div>

# 仕上げ

- オーバーレイがスケルトンの外側に位置している間は非表示にします。
- スケルトンに影を付けます。
- 光の反射を表現するために、オーバーレイの上端に控えめなボーダーを追加します。
- 角丸の部分で Safari がアニメーションをはみ出させてしまう問題は、`isolate` で修正できます。

<div className="space-y-2">
  <div className="flex justify-center rounded-lg bg-rose-100/[1%] p-8 ring-1 ring-inset ring-rose-100/[3%]">
    <div className="w-[200px]">
      <div className="relative isolate space-y-5 overflow-hidden rounded-2xl bg-white/5 p-4 shadow-xl shadow-black/5 before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:border-t before:border-rose-100/10 before:bg-gradient-to-r before:from-transparent before:via-rose-100/10 before:to-transparent">
        <div className="h-24 rounded-lg bg-rose-100/10"></div>
        <div className="space-y-3">
          <div className="h-3 w-3/5 rounded-lg bg-rose-100/10"></div>
          <div className="h-3 w-4/5 rounded-lg bg-rose-100/20"></div>
          <div className="h-3 w-2/5 rounded-lg bg-rose-100/20"></div>
        </div>
      </div>
    </div>
  </div>
  ```html
  <div
    class="
      [...]
      isolate
      overflow-hidden
      shadow-xl shadow-black/5
      before:border-t before:border-rose-100/10"
  >
    [...]
  </div>
  ```
</div>
