1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Tailwind Variants】React×Tailwind CSSで動的スタイリングを実現するTailwind Variantsの使い方

Last updated at Posted at 2024-12-26

はじめに

Tailwind Variants は、Tailwind CSSを使用して動的なスタイリングを簡潔に管理できるツールやライブラリです。

一つのコンポーネントに対して、引数を渡して動的にクラス設定が可能になります。
Webアプリケーションの開発において、UIコンポーネントのスタイリングは重要な要素です。Tailwind CSSを使うと、直感的にスタイルを設定できますが、次第にコードが冗長化したり、似たようなスタイルを持つ要素の管理が複雑化する問題が発生します。

特に、状況に応じてスタイルを動的に変更したい場合、Tailwind CSS単体では対応が煩雑になることがあります。このような課題に対して、Tailwind Variants は、動的スタイリングを簡潔に記述できる方法を提供します。

動的スタイリングがない場合の課題

例えば以下の様にサイト内でボタンがある場合、
単純にTailwind CSSのスタイルを定義すると、ボタンごとに異なるクラスを個別に設定する必要があります。
この場合、コンポーネント化を進めても、例えば複数のボタンコンポーネントを用意してそれぞれに異なる色を設定する必要が出てきます。.

image.png

実装例

<!DOCTYPE html><div className="grid grid-cols-3 items-center gap-4 font-bold text-lg">
       <h2 className="text-center">Size</h2>
       <h2 className="text-center">Primary</h2>
       <h2 className="text-center">Secondary</h2>
     </div>
     <div className="grid grid-cols-3 items-center gap-4 text-center">
       <h2 className="text-lg font-semibold">Large</h2>
       <button className="bg-blue-500 text-white py-2 rounded w-40">Button</button>
       <button className="bg-white text-black border border-black py-2 rounded w-40">Button</button>
     </div>
     <div className="grid grid-cols-3 items-center gap-4 text-center">
       <h2 className="text-lg font-semibold">Medium</h2>
       <button className="bg-blue-500 text-white py-2 rounded w-32">Button</button>
       <button className="bg-white text-black border border-black py-2 rounded w-32">Button</button>
     </div>
     <div className="grid grid-cols-3 items-center gap-4 text-center">
       <h2 className="text-lg font-semibold">Small</h2>
       <button className="bg-blue-500 text-white py-2 rounded w-24">Button</button>
       <button className="bg-white text-black border border-black py-2 rounded w-24">Button</button>
     </div>

これに対し、Tailwind Variantsを使うと、色や状態に応じて動的にクラスを設定でき、再利用可能なコードを効率よく管理できます。

事前準備

ここでは、Tailwind Variantsを導入するために必要なReactとTypeScriptのセットアップを行います。
もしすでにReactとTypeScriptの環境が整っている場合や、内容だけ知りたい場合は、次の「Tailwind Variantsの導入」に進んでください。
実際にセットアップを行いたい場合は、この手順を順番に実行して、Tailwind Variantsを使うための準備を整えてください。

各種インストール

  1. Reactと型宣言をインストール

    npm install react react-dom
    npm install --save-dev @types/react @types/react-dom
    

  2. TypeScriptのインストール

    npm install --save-dev typescript
    

  3. Viteのインストール

    npm install --save-dev vite
    

  4. Tailwind CSSのインストール

    npm install -D tailwindcss
    npx tailwindcss init
    

  5. Viteのインストール

    npm install --save-dev vite
    

各種作成

  1. TypeScriptの初期設定

    TypeScriptの設定ファイルtsconfig.jsonを初期化します。

    npx tsc --init
    

  2. tsconfig.jsonを編集

    tsconfig.jsonファイルを以下のように編集します。

    {
      "compilerOptions": {
        "target": "ESNext", 
        "module": "ESNext", 
        "jsx": "react-jsx", 
        "strict": true, 
        "moduleResolution": "node", 
        "esModuleInterop": true, 
        "skipLibCheck": true, 
        "forceConsistentCasingInFileNames": true 
      },
      "include": ["src/**/*"], 
      "exclude": ["node_modules"] 
    }
    

  3. index.htmlの作成
    index.html

    <!DOCTYPE html>
    <html lang="ja">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vite App</title>
      </head>
      <body>
        <div id="root"></div>
        <script type="module" src="/src/tsx/index.tsx"></script>
      </body>
    </html>
    

  4. Reactファイルの作成
    src/tsx/index.tsx

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './app';
    import '../css/output.css';
    
    const rootElement = document.getElementById('root');
    if (!rootElement) {
      throw new Error('Root element not found. Check your index.html file.');
    }
    
    const root = ReactDOM.createRoot(rootElement);
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    

    src/tsx/app.tsx

    import React from 'react';
    
    const App: React.FC = () => {
      return (
        <div>
          <section>
            <h1 className="text-3xl font-bold underline text-center">Test</h1>
          </section>
          <section className="grid gap-4 p-4">
            <div className="grid grid-cols-3 items-center gap-4 font-bold text-lg">
              <h2 className="text-center">Size</h2>
              <h2 className="text-center">Primary</h2>
              <h2 className="text-center">Secondary</h2>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Large</h2>
              <button className="bg-blue-500 text-white py-2 rounded w-40">Button</button>
              <button className="bg-white text-black border border-black py-2 rounded w-40">Button</button>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Medium</h2>
              <button className="bg-blue-500 text-white py-2 rounded w-32">Button</button>
              <button className="bg-white text-black border border-black py-2 rounded w-32">Button</button>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Small</h2>
              <button className="bg-blue-500 text-white py-2 rounded w-24">Button</button>
              <button className="bg-white text-black border border-black py-2 rounded w-24">Button</button>
            </div>
          </section>
        </div>
      );
    };
    
    export default App;
    

  5. input.cssの作成
    src/css/input.css

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    

  6. tailwind.config.jsの修正
    contentを以下の様に修正します。

    module.exports = {
      content: ['./src/**/*.{html,tsx}'],
      // …以下省略
    };
    

  7. output.cssの修正
    input.cssから最終的なoutput.cssを生成します。

    npx tailwindcss -i ./src/css/input.css -o ./src/css/output.css
    

  8. package.jsonにstartスクリプトを追加
    package.jsonにViteを使った開発サーバーを起動するstartスクリプトを追加します。

    {
      "name": "tailwind-variants",
      "version": "1.0.0",
      "scripts": {
        "start": "vite"
      },
      "dependencies": {
      }
    }
    

    これでプロジェクト構成は以下になっています。

    project_root/
    ├── node_modules/
    ├── src/
    │   ├── css/
    │   │   ├── input.css
    │   │   └── output.css
    │   └── tsx/
    │       ├── app.tsx
    │       └── index.tsx
    ├── package.json
    ├── tailwind.config.js
    └── tsconfig.json
    

    プロジェクトのルートディレクトリで以下のコマンドを実行します。

    npm start
    …
    Local:   http://localhost:5173/
    

    該当のURLをブラウザで開き、「はじめに」の画像にあるボタン群が表示されれば完了です。

Tailwind Variantsの導入

  1. Tailwind Variantsのインストール

    npm install tailwind-variants
    

  2. Reactファイルの作成
    事前準備」で用意したsrc/tsx/app.tsxを以下の様に修正します。

    import React from 'react';
    import { tv } from 'tailwind-variants';
    
    const button = tv({
      base: 'py-2 rounded text-center',
      variants: {
        color: {
          primary: 'bg-blue-500 text-white',
          secondary: 'bg-white text-black border border-black',
        },
        size: {
          sm: 'w-24',
          md: 'w-32',
          lg: 'w-40',
        },
      },
      defaultVariants: {
        color: 'primary',
        size: 'md',
      },
    });
    
    const App: React.FC = () => {
      return (
        <div>
          <section>
            <h1 className="text-3xl font-bold underline text-center">app_after.tsx</h1>
          </section>
          <section className="grid gap-4 p-4">
            <div className="grid grid-cols-3 items-center gap-4 font-bold text-lg">
              <h2 className="text-center">Size</h2>
              <h2 className="text-center">Primary</h2>
              <h2 className="text-center">Secondary</h2>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Large</h2>
              <button className={button({ color: 'primary', size: 'lg' })}>Button</button>
              <button className={button({ color: 'secondary', size: 'lg' })}>Button</button>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Medium</h2>
              <button className={button({ color: 'primary', size: 'md' })}>Button</button>
              <button className={button({ color: 'secondary', size: 'md' })}>Button</button>
            </div>
            <div className="grid grid-cols-3 items-center gap-4 text-center">
              <h2 className="text-lg font-semibold">Small</h2>
              <button className={button({ color: 'primary', size: 'sm' })}>Button</button>
              <button className={button({ color: 'secondary', size: 'sm' })}>Button</button>
            </div>
          </section>
        </div>
      );
    };
    
    export default App;
    

tv()関数

tv()は、Tailwind Variantsが提供するクラス名生成関数で、動的にクラスを生成するために使用されます。引数には以下の要素を設定します。

  1. base
    これは、すべてのボタンに共通して適用される基本のスタイルを定義します。上記の例では、'py-2 rounded text-center'が基本スタイルとして設定されています。これにより、すべてのボタンに対して、一定のパディング、角丸、およびテキストの中央揃えが適用されます。

  2. variants
    ここでは、動的に変更できるクラスのバリエーションを定義します。上記の例では、colorsizeの2つのバリエーションが設定されています。

    • color: primarysecondaryの2つのオプションがあり、それぞれ異なる背景色や文字色が設定されています。
    • size: sm, md, lgの3つのオプションがあり、それぞれ異なるボタンの幅が設定されています。
  3. defaultVariants
    これは、variantsで定義したバリエーションのデフォルト値を設定します。上記の例では、colorprimarysizemdに設定されており、tv()を呼び出す際に引数を省略すると、これらのデフォルト設定が適用されます。

使用方法

tv()関数を使って、ボタンに動的にスタイルを適用するには、以下のようにクラスを呼び出します。

<button className={button({ color: 'primary', size: 'lg' })}>Button</button>

修正後の状態で再度ブラウザで表示すると、修正前と同じようにボタンが表示されます。

所感

Tailwind Variantsの導入についてまとめてみました。
Tailwind Variantsを使用することで動的なスタイリングを簡潔に管理でき、スタイルの管理が非常に効率的になっているように感じました。
今回紹介した機能はあくまで機能の一部なので、興味がある方は是非触ってみて下さい。

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?