`@utility` に `--default(…)` を追加してフォールバック値をサポート

tailwindlabs/tailwindcss

--value(…) および --modifier(…) の内部で --default(…) を使えるようになり、値なしでも機能する functional utility をCSSだけで定義できるようになりました。

背景

@utility の functional utility は、これまで値(value)が必須でした。たとえば tab-* というユーティリティを定義しても、tab 単体では値が null になるためクラスが生成されず、tab-4 のように明示的な値を必ず付けなければなりませんでした。#16824 では、modifier についても同様の問題が報告されています。@utility text を静的に定義すると text/50 のような modifier 付きの表記が解釈されず、modifier を使うためだけに text-* という functional utility の形を取らざるを得ませんでした。

この制約は、既存のJSベースのAPIでは対応できていた shadow/50 のような「値なし・modifier あり」のパターンが、CSSベースの @utility では実現できないことを意味していました。結果として、ユーザーはCSSだけで記述できるケースでもJSベースのAPIに頼らざるを得ないという状況が生じていました。

技術的な変更

--value(…)--modifier(…) の引数として --default(…) という新しい構文が追加され、値や modifier が省略された場合のフォールバックを宣言できるようになりました。

基本的な使用例を示します。

@utility tab-* {
  tab-size: --value(integer, --default(4));
}

この定義により、以下の挙動が得られます:

  • tabtab-size: 4--default(4) が適用される)
  • tab-123tab-size: 123integer 型の値として解決される)
  • tab-foo → 生成なし(integer でも default でもない)

calc() などの複合式の中でも動作します。

@utility tab-* {
  tab-size: calc(--value(integer, --default(4)) * 2);
}

この場合、tabtab-size: 8tab-123tab-size: 246 として解決されます。実装面では、packages/tailwindcss/src/utilities.ts において、value === null の場合に即座に処理を打ち切っていた箇所が削除されました。代わりに、--default(…) が解決できたかどうかを追跡する仕組みが導入され、値が解決できない場合はその宣言を取り除く制御に変更されています。また、--modifier(…) に対しても同様に --default(…) がサポートされ、text-sm のようにデフォルトの line-height を設定するユーティリティを modifier なしで記述できるようになっています。

設計判断

--default(…)--value(…) の内部引数として明示する方式 が採用されました。

PR内では複数のアプローチが検討されました。一つは、静的な宣言をフォールバックとして並べる方式です。

@utility tab-* {
  tab-size: 4;
  tab-size: --value(integer);
}

しかしこの方式には、tab-foo のような無効な値でも tab-size: 4 を持つクラスが生成されるという問題があります。無限個のクラスが同一のCSSを生成してしまい、不正な入力を静かに受け入れてしまいます。別の候補として --value(…, 4) のように直接フォールバックを末尾引数として渡す方式も検討されましたが、数値・キーワードが既存の解決ロジックで誤解釈されるリスクがありました。--default(…) を独立した関数として扱う現行の設計は、フォールバックであることを明示しつつ、tab-foo のような無効なクラスを生成しない安全な制約を維持しています。また、calc() 内のような複合プロパティ値の中でも機能するため、別プロパティの重複定義が不要になるという実用上のメリットもあります。

まとめ

--default(…) の追加により、shadow/50tab のような「引数省略可能な functional utility」がCSSベースの @utility だけで完結して定義できるようになりました。JSベースのAPIとのギャップが埋まり、CSSファーストなユーティリティ定義の表現力が大きく向上しています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
2ad7a415

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)」の3部構成が明確に適用されており、理想的な記事構成です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックのシンタックスハイライト、PR番号・Issue番号のリンク記法など、すべてのカスタムMarkdown構文が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Tailwind CSSの`@utility`機能に関する深い知識を前提としており、専門知識を持つエンジニアという対象読者に完全に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクション、各パラグラフが「総論→各論」の構成になっており、トピックセンテンスが段落の先頭に配置されているため、非常に高い可読性を確保しています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコード例は、提供されたDiff内のテストコードと完全に一致しており、正確です。実装面の解説もDiffの変更内容を正しく反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「functional utility」「--value()」「--modifier()」「--default()」など、PRやTailwind CSSの文脈で使われる技術用語が正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

新機能の挙動、実装の変更点、設計判断の背景にある技術的なトレードオフに関する説明は、すべてPR情報とDiffによって裏付けられており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張は、PRのTitle, Description, Diffの内容に基づいており、根拠のない推測や憶測(ハルシネーション)は一切見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号「#19989」や関連Issue番号「#16824」などの数値・固有名詞はすべて正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「`@utility` に `--default(…)` を追加してフォールバック値をサポート」は、PRの主題を的確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に含まれていないバージョンのサポート状況やリリース日程などの外部知識は記載されておらず、事実に基づいた記述に徹しています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「JSベースのAPIに頼らざるを得ないという状況が生じていました」といった過去形の表現は、PR Descriptionの「it's more like a missing feature right now」という現状認識と一致しており、時間表現は正確です。