コハム

Webクリエイターのコハムが提供する、Web制作に役立つ情報をまとめたブログです。

Tailwind CSSとReactでかんたん実装!華やかなスタガーテキストアニメーションを取り入れたヒーローイメージ

Create Staggered Text Animation with Tailwind CSS and React

記事は上記記事を意訳したものです。

※当ブログでの翻訳記事は元サイト様に許可を得て掲載しています。


Linearのランディングページに似た、React と Tailwind CSS を使って作成されたスタガーテキストアニメーションを実装してみましょう!

Vite React アプリの設定と Tailwind CSS のセットアップ

最初に、npx create vite app コマンドを使用して、Vite React アプリを作成し、ライブラリとして React を選択します。公式の Tailwind CSS ドキュメントに従って、6つの簡単なステップを実行し、プロジェクトに Tailwind をセットアップします。

npm run dev でデベロップメントサーバーを起動すると、アプリが localhost:5173 で実行されるはずです。

代わりに、Vite の代替として Next.js または Remix を使うこともできます。

マークアップの生成

Figma のこのモックアップから出発し、Builder.io の Figma プラグインの Visual Copilot を使って、デザインを React + Tailwind のコードに変換しました。

Figma で「Generate」をクリックし、生成されたコードをコードベースにコピー&ペーストしました。私は Hero.tsx という新しいファイルにそのコードを配置しました。

スライドインアニメーションの追加

Tailwind のアニメーション機能を強化するため、tailwind.config.js ファイルの theme.extend.animationtheme.extend.keyframes を変更しました。

export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {
      keyframes: {
        slidein: {
          from: {
            opacity: "0", 
            transform: "translateY(-10px)",
          },
          to: {
            opacity: "1",
            transform: "translateY(0)", 
          },
        },
      },
      animation: {
        slidein: "slidein 1s ease 300ms",
      },
    },
  },
  plugins: [],
};

この コードスニペットでは、新しい slidein アニメーションを定義しています。from キーフレームでは、コンテンツが不透明度 0%で最終位置よりも少し上にあり、to キーフレームでは、不透明度 100%で最終位置になります。

このアニメーションは 1 秒かけて 'ease' タイミング関数で実行され、300ms の遅延があります。

この animate-slidein クラスをヒーローテキストを表す 4 つの要素に適用します。

<!-- 要素 1 -->
<div className="animate-slidein ...">
  <div className="...">Introducing Linear Asks</div>
  <img loading="lazy" src="..." className="..." alt="Icon" />
</div>

<!-- 要素 2 -->
<h1 className="animate-slidein ...">
  Linear is a better way
  <br />
  to build products
</h1>

<!-- 要素 3 -->
<p className="animate-slidein ...">
  Meet the new standard for modern software development.
  <br />
  Streamline issues, sprints, and product roadmaps.
</p>

<!-- 要素 4 -->
<div className="animate-slidein ...">
  <div className="...">Get started</div>
  <img loading="lazy" src="..." className="..." alt="Arrow icon" />
</div>

アニメーションのスタガー

アニメーションが実行されますが、すべての要素が一度にスライドインしています。スタガー効果を作るため、Tailwind の設定で slidein アニメーションの 4 つのバリアントを定義し、異なる遅延を設定します。

animation: {
  slidein300: "slidein 1s ease 300ms",
  slidein500: "slidein 1s ease 500ms", 
  slidein700: "slidein 1s ease 700ms",
},

Hero コンポーネントの className をこれらの新しいアニメーションバリアントに更新します。

<!-- 要素 1 -->
<div className="animate-slidein300 ...">
  <div className="...">Introducing Linear Asks</div>
  <img loading="lazy" src="..." className="..." alt="Icon" />
</div>

<!-- 要素 2 -->
<h1 className="animate-slidein300 ...">
  Linear is a better way 
  <br />
  to build products
</h1>

<!-- 要素 3 --> 
<p className="animate-slidein500 ...">
  Meet the new standard for modern software development.
  <br />
  Streamline issues, sprints, and product roadmaps.
</p>

<!-- 要素 4 -->
<div className="animate-slidein700 ...">
  <div className="...">Get started</div>
  <img loading="lazy" src="..." className="..." alt="Arrow icon" />
</div>

これでアニメーションがきれいにスタガーするようになりましたが、アニメーション開始前に要素が表示されてしまう問題があります。これを修正するため、opacity-0 クラスを追加して、初期状態で要素が非表示になるようにします。

<!-- 要素 1 -->
<div className="animate-slidein300 opacity-0 ...">
  <div className="...">Introducing Linear Asks</div>
  <img loading="lazy" src="..." className="..." alt="Icon" />
</div>

<!-- 要素 2 -->
<h1 className="animate-slidein300 opacity-0 ...">
  Linear is a better way
  <br />
  to build products  
</h1>

<!-- 要素 3 -->
<p className="animate-slidein500 opacity-0 ...">
  Meet the new standard for modern software development.
  <br />
  Streamline issues, sprints, and product roadmaps.
</p>

<!-- 要素 4 -->
<div className="animate-slidein700 opacity-0 ...">
  <div className="...">Get started</div>
  <img loading="lazy" src="..." className="..." alt="Arrow icon" />
</div>

スタガーアニメーションが期待通りに動作しますが、アニメーション後にヒーローテキスト要素がすべて消えてしまいます。これを修正するため、animation-fill-mode: forwards を指定して、要素がアニメーションの最後のキーフレームのスタイルを維持するようにします。

animation: {
  slidein300: "slidein 1s ease 300ms forwards",
  slidein500: "slidein 1s ease 500ms forwards",
  slidein700: "slidein 1s ease 700ms forwards", 
},

これでアニメーションがきれいにスタガーするようになりました。

CSS 変数を使ったリファクタリング

コードを最適化するため、CSS 変数を使ってカスタムアニメーションをリファクタリングします。デフォルト値が 0ms の --slidein-delay 変数を導入します。

animation: {
  slidein: "slidein 1s ease var(--slidein-delay, 0) forwards",
}

次に、この変数を Hero コンポーネントに適用します。

<!-- 要素 1 -->
<div className="animate-slidein opacity-0 [--slidein-delay:300ms] ...">
  <div className="...">Introducing Linear Asks</div>
  <img loading="lazy" src="..." className="..." alt="Icon" />
</div>

<!-- 要素 2 -->
<h1 className="animate-slidein opacity-0 [--slidein-delay:300ms] ...">
  Linear is a better way
  <br />
  to build products
</h1>

<!-- 要素 3 -->
<p className="animate-slidein opacity-0 [--slidein-delay:500ms] ...">
  Meet the new standard for modern software development.
  <br />
  Streamline issues, sprints, and product roadmaps.
</p>

<!-- 要素 4 -->
<div className="animate-slidein opacity-0 [--slidein-delay:700ms] ...">
  <div className="...">Get started</div>
  <img loading="lazy" src="..." className="..." alt="Arrow icon" />
</div>

以上が、React と Tailwind CSS を使って Linear のランディングページに似たスタガーテキストアニメーションを実装する手順です。

©コハム