Tailwind CSSを安全に上書きして補完・ソートもできる自作関数を作ってみた
自己紹介
Toshikiといいます。
普段はNext.js, React Nativeを中心にフロントエンド開発をしています。
こんな悩みありませんか...?
- Tailwind CSSのクラス名が上書き出来ない時があって困っている
- コンポーネントの外からTailwind CSSのクラスをあてたい
- 自作関数の実引数でTailwind CSS Intellisenseで補完を効かせたい
- 並べ替えもしたい!!
今回は上記の悩みを解決すべく、私なりに調べた結果をまとめようと思います!!
問題の確認(クラス名上書きの失敗例)
// デフォルトで赤色のタイトルを表示するコンポーネント
type TitleProps = {
className?: string
children: string
}
const Title: FC<TitleProps> = ({ className, children }) => {
return (
<h2 className={clsx(className, 'text-5xl font-bold text-red-500')}>
{children}
</h2>
)
}
// 複数のタイトルを表示するコンポーネント
const TitleListPage: NextPage = () => {
return (
<>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title className='text-blue-500'>青色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
<Title>赤色のタイトル</Title>
</>
)
}
export default TitleListPage
結果↓↓
結果を見て分かる通り、Titleコンポーネントを呼び出す際のtext-blue-500
がうまくいっていません。原因としては、元々のtext-red-500
とtext-blue-500
が重複しているため、Tailwind CSS側で先に定義されているtext-red-500
が優先されてしまっていると考えられます。
解決策
後ろのクラス名を優先して重複を排除してくれるこちらのライブラリを使います!
使い方
import { overrideTailwindClasses } from 'tailwind-override'
overrideTailwindClasses('pt-2 pt-4')
// => 'pt-4'
overrideTailwindClasses('text-pink-200 text-blue-200')
// => 'text-blue-200'
overrideTailwindClasses('text-pink-200 pt-2')
// => 'text-pink-200 pt-2' (don't clash)
overrideTailwindClasses('orange apple')
// => 'orange apple' (not tailwind classes)
overrideTailwindClasses('dark:md:text-pink-200 dark:md:text-blue-200')
// => 'md:text-pink-200 md:text-blue-200'
overrideTailwindClasses('text-pink-500 !text-[#ffaa11]/25')
// => '!text-[#ffaa11]/25'
とてもシンプルで分かりやすいですね!!
ついでにclsxの書き心地で書けるようにしておきましょう!
import clsx, { ClassValue } from 'clsx'
import { overrideTailwindClasses } from 'tailwind-override'
export const cn = (...classNames: ClassValue[]) => {
return overrideTailwindClasses(clsx(...classNames.reverse()))
}
何回も呼び出すことになるので関数名をcn
としました。
overrideTailwindClasses
は後ろのクラス名を優先するので、...classNames.reverse()
とすることで前に書いたクラス名を優先するようにしました。
動作確認
先ほどのコードのclsx
部分を自作したcn
に置き換えます。
const Title: FC<TitleProps> = ({ className, children }) => {
return (
- <h2 className={clsx(className, 'text-5xl font-bold text-red-500')}>
+ <h2 className={cn(className, 'text-5xl font-bold text-red-500')}>
{children}
</h2>
)
}
結果↓↓
成功しました!検証ツールで開いても綺麗に上書き出来ているのが確認できます。
でもまだ問題が残っています。
cn
の呼び出す際の引数にはTailwind Intellisenseもソートも効きません。
これらも解決していきます!
自作関数cnの実引数にTailwind CSSクラスの補完を効かせる
自作関数の実引数にTailwind CSSクラスの補完を効かせるにはsettings.jsonに下記の設定を追加します。
参考Issue
{
"tailwindCSS.experimental.classRegex": [["cn\\(([^)]*)\\)", "'([^']*)'"]]
}
自作関数cnの実引数でソートできるようにする
まず下記のサイトを参考にeslint-plugin-tailwindcssを導入します。
導入ができたらeslintの設定に下記を追加します。
{
"settings": {
"tailwindcss": {
"callees": ["classnames", "clsx", "ctl", "cn"],
}
}
}
さいごに
今回は備忘録も含めTailwind CSSクラスの上書き、補完、ソートについてまとめてみました!
少しでもこの記事がお役に立てれば嬉しいです!!
Tailwind CSS最高!!!!!
Discussion