Tailwindクラスを柔軟にするライブラリ
投稿日: 2025/5/12
Tailwind
clsx × tailwind-merge × cva の使い方
はじめに
clsx × tailwind-merge × cvaの使い方や役割がちゃんとわかっていなかったので学んだ内容を書きました。
clsx
https://github.com/lukeed/clsx
軽量かつ高速なユーティリティライブラリ
クラス名を簡単に結合してくれる
import { clsx } from 'clsx';
clsx('foo', 'bar', 'baz');
// => 'foo bar baz' 空白で出力
clsx(true, false, '', null, undefined, 0, NaN);
// => '' falseyは除外
clsx(['foo', 'bar']);
// => 'foo bar' 配列やobjもOKtailwind-merge
https://github.com/dcastil/tailwind-merge
サイズは898kBでclsxの100倍だけど軽量の部類だと思う
Tailwind のクラス競合を解決してくれる
clsx('bg-red-500', 'bg-blue-500')
// => 'bg-red-500 bg-blue-500'
import { twMerge } from 'tailwind-merge'
twMerge('bg-red-500 bg-blue-500')
// => "bg-blue-500"
twMerge(clsx( // ← clsxの併用でクラス名を結合
'px-4 py-2',
'bg-blue-500',
'bg-red-500' // ← 最後のものが優先されるよう自動解決
))
// => 'px-4 py-2 bg-gray-500'class-variance-authority
https://github.com/joe-bell/cva
Tailwind CSS のクラスを構造的かつ再利用可能な形で定義できる軽量ライブラリ
Variants(バリエーション)の管理がしやすくなり、スタイルを一元化・拡張しやすくなる
import { cva } from 'class-variance-authority'
const button = cva('px-4 py-2', {
variants: {
intent: {
primary: 'bg-blue-500 ',
secondary: ['bg-gray-100'], ← 配列もOK
},
size: {
sm: 'text-sm',
md: 'text-base',
},
},
defaultVariants: {
intent: 'primary',
size: 'md',
},
})
button({ intent: 'secondary', size: 'sm' })
// => 'px-4 py-2 bg-gray-100 text-sm'clsx × tailwind-merge × class-variance-authority
3つを組み合わせると、柔軟で安全にクラスを構築できる
- clsx: 条件によってクラスを結合
- twMerge: クラスの競合を最適化
- cva: 再利用可能なクラス定義 + variant管理
// 1. cvaで定義
const button = cva('px-4 py-2', {
variants: {
intent: {
primary: 'bg-blue-500',
secondary: 'bg-gray-100',
},
size: {
sm: 'text-sm',
md: 'text-base',
},
},
defaultVariants: {
intent: 'primary',
size: 'md',
},
})
// 2. 動的に組み合わせたクラスをtwMergeで最適化
const className = twMerge(
clsx(
button({ intent: 'secondary', size: 'sm' }),
'bg-red-500', // 外から上書きしたい場合もOK
)
)
// => 'px-4 py-2 rounded text-sm bg-red-500'まとめ
- cvaを使ってバリエーションを構造化
- clsxとtwMergeでクラスを柔軟に制御
それぞれのライブラリの使い方と役割が明確になりました🙋♂️