🎨 CSS Advent Calendar: Day 5 / Cascade for Cascading Style Sheets - Behind the Scenes of Importance

Published on

Updated on

Cascade の登場と Importance の裏側

Table of Contents

Table of Contents

はじめに

今回はいよいよ “CSS” の Cascade についてです。

CSS は CHSS を前身として、Hakon Wium Lie と Bert Bos によって 1995 年に提案されました。提案最初の Editors Draft は以下とされています。

最初の Working Draft (First Public Working Draft) は同年の後半に公開されています。

そして、以下が CSS1 の最終形態で 1996年12月に、W3C の Recommendation として勧告されたものです。

今回は、この最終形態の CSS1 の仕様をもとに、Cascade の裏側を解釈してみようと思います。

The Cascade

単一のスタイルシートがプレゼンテーションに “Influence” すること以上に、「複数のスタイルシートが相互に影響して “Influence” するために、なぜ “Cascade” という方法論である必要があるのか」ということを、CSS の仕様では、“Modularity”“Balance” に分けて説明しています。

Modularity for the Cascade

Modularity が可能にすることは、「スタイルシートの統合による、冗長性の排除」です。 @import を使うことで、別のスタイルシートの内容を継承して取り込む以下の記法のことです。

@import url(http://www.style.org/punk);
@import url(http://www.style.org/funk);

H1 { color: red }     /* override imported sheets */

ただし、競合が発生した場合、@import されたスタイルシートの優先度は、@import 元のスタイルシートの優先度よりも低くなるというのも考慮されています。

CHSS でも、「LINK のスタイルシートは読み込み順に優先度が決まる」という記述がありましたが、@import はその延長線上の考え方です。

Balance

Modularity は「同一オリジンでのスタイルシートの統合」の話でしたが、Balance は基本的に「異なるオリジンでのスタイルシートの統合」の話です。

オリジンの種別としては、この時点では2種類が触れられています。「User」 と 「Author」 です。User は、Web ページを閲覧する人(読者)、Author は、Web ページを作成する人(開発者)を指します。

User と Author という異なるオリジンから、同じ場所にスタイルを Influence 可能にするとなると、どちらも同じスタイルシート言語を使うことが妥当になります。

both readers and authors can influence the presentation through style sheets. To do so, they use the same style sheet language thus reflecting the philosophy of the web: everyone can become a publisher.

Cascading Style Sheets, level 1

そうした時に、User/Author 間で競合が起きた場合はどうするかを考える必要があります。

Conflict resolution is based on each style declaration having a weight. By default, the weights of the reader’s declarations is less that the weights of declarations in incoming documents. I.e., if there are conflicts between the style sheets of an incoming document and the reader’s personal sheets, the incoming declarations will be used.

デフォルトでは、User スタイルシートの優先度は、Author スタイルシートの優先度よりも低くなるように設定されます。その上で、Author オリジンではスタイルシートのロード順(@importの親から順、<LINK> のロード順)に優先度が高くなります。この「デフォルトでは User < Author スタイル」の考え方も CHSS と同じです。

!important

ただし、CHSS になかったものとして、!important キーワードが導入されました。

H1 { color: black ! important; background: white ! important }
P  { font-size: 12pt ! important; font-style: italic }

!important を用いると、その宣言の優先度を上げることができます。

CHSS では、これをパーセンテージで「どの程度影響力があるか」を表現していましたが、CSS1 では !important を用いて、「どちらの方が影響力があるか」という 0/100 で影響力を表現するようになります。「最終的には単一の宣言のみしか採用されない」ということを考えると、パーセンテージで範囲を持つ意味はなかったのです。

この !important のオリジン間での優先度に関しては、以下のような記述があります。

A reader rule with an important declaration will override an author rule with a normal declaration. An author rule with an important declaration will override a reader rule with an important declaration.

「Author !important が User !important よりも優先される」

この先に勧告される CSS2 の Working Draft でも、この定義は変更されていませんでした。

I am !important ! Please DO NOT override me

しかし、1998年に勧告された CSS2 の Proposed Recommendation で、この定義に関して劇的な見直しが行われることになります。

CSS attempts to create a balance of power between author and user style sheets.

for balance, an “!important” declaration (the keywords ”!” and “important” follow the declaration) takes precedence over a normal declaration. Both author and user style sheets may contain “!important” declarations, and user “!important” rules override author “!important” rules.

Note. This is a semantic change since CSS1. In CSS1, author “!important” rules took precedence over user “!important” rules. Assigning property values, Cascading, and Inheritance

この記事を読んでいる人であればご存知だと思いますが、これが現在の Cascade の形です。

CSS1, CSS2 の Working Draft まで、 「Author !important が User !important よりも優先される」という定義でしたが、CSS2 の Proposed Recommendation を以て、この順序が変更されました。 「User !important が Author !important よりも優先される」という定義は、CSS の最初から存在していたわけではなく、CSS1 最初の提案から約 3 年後に変更されたものです。

仕様にもある通り、これは単なる仕様変更ではなく、「a semantic change」と明記されています。 Author !important が User !important よりも優先されるという、常に Author の権限が大きかった時代から、User の権限を大きくできる可能性を持てるようになりました。「a balance of power」が User と Author の間で取れるようになったのです。


こうした背景を踏まえると、!important が Cascade においてどういう意味を持つべきとされているのかが見えてきます。

もちろん、!important を用いれば、同一オリジン間での優先度を上げるような使い方もできます。例えば、拡張機能など、いかなる状況でも詳細度を上げなければどうしようもない局面においては、!important を用いて「最大限の影響力」を表現をするのは仕方がありません。

しかし、!important はあくまで「balance」を取るために導入されたものであり、non-!important な宣言に対しても、「balance」を取る目的で利用されることが望まれています。

for balance, an “!important” declaration takes precedence over a normal declaration.

それゆえ、他の宣言を無理矢理上書きする目的で !important を用いて、何かを「上書き」する場合は、仕様の想定に反した使い方をしている可能性があることを、ぜひ念頭に置いておきたいものです。

Appendix