Simplify CSS for `*-0` and `*-1` spacing utilities
TailwindCSS now emits plain 0 or var(--spacing) for spacing utilities ending with -0 or -1 instead of the verbose calc(var(--spacing) * 0) / calc(var(--spacing) * 1). これにより生成される CSS が軽量化され、ブラウザのパーサ負荷が軽減されます。
背景
Tailwind が生成する CSS には、inset-0{inset:calc(var(--spacing) * 0)} のように calc(... * 0) が頻出し、実質的に不要な計算式が多数含まれていました。 これらは視覚的にも冗長であり、デバイス側の CSS パーシングコストを無駄に増やす要因となっていました。
実際にサイトを検証すると、inset-x-0、top-0、m-0 など 0 系ユーティリティが全て同様の calc 式で出力され、-1 系ユーティリティ でも calc(var(--spacing) * 1) が出力されていました。 こうしたコードは人間の可読性も低く、最適化の余地が大きいことが明らかです。
この問題を解消することで、生成 CSS のサイズ削減とパーサ負荷の低減という二重の効果が期待できるため、変更の対象となりました。
技術的な変更
本 PR では spacing 関数 とユーティリティ生成ロジックに最適化を導入し、0 と 1 の場合は直接リテラルに置き換えるようにしました。 変更点は主に css-functions.ts、utilities.ts、およびテストコードです。
css-functions.ts の最適化ロジック
@@ -62,6 +63,22 @@ function spacing(
- return `calc(${multiplier} * ${value})`
+ // Optimization:
+ // - value === 0 → "0"
+ // - value === 1 → multiplier (i.e. var(--spacing))
+ let valueDimension = dimensions.get(value)
+ if (valueDimension) {
+ if (valueDimension[0] === 0) return '0'
+ if (valueDimension[0] === 1) return multiplier
+ }
+ return `calc(${multiplier} * ${value})`
ここでは dimensions ユーティリティを利用して入力値を数値化し、0 と 1 が検出された場合にそれぞれ '0' と multiplier(var(--spacing))を返すようにしています。 それ以外のケースは従来通り calc 式を生成します。
utilities.ts のハンドラ拡張
@@ -550,14 +552,14 @@ export function createUtilities(theme: Theme) {
- return `calc(${multiplier} * ${value})`
+ return `--spacing(${value})`
@@ -568,6 +570,8 @@ export function createUtilities(theme: Theme) {
- return `calc(${multiplier} * -${value})`
+ return `--spacing(-${value})`
functionalUtility が handleBareValue と handleNegativeBareValue で --spacing(...) 記法を返すようになり、内部で先述の spacing 関数が最適化を適用します。 これにより m-0 は margin: 0;、m-1 は margin: var(--spacing); と出力されます。
テストの追加と期待出力
+expect(await compileCss(`.foo { margin: --spacing(0); }`)).toMatchInlineSnapshot(`".foo { margin: 0; }"`)
+expect(await compileCss(`.foo { margin: --spacing(1); }`)).toMatchInlineSnapshot(`".foo { margin: var(--spacing); }"`)
css-functions.test.ts と utilities.test.ts に新たに 最適化の検証テスト が追加され、0 と 1 が正しく簡略化されることが自動的に保証されます。
結論
spacing とユーティリティ生成のロジックに最小限の分岐を加えるだけで、生成 CSS が calc 式からシンプルなリテラルへ置き換わります。 これによりビルド産物が軽量化され、実行時のパーサ負荷が減少しますが、既存のユーティリティ API は一切変更されません。
設計判断
本変更は 後方互換性を保ったまま 出力を最適化するという設計方針に沿っています。 既存の --spacing カスタムプロパティやユーティリティ名はそのままで、内部ロジックだけが拡張されました。
dimensions.get による数値判定は 長さユニットに限定 されており、0px や 0rem などのゼロ系長さだけが対象です。 そのため他の非長さ値や演算式に対しては従来通り calc が使用され、期待された動作は維持されます。
このアプローチはコードベースへの侵入度が低く、テストカバレッジで確実に検証できる点が評価されました。 変更箇所は数百行に留まり、ビルドロジック全体への影響は限定的です。
まとめ
TailwindCSS は *-0 と *-1 ユーティリティの生成ロジックに最適化を導入し、calc(var(--spacing) * 0) → 0、calc(var(--spacing) * 1) → var(--spacing) と置き換えることで CSS の体積とパーサ負荷を削減しました。 変更は内部実装に留まり、公開 API は変更せずに効果を得ています。