前置知識#
Tailwind CSS を使用する際、クラス名の組み合わせは一般的なニーズです。私たちは通常、cn
という名前のメソッドを使用して、クラスを効率的かつ優雅に管理します。これは通常、以下の 2 つの一般的なツールをラップしています。
1. clsx
#
- より軽量で、パフォーマンスに優れた
classnames
の代替品。 - 文字列、オブジェクト、配列などの形式でクラスを組み合わせることをサポート。
- 例:
clsx('btn', { 'btn-primary': isPrimary }) // => 'btn btn-primary'
2. tailwind-merge
(略してtwMerge
)#
- 衝突する Tailwind CSS クラス名をマージするためのもの。
text-sm text-lg
のような衝突を処理し、最後の優先度が高いクラスを保持します。- 例:
twMerge('text-sm text-lg') // => 'text-lg'
3. cn
メソッドのラップ#
上記の 2 つのライブラリを組み合わせて、統一されたcn
メソッドを作成します:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(...inputs))
}
4. なぜclassName
を最後の引数にするのか?#
ユーザーが渡すスタイルがデフォルトスタイルを上書きできるように、className
を最後に置くことを推奨します:
cn('default-class', className)
twMerge
は左から右にマージされるため、後のクラスが優先的に保持されます。順序が逆になると、コンポーネントのデフォルトスタイルがユーザーの意図を上書きしてしまう可能性があります。
私は何をしましたか?#
className
を引数の末尾に置く実践の一貫性を保つために、Grok3 の支援を受けて、静的検出と自動修正を行う ESLint プラグインを開発しました。Eslint v7-v9 に対応しています。
ソース:#
eslint-plugin-classname-arg-last
例:#
// エラー例
cn(className, 'text-sm')
// 正しい書き方
cn('text-sm', className)
設定方法:#
.eslintrc.js
に追加:
module.exports = {
// ...
plugins: ['classname-arg-last'],
rules: {
'classname-arg-last/classname-arg-last': 'error',
},
}
このプラグインを使用することで、開発段階での規範を統一し、順序の問題によるスタイルの上書き衝突を減らすことができます。