はじめに
Tailwind Variants は、Tailwind CSSを使用して動的なスタイリングを簡潔に管理できるツールやライブラリです。
一つのコンポーネントに対して、引数を渡して動的にクラス設定が可能になります。
Webアプリケーションの開発において、UIコンポーネントのスタイリングは重要な要素です。Tailwind CSSを使うと、直感的にスタイルを設定できますが、次第にコードが冗長化したり、似たようなスタイルを持つ要素の管理が複雑化する問題が発生します。
特に、状況に応じてスタイルを動的に変更したい場合、Tailwind CSS単体では対応が煩雑になることがあります。このような課題に対して、Tailwind Variants は、動的スタイリングを簡潔に記述できる方法を提供します。
動的スタイリングがない場合の課題
例えば以下の様にサイト内でボタンがある場合、
単純にTailwind CSSのスタイルを定義すると、ボタンごとに異なるクラスを個別に設定する必要があります。
この場合、コンポーネント化を進めても、例えば複数のボタンコンポーネントを用意してそれぞれに異なる色を設定する必要が出てきます。.
実装例
<!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を使うための準備を整えてください。
各種インストール
-
Reactと型宣言をインストール
npm install react react-dom npm install --save-dev @types/react @types/react-dom
-
TypeScriptのインストール
npm install --save-dev typescript
-
Viteのインストール
npm install --save-dev vite
-
Tailwind CSSのインストール
npm install -D tailwindcss npx tailwindcss init
-
Viteのインストール
npm install --save-dev vite
各種作成
-
TypeScriptの初期設定
TypeScriptの設定ファイル
tsconfig.json
を初期化します。npx tsc --init
-
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"] }
-
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>
-
Reactファイルの作成
src/tsx/index.tsximport 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;
-
input.cssの作成
src/css/input.css@tailwind base; @tailwind components; @tailwind utilities;
-
tailwind.config.jsの修正
contentを以下の様に修正します。module.exports = { content: ['./src/**/*.{html,tsx}'], // …以下省略 };
-
output.cssの修正
input.cssから最終的なoutput.cssを生成します。npx tailwindcss -i ./src/css/input.css -o ./src/css/output.css
-
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の導入
-
Tailwind Variantsのインストール
npm install tailwind-variants
-
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が提供するクラス名生成関数で、動的にクラスを生成するために使用されます。引数には以下の要素を設定します。
-
base
これは、すべてのボタンに共通して適用される基本のスタイルを定義します。上記の例では、'py-2 rounded text-center'
が基本スタイルとして設定されています。これにより、すべてのボタンに対して、一定のパディング、角丸、およびテキストの中央揃えが適用されます。 -
variants
ここでは、動的に変更できるクラスのバリエーションを定義します。上記の例では、color
とsize
の2つのバリエーションが設定されています。-
color
:primary
とsecondary
の2つのオプションがあり、それぞれ異なる背景色や文字色が設定されています。 -
size
:sm
,md
,lg
の3つのオプションがあり、それぞれ異なるボタンの幅が設定されています。
-
-
defaultVariants
これは、variants
で定義したバリエーションのデフォルト値を設定します。上記の例では、color
がprimary
、size
がmd
に設定されており、tv()
を呼び出す際に引数を省略すると、これらのデフォルト設定が適用されます。
使用方法
tv()
関数を使って、ボタンに動的にスタイルを適用するには、以下のようにクラスを呼び出します。
<button className={button({ color: 'primary', size: 'lg' })}>Button</button>
修正後の状態で再度ブラウザで表示すると、修正前と同じようにボタンが表示されます。
所感
Tailwind Variantsの導入についてまとめてみました。
Tailwind Variantsを使用することで動的なスタイリングを簡潔に管理でき、スタイルの管理が非常に効率的になっているように感じました。
今回紹介した機能はあくまで機能の一部なので、興味がある方は是非触ってみて下さい。
参考資料