tailwindcss × React で作る点滅するローディングアニメーションのサンプル

![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610773/8d1b14ac-0d12-b02d-7f38-175fcfc37530.gif)

https://tailwindcss.com/docs/animation

:::note
点滅させたい箇所に　`className="animate-pulse"` を付けるだけで簡単に実装できます。
:::

> Pulse
> Add the animate-pulse utility to make an element gently fade in and out — useful for things like > skeleton loaders.

```css
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;

@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: .5;
}
}
```

### サンプルコード

#### Cardコンポーネント

```ts
const Card = () => (
    <div className="p-4 md:w-1/3">
      <div className="h-full border-2 border-gray-200 rounded-lg overflow-hidden">
        <img
          className="lg:h-48 md:h-36 w-full object-cover object-center"
          src="https://source.unsplash.com/IgQo1_gUzBY"
          alt="blog"
        />
        <div className="p-6">
          <h2 className="tracking-widest text-xs title-font font-medium text-gray-500 mb-1">
            カテゴリー
          </h2>
          <h1 className="text-lg font-medium text-gray-900 mb-3">タイトル</h1>
          <p className="leading-relaxed mb-3">
            ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。ここに説明が入ります。
          </p>
          <div className="flex items-center flex-wrap ">
            <a className="text-indigo-500 inline-flex items-center md:mb-2 lg:mb-0">
              詳細
              <svg
                className="w-4 h-4 ml-2"
                viewBox="0 0 24 24"
                stroke="currentColor"
                stroke-width="2"
                fill="none"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <path d="M5 12h14"></path>
                <path d="M12 5l7 7-7 7"></path>
              </svg>
            </a>
          </div>
        </div>
      </div>
    </div>
  );
```

#### 点滅するCardコンポーネント

```ts
  const PulseCard = () => (
    <div className="p-4 md:w-1/3">
      <div className="h-full border-2 border-gray-200 rounded-lg overflow-hidden">
        <div className="lg:h-48 bg-gray-400 md:h-36 w-full object-cover object-center"></div>
        <div className="p-6">
          <h2 className="bg-gray-400 animate-pulse h-4 w-1/4 mb-2"></h2>
          <h1 className="w-1/2 mb-4 h-6 animate-pulse bg-gray-500"></h1>
          <p className="leading-relaxed mb-3 w-full h-3 animate-pulse bg-gray-400"></p>
          <p className="leading-relaxed mb-3 w-2/3 h-3 animate-pulse bg-gray-400"></p>
          <p className="leading-relaxed mb-3 w-1/2 h-3 animate-pulse bg-gray-400"></p>
          <div className="flex items-center flex-wrap ">
            <a className="bg-indigo-300 h-4 animate-pulse mt-2 w-32 inline-flex items-center md:mb-2 lg:mb-0"></a>
          </div>
        </div>
      </div>
    </div>
  );
```

#### 動かすためのサンプル(9個のカードが3秒間ローディングするようにしてます)

```tsx
const Home = () => {
  const [data, setData] = useState<any[]>();
  const pulseData: any[] = [...Array(9)];

  const fetchData = () => {
    const data = [...Array(9)];
    setTimeout(() => setData(data), 3000);
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
      <section className="w-full">
        <div className="container px-5 py-24 mx-auto">
          <div className="flex flex-wrap -m-4">
            {data
              ? data.map((v, i) => <Card key={i} />)
              : pulseData.map((v, i) => <PulseCard key={i} />)}
          </div>
        </div>
      </section>
  );
};
```

### 完成サンプル（一応レスポンシブも対応してます。）

![gifさんぷ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610773/0f239b8e-09d0-4124-1dfb-631fe0b841c7.gif)

とっても簡単でした。