prose.css に @scope を導入し、wa‑prose と wa‑not‑prose の近接認識を実装
@scope を用いて prose.css のルールをラップし、wa-prose と wa-not-prose が入れ子構造でも期待通りに適用・除外できるようになりました。この変更はレイヤー優先順位と CSS Specificity の二重課題を根本的に解決します。
背景
現在の実装では wa-prose と wa-not-prose が同一 @layer wa-utilities 内で定義されており、wa-not-prose がレイヤー全体のプロパティを revert-layer で巻き戻すため、他ユーティリティのフォントサイズやマージンリセットまで無効化していました(問題 1)。
さらに、wa-not-prose の方が Specificity が高く、wa-prose を wa-not-prose 内に配置しても再度 wa-prose を有効化できず、問題 2 が発生していました。このため、ドキュメントとコード例のスタイルが不整合になるケースが多数報告されていました。
これらの課題は、wa-prose と wa-not-prose が要素の近接性(proximity)に応じてスタイルを切り替えることができないことに起因します。そこで、スコープベースの解決策が採られました。
技術的な変更
@scope を利用して :where(.wa-prose) と :where(.wa-not-prose) をそれぞれ from と to の範囲でラップしました。これにより、スコープ外のスタイルは影響しず、入れ子構造でも正しく継承・除外が行われます。
@@
- :where(.wa-prose) {
- /* 旧実装 … (省略) */
- }
+ @scope (.wa-prose) to (.wa-not-prose) {
+ /* 新実装 – ルートは 0,0,0 Specificity のまま、内部は従来通り */
+ --wa-prose-rhythm-scale: 1;
+ /* 省略: 既存トークン・ヘディング定義など */
+ }
コードブロックの前後には必ず空行を入れ、差分の削除行(-)と追加行(+)を明示しています。変更前は :where(.wa-prose) のみで定義され、wa-not-prose がレイヤー全体に影響していましたが、@scope に置き換えることで wa-not-prose はスコープ外に限定されます。
この変更は prose.md と changelog.md の記述も更新し、利用例に wa-prose wa-font-size-s のように他ユーティリティと併用できることを示しています。ドキュメント側のコード例も wa-callout での wa-not-prose 使用例へと刷新され、実際の挙動が視覚的に確認できるようになりました。
設計判断
@scope の採用は、既存のユーティリティレイヤー構造を崩さずに近接感知を実装できる最小侵襲な手法として選ばれました。代替案として新規クラスや !important に頼る方法も検討されましたが、後方互換性とメンテナンス性を重視した結果、標準化された CSS 機能である @scope が最適と判断されました。
この設計は「レイヤーは変えずにスコープだけを切り替える」という方針に沿い、他ユーティリティ(例: wa-stack, wa-font-size-*)への副作用を防ぎます。また、@scope はブラウザの最新二世代でサポートされているため、プログレッシブエンハンスメントとして安全に導入可能です。
まとめ
prose.css に @scope を導入したことで、wa-prose と wa-not-prose が入れ子でも正しく適用・除外でき、レイヤー優先順位と Specificity の問題が根本的に解消されました。既存コードへの影響は最小限で、ドキュメントも新しい利用パターンに合わせて更新されています。