Open
5

Shadow DOMによりスタイルが閉じ込められる仕組み

Shadow DOMによるスタイルのスコーピング周りの仕様を調べたい

Shadow DOMの中に書かれたstyle要素は同じShadow DOMの中にしか影響を及ぼさない。このことの根拠となる仕様を調べたい。

style要素がCSSとして認識される仕組み

HTML仕様書のstyle要素の定義に次の記述がある:

The user agent must run the update a style block algorithm whenever one of the following conditions occur:

update a style blockアルゴリズムはCSSOMで定義されるCreate a CSS style sheetアルゴリズムを呼び出す。

Create a CSS style sheetは内部的にAdd a CSS style sheetを呼び出し、the list of document or shadow root CSS style sheets に作られたCSS style sheetを追加する。

  1. Add the CSS style sheet to the list of document or shadow root CSS style sheets at the appropriate location. The remainder of these steps deal with the disabled flag.

以上によりstyle要素がCSSスタイルシートとしての効力を発揮することが分かる。appropriate locationというのが具体的にどこかというのは、the list of document or shadow root CSS style sheetsがtree orderと定義されていることから分かる。

このリストについては次のように定義されている。

Each DocumentOrShadowRoot has an associated list of zero or more CSS style sheets, named the document or shadow root CSS style sheets. This is an ordered list that contains all CSS style sheets associated with the DocumentOrShadowRoot, in tree order, with CSS style sheets created from HTTP Link headers first, if any, in header order.

このことからそれぞれのDocumentまたはShadowRootがCSS style sheetsのリストを持っていることが分かかる。どのリストに追加されるのかは仕様に明記されていないが、CSS style sheetの作成時にowner nodeの情報が渡されているので、どのリストに属するのかは判定可能であると考えられる。

リストに属するCSSが具体的にどのように効力を発揮するのかは別の仕様で定義されると考えられる。

Selectors Level 4

Selectors Level 4という仕様ではMatch a selector against a treeアルゴリズムを定義している。このアルゴリズムはセレクタとroot elementsを受け取り、root elementsの配下にある要素のうちセレクタにマッチする要素の一覧を返すアルゴリズムである。

このアルゴリズムはShadow DOMの中まで探すことはなく、root elementsとしてLight DOMの要素が与えられた場合はShadow DOMの要素を返さない。

このアルゴリズムは例えばDOMのquerySelectorAllの仕様から使われている

CSSルールがどの要素に対して適用されるのか決定する際にこのアルゴリズムが使用されることが期待される。

と思いきや……

Cascading and Inheritance Level 4

こういうときに関係ありそうな仕様といえばCSS Cascading and Inheritance Level 4である。

特に、5. Filteringで、どの要素に対してどのスタイルが適用されるのかが定義されている。

どれどれ……

ISSUE 1 Define whatever it is that Shadow DOM needs here.

なるほど……

まだShadow DOMについては定義されていなかった😇

ということで、Shadow DOMのCSS Scopingに関してはまだ仕様がなくお気持ちで定義されていることがわかった。

余談: 中と外の優先度

Shadow DOM内のCSSはShadow DOM内にのみ効果を及ぼすのが原則だが、実は :hostだけはShadow DOMの中からShadow DOMの外の要素を参照することができる。このことについてはCSS Scoping Module Level 1の中の「Why is the shadow host so weird?」というコラムで言及されている。また、これに関連してSelectors 4の中でfeaturelessという概念が定義されているので一読の価値がある。

Shadow DOMの中から外の要素にスタイルを与えることができるとなると、Shadow DOMの中と外のスタイルがコンフリクトしたときにどちらが優先されるのかという問題がある。

Cascading and Inheritance Level 4ではContextによるルールの優先付けが定義されており、normalな(!importantではない)ルールではShadow DOMの中よりも外が優先される一方で、!importantはルールではShadow DOMの外よりも中が優先されると定義されている。

デモ:

ログインするとコメントできます