現状
#17 のようなコンポーネントにデフォルトのスタイルを設定しつつ、background-color
などを含めたスタイルを外部から変更できるようにしたい場合に必要となる。
このとき、TailwindCSSを使用しているため、「className
をProps
として受け取り自身のクラス指定に追加する」といった実装となる。
しかし、Tailwindは下記のように、ユーティリティクラス名のみでスタイルを指定するため、すべてのスタイルが同じ詳細度を持つ。したがって、その優先順位は記述されたCSSがより後に読み込まれたものが優先される。
.text-neutral-900 {
--tw-text-opacity: 1;
color: rgb(8 15 22 / var(--tw-text-opacity));
}
CodePenでCSSの動作を確かめる
考えられる対応策
参考 [Feature Proposal] CSS class override utility for component composition.
#1446
その1: !important
でデフォルトのものを上書きする
使うべきではないと思う
<Button className="!bg-success-700">
Hello world!
</Button>
その2: :where()
疑似クラスを使ってデフォルトのスタイルの詳細度を0にしておく
where:bg-***
のようにTailwindのVariantとして使えるようにプラグインを書く。
使う側は、その1とは違い!important
をつけるなどの配慮をしなくてよい。
追記
Insane idea to give components overridable default TW classes #3523
// 詳細度を0に設定する擬似クラス:where()をバリアントとして追加する
plugin(({ addVariant, e: escape }) => {
addVariant('where', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `:where(.${escape(`where${separator}${className}`)})`;
});
});
}),
:where()
で囲んだだけではリセットCSSにも勝てないくそざこなめくじになってしまいデフォルトのスタイルが適用できず、
body :where()
のようにしてTailwindのユーテリティクラス以下リセットCSS以上の詳細度を適用しようとしても、必要な詳細度の基準がリセットCSSの定義によって変わってしまうから扱いづらい。ので:where()
で詳細度を下げるのは現実的ではないと思いました
tailwind-override
参考: Zenn.dev
- .tailwind.config.js
を読み取ってカスタムクラスまで対応してくれるのかが不明
- CSSの詳細度の問題をJS/TS側で無理やり対処しているところがすっきりしない
- GitHubのスター数が84で頼りない
tailwind-merge
import { twMerge } from 'tailwind-merge'
twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hover:bg-dark-red p-3 bg-[#B91C1C]'
クラス名に対立(Conflict)する複数のTailwindユーティリティクラスが存在する場合、後ろのものを優先して抜き出してくれる関数twMerge
を提供するパッケージ。
- キャッシュと遅延計算でパフォーマンスが考慮されている
Optimized for speed
Results get cached by default, so you don't need to worry about wasteful re-renders. The library uses a LRU cache which stores up to 500 different results. > The cache size can be modified or opt-out of by using extendTailwindMerge.
Expensive computations happen upfront so that twMerge calls without a cache hit stay fast.
These computations are called lazily on the first call to twMerge to prevent it from impacting app startup performance if it isn't used initially.
- コンフィグを設定すれば
.tailwind.config.js
に記述したgradient-*
などの独自のクラスにも対応できる
- GitHubスター数563と多め
- 直近コミットが16日前
その4: カスタムクラスを@layer components
で作成する
Tailwindはここで定義されたものを含むcomponents
クラスをbg-red-500
等のユーティリティクラスよりも前に挿入するから、それを使用したスタイルの上書きが適切に行えるようになる。しかし、多階層の上書きはできない