1. カスタム要素に対する既定のスタイル
この節は、 試験的であり,論の最中にある。 実装する前に,CSS WG に諮ること。 This section is experimental, and is under active discussion. Do not implement without consulting the CSSWG.
カスタム要素を定義するときは、 それ用に[ 組み込みの要素に適用される UA スタイルと同類な, “既定のスタイル” ]を設定しておくよう求まれることが多い。 あいにく,従来の CSS でこれを行うことは、 次に挙げることから難しい: When defining custom elements, one often wants to set up "default" styles for them, akin to the user-agent styles that apply to built-in elements. This is, unfortunately, hard to do in vanilla CSS, due to issues of scoping and specificity—\
-
視野法の課題: 当の要素は,shadow ツリー内で利用されるかもしれない — その場合、 文書ツリー†内にある,要素をターゲットしている選択子 ]からは到達不能になる。
【† 原文には, “最も外縁な文書( outermost document )” と記されているが、 実際には,文書ツリーを指す (スタイルシートは、複数の文書に適用し得ない)。 この仕様に現れる語 “文書” は, 実際にはノードツリー — [ 文書ツリー, shadow ツリー ]の総称 — を意味する箇所が多いので、 この訳では,そのように改める。 】
the element in question might be used in shadow trees, and thus is unreachable by any selector targeting it in the outermost document;\ - 詳細度の課題: 型選択子の様な詳細度が低い選択子でも、[ 当の要素をターゲットするよう意図された,作者レベルのスタイル ]を不用意に上書きし得る。 and selectors, even low-specificity ones like simple type selectors, can accidentally override author-level styles meant to target the element.
これを援助するため、 この節では,[ 所与の要素に “既定の要素スタイル” を与えるスタイルシート ]の作成法を定義する。 この種のスタイルシートは、[ 文書全体, および すべての shadow ツリー内 ]にわたって適用され、 その中の各規則は — 作者レベルの規則が自動的に優先されるよう — UA 出自の下で適用される。 To aid in this, this section defines a way to create a stylesheet of "default element styles" for a given element. This stylesheet applies across the entire document, in all shadow trees, and the rules in it apply at the user agent origin, so author-level rules automatically win.
各 Window
は、
[[defaultElementStylesMap]]
内部 slot を有する
— それは、
要素の局所名をスタイルシートに対応付ける。
それらのスタイルシートは:
Windows gain a private slot [[defaultElementStylesMap]] which is a map of local names to stylesheets.
-
当の window に結び付けられた文書を成す どのノードツリーにも適用するものとする。 加えて,UA スタイルシートとして解釈するものとする。 These stylesheets must apply to every document in the window. They must be interpreted as user agent stylesheets.
注記: このことは、 当のスタイルシートは shadow ツリーにも適用され,その中の宣言は UA 出自になることを含意する。 Note: This implies, in particular, that they apply to all shadow trees in every document, and that the declarations in them are from the user agent origin.
- カスケードの目的においては、 UA の自前のスタイルシートより後の順になる。 この種のスタイルシートどうしの順序は、 観測され得ないので,問われない。 For the purpose of the cascade, these stylesheets are ordered after the user agent’s own stylesheets; their relative ordering doesn’t matter as it is not observable.
- その中の複階選択子は、 無効になるものとする。 Within these stylesheets, complex selectors must be treated as invalid.\
- その中の複合選択子は、[ 次に該当する要素を選択する,型選択子 ]が追加されたものとして扱うものとする。 :その局所名は、 [[defaultElementStylesMap]] 内で当のスタイルシートに対応付けられる Every compound selector must be treated as containing an additional type selector that selects elements with the local name that the stylesheet is keyed with.
この種のスタイルシートに利用可能な at-規則を制約する必要はあるか?
例えば、
@font-face
は許容されるか?
編集者は、
とりあえず,何か不都合を[
聞くまで/聞かない限り
]は、
許容したままにしておくことにする。
Do we need to restrict the at-rules that can be used in these sheets? For example, do we allow an @font-face? I’m going to leave it as allowed unless/until I hear complaints.
この仕様は、 [[defaultElementStylesMap]] を一般に操作する方法 — 追加する, 除去する, その他 — は,定義しない。 そうするための仕方は、 [DOM] などの他の仕様が定義するものと期待される。 【今や、有順序マップ [INFRA] 用の演算として定義されるであろう。】 This specification does not define how to add to, remove from, or generally manipulate the [[defaultElementStylesMap]]. It is expected that other specifications, such as [DOM], will define ways to do so.
2. shadow のカプセル化
2.1. shadow DOM の説明
この節は規範的ではない。This section is non-normative.
この節では、 この仕様が何を定義しているかを[ DOM 標準 [DOM] を全部的に把握せずに理解する ]のを援助するため、 DOM が規範的に定義するいくつかの概念を説明する。 The following is a non-normative explanation of several concepts normatively defined in the DOM Standard [DOM], to aid in understanding what this spec defines without having to fully grok the DOM Standard.
[SELECTORS4] の § データモデル に定義される要素ツリーの各種特性に加え、 DOM 標準は,shadow ツリーに関係するいくつかの新たな概念を追加している。 うちいくつかは CSS にも関連する。 In addition to the qualities of an element tree defined in Selectors Level 4 § data-model, the DOM Standard adds several new concepts related to shadow trees, several of which are relevant to CSS.
要素 ホスト は、 ある shadow ツリー shadow ツリー をホストすることもある — その根である shadow 根 shadow 根 は、 特別な種類の文書片である(要素ノードではない)。 shadow 根 の子孫は、 普通の要素その他のノードからなる。 ホスト は、 shadow 根 のホストであり, 【 shadow ツリー をホストする】shadow ホストになる。 An element can host a shadow tree, which is a special kind of document fragment with a shadow root (a non-element node) at its root. Children of the shadow root are ordinary elements and other nodes. The element hosting the shadow tree is its host, or shadow host.
shadow ツリー 内の要素は、 一般に, ホスト の子孫ではない (子孫結合子の様な選択子の目的も含めて)。 しかしながら, shadow ツリー は、 ホスト が属するノードツリー(light ツリー) light ツリー における平坦ツリーの構築に利用される。 CSS においては、 この平坦ツリーが,選択子より後の すべての目的(継承やボックスの構築なども含む)に利用される。 The elements in a shadow tree are not descendants of the shadow host in general (including for the purposes of Selectors like the descendant combinator). However, the shadow tree, when it exists, is used in the construction of the flattened element tree, which CSS uses for all purposes after Selectors (including inheritance and box construction).
shadow ツリー は、
概ね,[
light ツリー における, ホスト の通常の内容
]に代わって ホスト の内容として扱われる。
しかしながら,[
light ツリー における ホスト の子
]も、
ある slot slot にあてがわれることにより, shadow ツリー の “中に引き込まれる” ことはある
— そのような子は、
CSS の目的においては slot の子として扱われる。
さらには、
slot も,より深い shadow ツリー内の slot にあてがわれることもある。
幸いなことに,[
どの slot も,それ自身は既定ではボックスを生成しない
]ので、[
shadow ツリー を包装して CSS を遮断している slot
要素†のカスケード
]を作者が予測不能になることはない。
【†slot を作成できるのは、この型の要素に限られる。】
Loosely, the shadow tree is treated as the shadow host’s contents instead of its normal light tree contents. However, some of its light tree children can be "pulled into" the shadow tree by assigning them to slots. This causes them to be treated as children of the slot for CSS purposes. The slots can then be assigned to slots in deeper shadow trees; luckily, slots themselves don’t generate boxes by default, so you don’t get an unpredictable cascade of slot wrapper elements disrupting your CSS.
slot に何も明示的にあてがわれていない場合、 代わりに,slot の自前の子たちが “既定の” 内容としてあてがわれる。 If nothing is explicitly assigned to a slot, the slot’s own children are instead assigned to it, as a sort of "default" contents.
2.2. shadow DOM と選択子
2.2.1. shadow ツリーに対する選択子の照合法
選択子が shadow ツリーに対し照合されるときの selector match list† は、 初期時には,[ 先頭の shadow ホスト ]および[ ツリー順序による,shadow ツリーの shadow 根の子孫すべて ]からなるとする。 When a selector is matched against a shadow tree, the selector match list is initially the shadow host, followed by all children of the shadow tree’s shadow root and their descendants, ordered by a pre-order traversal.
† これを【更新された [SELECTORS4] 仕様の】より新たな形の照合アルゴリズムへの call に見合うよう書き直す。 Rewrite this against the newer call forms of the matching algorithms.
注記: shadow ツリーは、 要素の子孫には含まれない — 要素の子孫は、[ light ツリーにおける,要素の子 ]に基づく。 Note: Remember that the descendants of an element are based on the light tree children of the element, which does not include the shadow trees of the element.
ツリーに対し選択子を照合するときの ツリー文脈 は、[ そのアルゴリズムに渡される 根要素 ]の根で与えられる。 ツリー文脈が shadow 根であるとき、 選択子は shadow ツリーの文脈下 で照合されてるという。 When a selector is matched against a tree, its tree context is the root of the root elements passed to the algorithm. If the tree context is a shadow root, that selector is being matched in the context of a shadow tree.
例えば,あるスタイルシートが shadow ツリー内の[
要素内に埋め込まれている/要素からリンクされている
]とき、
そのスタイルシート内のどの選択子も,shadow ツリーの文脈下にある。
shadow 根に対し call される querySelector()
に渡す選択子引数も同様になる。
For example, any selector in a stylesheet embedded in or linked from an element in a shadow tree is in the context of a shadow tree. So is the argument to querySelector() when called from a shadow root.
宣言ブロック内の各宣言は、 それを適用するために照合した選択子のツリー文脈を継承する。 Declarations inherit the tree context of the selector that was matched to apply them.
2.2.2. shadow ツリーの中から shadow ホストを選択するとき
shadow ホスト ホスト は、[ それがホストする shadow ツリー shadow ツリー の外側にある ]ので,普通は[ shadow ツリーの文脈下で評価される選択子からはターゲット不能 ]になる(選択子のターゲットは,単独のツリーに制限される)が、 ときには, shadow ツリー の文脈の内側からも ホスト をスタイル可能になれば有用になることもある。 A shadow host is outside of the shadow tree it hosts, and so would ordinarily be untargettable by any selectors evaluated in the context of the shadow tree (as selectors are limited to a single tree), but it is sometimes useful to be able to style it from inside the shadow tree context.
- 選択子の目的においては、 ホスト は shadow ツリー にも — shadow ツリー の内容が ホスト の子として扱われるように — 現れる (言い換えれば、 ホスト は[ shadow ツリー の根である shadow 根 ]を置換するものとして扱われる)。 For the purpose of Selectors, a shadow host also appears in its shadow tree, with the contents of the shadow tree treated as its children. (In other words, the shadow host is treated as replacing the shadow root node.)
-
ホスト は、
shadow ツリー の中では無特能であると見なされ,
それに合致し得る選択子は[
:host
/:host()
/:host-context()
]疑似クラスに限られる。 When considered within its own shadow trees, the shadow host is featureless. Only the :host, :host(), and :host-context() pseudo-classes are allowed to match it.
注記: なぜ shadow ホストは無特能にされているのか ? Why is the shadow host so weird?
shadow ツリー の外側に居る ホスト のマークアップは、 【 shadow ツリーを内容とする】部品の作者ではなく,ページ作者の制御下にある。 The shadow host lives outside the shadow tree, and its markup is in control of the page author, not the component author.
この部品が、 shadow ツリー 内のスタイルシート内で,ある特定のクラス名を内部的に利用しているとする。 そのような部品を利用しているページ作者が,同じクラス名を偶発的に ホスト に利用した場合、 良くないことが起こる。 そのような状況の結果, 【そのクラス名を選択する選択子を通して,ホストに】 偶発的にあてられるスタイルは、 部品作者には予測不可能であり,ページ作者もデバッグに戸惑うことになる。 It would not be very good if a component used a particular class name internally in a shadow tree stylesheet, and the page author using the component accidentally also used the same class name and put it on the shadow host. Such a situation would result in accidental styling that is impossible for the component author to predict, and confusing for the page author to debug.
しかしながら、[
shadow ツリー 内のスタイルシートが ホスト をスタイルする
]ことが適理になる利用事例は,依然としてある
(例えば,当の部品は flexbox としてレイアウトするよう求まれている場合、
ホスト の display
を設定することが要求される)。
なので、
この状況を許容しつつ,偶発的にスタイルされないようにするため、
ホスト は,[
shadow ツリー には現れる
]が[
完全に無特能
]かつ[
選択するためには、
ページ作者が供したマークアップに対し,部品作者が明示的に[
:host
/ :host()
/ :host-context()
]を通して照合する他にない
]ようにしてある。
However, there are still some reasonable use-cases for letting a stylesheet in a shadow tree style its shadow host. (For example, the component might want to be laid out as a flexbox, requiring the shadow host to be set to display: flex.) So, to allow this situation but prevent accidental styling, the shadow host appears but is completely featureless and unselectable except through :host and its related functional forms, which make it very explicit when you’re trying to match against markup provided by the page author.
2.2.3. light ツリーの中への選択法: :host
, :host()
, :host-context()
疑似クラス
:host
疑似クラスは、
shadow ツリーの文脈下では,[
当の shadow ツリーをホストしている shadow ホスト
]に合致するように評価される。
他の文脈下では,何にも合致しない。
The :host pseudo-class, when evaluated in the context of a shadow tree, matches the shadow tree’s shadow host. In any other context, it matches nothing.
関数形の疑似クラス
:host()
の構文は、
次で与えられる:
The :host() function pseudo-class has the syntax:
:host( <compound-selector> )
それは、 shadow ツリーの文脈下では,[ 当の shadow ツリーをホストしている shadow ホスト ]であって[ 通常の文脈下で,引数の選択子(複合選択子)にも合致するもの ]に合致するように評価される。 他の文脈下では,何にも合致しない。 When evaluated in the context of a shadow tree, it matches the shadow tree’s shadow host if the shadow host, in its normal context, matches the selector argument. In any other context, it matches nothing.
:host
の詳細度は、
疑似クラスのそれとする。
:host()
の詳細度は、
疑似クラスのそれに引数の詳細度を足したものになる。
The specificity of :host is that of a pseudo-class. The specificity of :host() is that of a pseudo-class, plus the specificity of its argument.
注記:
これは、
:is()
や :not()
の様な[
類似するが,引数の詳細度しかとらない疑似クラス
]の詳細度とは異なる。
そのわけは、
:host
が, “通常の” 疑似クラスの様に独力で【すなわち,引数なしでも】要素を選択するからである
— それは構文上の理由から引数に選択子をとるが( :host.foo
に合致するなら .foo
にも合致させる必要がある)、
他の点では,単に ある選択子が後続している :host
を利用することに一致する。
【 :host.foo
は :host
と .foo
の論理積を表すが、 .foo
単体では shadow ツリーの外にあるものに合致し得ない。】
Note: This is different from the specificity of similar pseudo-classes, like :is() or :not(), which only take the specificity of their argument. This is because :host is affirmatively selecting an element all by itself, like a "normal" pseudo-class; it takes a selector argument for syntactic reasons (we can’t say that :host.foo matches but .foo doesn’t), but is otherwise identical to just using :host followed by a selector.
例えば、 次の様な shadow ツリーを伴う部品があるとするとき: For example, say you had a component with a shadow tree like the following:
<x-foo class="foo"> <“shadow ツリー”> <div class="foo">...</div> </“shadow ツリー”> </x-foo>
shadow ツリーの中のスタイルシートにおいては: For a stylesheet within the shadow tree:
-
:host
は、x-foo
要素に合致する。 :host matches the <x-foo> element. -
x-foo
は、 何にも合致しない。 x-foo matches nothing. -
.foo
はdiv
要素のみに合致する。 .foo matches only the <div> element. -
.foo:host
は、 何にも合致しない —.foo
はx-foo
要素に合致しないので。 .foo:host matches nothing -
:host(.foo)
は、x-foo
要素に合致する — 引数の.foo
も合致するので。 :host(.foo) matches the <x-foo> element.
shadow ツリーの中の選択子からは、 普通は,shadow ツリーの外側にある要素は まったく見えない。 しかしながら、 ときには, shadow ツリーの外側にあるどこか — 同じ文書内の, より上位にある先祖 — を選択できると有用になることもある。 Ordinary, selectors within a shadow tree can’t see elements outside the shadow tree at all. Sometimes, however, it’s useful to select an ancestor that lies somewhere outside the shadow tree, above it in the document.
例えば,一群の部品からなるグループは、[ 各自がどう応答するかを知る,一握りの色テーマ ]を定義することもある — ページ作者が、[ それらの部品または, 文書内のより上位 ]に特定のクラスを追加して,ある特定のテーマを任意選択で選べるような。 For example, a group of components can define a handful of color themes they know how to respond to. Page authors could opt into a particular theme by adding a specific class to the components, or higher up in the document.
【 すなわち、 部品を内容に含ませている先祖にあてがわれたクラスに応じて、 利用する色テーマ (部品どうしや, その内部の構成子たちの色合いが調和するように設計された,色の集合) を切り替える。 】
関数形の疑似クラス
:host-context()
は、
shadow ツリーの外側に[
ある特定の選択子に合致する先祖
]は在るかどうかをテストする。
その構文は、
次で与えられる:
The :host-context() functional pseudo-class tests whether there is an ancestor, outside the shadow tree, which matches a particular selector. Its syntax is:
:host-context( <compound-selector> )
:host-context()
疑似クラスは、
shadow ツリーの文脈下では,[
当の shadow ツリーをホストしている shadow ホスト, または その shadow も含めた先祖
]のうち[
通常の文脈下で引数の選択子(複合選択子)に合致する
]ものに合致するように評価される。
他の文脈下では,何にも合致しない。
When evaluated in the context of a shadow tree, the :host-context() pseudo-class matches the shadow host, if the shadow host or one of its shadow-including ancestors matches the provided <compound-selector>. In any other context, it matches nothing.
:host-context()
の詳細度は、
疑似クラスのそれに引数の詳細度を足したものになる。
The specificity of :host-context() is that of a pseudo-class, plus the specificity of its argument.
注記: このことは、 当の選択子は,[ 文書の根に到達するか, 引数に合致する要素が見つかる ]まで[ shadow 境界を貫くように遡る ]ことを意味する。 Note: This means that the selector pierces through shadow boundaries on the way up, looking for elements that match its argument, until it reaches the document root.
2.2.4. slot にあてがわれた内容の選択法: ::slotted()
疑似要素
::slotted()
疑似要素は、[
平坦化された結果,slot にあてがわれた要素たち
]を表現する。
この疑似要素は:
The ::slotted() pseudo-element represents the elements assigned, after flattening, to a slot.\
- slot 上にのみ存在する。 【すなわち、当の slot が,この疑似要素の出自の要素になる。】 This pseudo-element only exists on slots.
- 当のツリー内の他の要素を指す別名であり、 それ自体はボックスを生成しない。 【すなわち,要素が裏にある疑似要素である。】 The ::slotted() pseudo-element is an alias for other elements in the tree, and does not generate any boxes itself.
-
その文法は、 次で与えられる: The grammar of the ::slotted() pseudo-element is:
::slotted( <compound-selector> )
-
∧↓ を満たす要素を表現する: The ::slotted() pseudo-element represents the elements that are:
-
平坦化された結果として,[
::slotted
の出自の要素である slot ]にあてがわれている。 assigned, after flattening, to the slot that is ::slotted’s originating element - 要素に対し選択子を照合したとき, 引数の <compound-selector> (複合選択子)に合致する。 matched by its <compound-selector> argument
-
平坦化された結果として,[
-
::slotted()
::before
の様に, ツリーに留まる疑似要素を後続させれる — それは、::slotted()
疑似要素により表現される要素を出自の要素とする適切な疑似要素を表現する。 The ::slotted() pseudo-element can be followed by a tree-abiding pseudo-element, like ::slotted()::before, representing the appropriate pseudo-element of the elements represented by the ::slotted() pseudo-element.
::slotted()
の詳細度は、
疑似要素のそれに引数の詳細度を足したものになる。
The specificity of ::slotted() is that of a pseudo-element, plus the specificity of its argument.
例えば、 次の様な[ 子たち, および shadow ツリー ]を伴う部品があるとする: For example, say you had a component with both children and a shadow tree, like the following:
<x-foo> <div id="one" slot="foo" class="foo">...</div> <div id="two" slot="foo">...</div> <div id="three" class="foo"> <div id="four" slot="foo">...</div> </div> <“shadow ツリー”> <div id="five">...</div> <div id="six">...</div> <slot name="foo"></slot> </“shadow ツリー”> </x-foo>
shadow ツリーの中のスタイルシートにおいては、
選択子 ::slotted(*)
は,[
#one
, #two
]のみを選択する
— それらは、
もっぱら slot
要素にあてがわれる要素なので。
それは、
slot
属性を有さない #three
は選択しない。
また、
#four
も選択しない
(slot にあてがわれるノードは、
shadow ホストの(直な)子に限られるので)。
For a stylesheet within the shadow tree, a selector like ::slotted(*) selects #one and #two only, as they’re the elements assigned to the sole slot element. It will not select #three (no slot attribute) nor #four (only direct children of a shadow host can be assigned to a slot).
一方で, ::slotted(.foo)
の様な選択子は、[
#one
, #two
]のうち .foo
に合致する前者のみを選択する。
A selector like ::slotted(.foo), on the other hand, will only select #one, as it matches .foo, but #two doesn’t.
注記:
::slotted(*)
の様な選択子は、
*::slotted(*)
と等価になる
— 先頭の *
は、
slot
要素の他にも多数の要素を選択するが、
slot になるのは slot
要素に限られるので,合致するのは ::slotted()
疑似要素に合致する要素に限られる。
Note: Note that a selector like ::slotted(*) is equivalent to *::slotted(*), where the * selects many more elements than just the slot element. However, since only the slot elements are slots, they’re the only elements with a ::slotted() pseudo-element as well.
注記:
slot にはテキストノードもあてがえるが、
それらは ::slotted()
では表現されないので,選択できない。
そのようなテキストノードをスタイルする仕方は、
slot をスタイルした上で,継承に依拠する他にない。
Note: ::slotted() can only represent the elements assigned to the slot. Slots can also be assigned text nodes, which can’t be selected by ::slotted(). The only way to style assigned text nodes is by styling the slot and relying on inheritance.
2.2.5. slot にあてがわれたノードの有無に対する照合法: :has-slotted
疑似クラス
:has-slotted
疑似クラスは、
次を満たす slot
要素に合致する
:次の結果は空でない
:slot 用に平坦化された slot 可能なものを見出す( 当の要素 )
The :has-slotted pseudo-class matches slot elements which have a non-empty list of flattened slotted nodes.
ある[
フォールバック内容†を伴う slot
]が :has-slotted
に合致したならば、[
当のフォールバック内容は表示されていない
]ものと結論できる。
When :has-slotted matches a slot with fallback content, we can conclude that the fallback content is not being displayed.
【†
すなわち、
上の “結果” が空になるとき,当の slot にあてがわれる内容
(当の slot
要素の内容)。
】
注記:
【上の “結果” が】空白のみからなる 1 個のテキストノードであっても,
:has-slotted
を適用させるものとして足る。
そのように設計されたのは、
この疑似クラスのふるまいを assignedNodes()
メソッドのふるまいと一貫させるためである。
この仕様の将来バージョンは、
この事例で合致することを除外する仕方を導入するものと期待される。
Note: Even a single whitespace text node is sufficient to make :has-slotted' apply. This is by design, so that the behavior of this pseudo-class is consistent with the behavior of the assignedNodes() method. A future version of this specification is expected to introduce a way to exclude this case from matching.
注記:
この仕様の将来バージョンは、
関数形の :has-slotted()
疑似クラスを導入することが期待される
— それは、
選択子引数を受容することにより,もっと木目細かな照合を許容する。
:has-slotted
は、
:has-slotted(*)
の別名にはならない
— 前者は[
上の “結果” がテキストノードのみであっても合致する
]が、
後者はそうでない。
Note: It is expected that a future version of this specification will introduce a functional :has-slotted() pseudo-class that allows more fine-grained matching by accepting a selector argument. :has-slotted is not an alias of :has-slotted(*), as the latter would not match slotted text nodes, but :has-slotted does.
2.3. shadow ツリーとカスケード
カスケード文脈 [CSS-CASCADE-4] を見よ。 See CSS Cascading 4 § 6.1 Cascade Sorting Order.
2.4. DOM から要素ツリーへの平坦化法
選択子は,ホスト言語が提示する DOM ツリーに対し演算するが、 CSS の他の部分が[ 標準な[ 親/子 ]関係性を介することでは到達不能な,別々なツリー ]に働くためには,単一化されたツリー構造が必要になる。 これは、 平坦化された要素ツリー ( flattened element tree ) — 略して,平坦ツリー( flat tree ) — と呼ばれ,次に従って構築される 【この “平坦化” は、要素の入れ子ではなく,ツリーの入れ子を平坦化することを表す。】 : While Selectors operates on the DOM tree as the host language presents it, with separate trees that are unreachable via the standard parent/child relationship, the rest of CSS needs a single unified tree structure to work with. This is called the flattened element tree (or flat tree), and is constructed as follows:
- 根 :← 文書の根要素 ↓
- 処理待ちノードリスト :← 新たなリスト — このリストは、 ( ノード, 親 ) が成すタプルとして与えられるアイテムたちで拡充されることになる。 Let pending nodes be a list of DOM nodes with associated parents,\
- 処理待ちノードリスト に ( 根, ε ) を付加する initially containing just the document’s root element with no associated parent.
- 平坦ツリー :← 根 を根とする, 根 のみからなる新たな平坦ツリー ↓
-
WHILE[ 処理待ちノードリスト は空でない ]: Repeatedly execute the following substeps until pending nodes is empty:
- アイテム :← 処理待ちノードリスト[ 0 ] ↓
- 処理待ちノードリスト から アイテム を除去する Pop the first element from pending nodes, and assign it to pending node.
- ノード :← アイテム の ノード ↓
- IF[ ノード ≠ 根 ] :ノード を[ アイテム の 親 の子 ]として 平坦ツリー の中へ挿入する Insert pending node into the flat tree as a child of its associated parent.\(If it has no associated parent, it’s the document root—just insert it into the flat tree as its root.)
-
IF[ ノード は shadow ホストである ]: Perform one of the following, whichever is the first that matches:pending node is a shadow host
- ノード がホストしている shadow ツリーの shadow 根の子群を成す 各 ( 子ノード ) に対し :処理待ちノードリスト に ( 子ノード, ノード ) を付加する Append the child nodes of the shadow root of the shadow tree it hosts to pending nodes, with pending node as their associated parent.
- CONTINUE
-
IF[ ノード は slot である ]:
- slot 可能リスト :← slot 用に slot 可能なものを見出す( ノード )
-
IF[ slot 可能リスト は空でない ]:
- slot 可能リスト を成す 各( slot 可能 ) に対し :処理待ちノードリスト に ( slot 可能, ノード ) を付加する
- CONTINUE
- ノード の(light ツリーにおける)子群を成す 各( 子 ) に対し :処理待ちノードリスト に ( 子, ノード ) を付加する Otherwise,Append the child nodes of pending node’s light tree to pending nodes, with pending node as their associated parent.
注記: 言い換えれば、 平坦ツリーは,トップレベルの DOM ツリーであるが:
- 各 shadow ホストは、[ その light ツリー内の子たち ]に代わって,[ shadow ツリー内の子たち ]で埋められる (更に,[ 当の shadow ツリーも shadow ホストを包含する ]ならば、 これを再帰的に続行する)。
- 各 slot は、[ それにあてがわれたノードたち ]で埋められる (更に,当の slot も[ より深い shadow ツリー内の slot ]にあてがわれるなら、 これを再帰的に続行する)。
これによる明白でない結果は、
slot にあてがわれた要素は、
その slot から【スタイルを】継承することである
— 要素の light ツリーにおける親や, その slot があてがわれている より深い slot でなく。
このことは、
【 slot にあてがわれた】テキストノードは、
その親の shadow ツリーによりスタイルされ,他からはどうやっても介入できないことを意味する。
そのようなテキストノードをターゲットする追加の疑似要素は,求まれるか?
— それらにも,要素のときと同様に slot にあてがわれた下でスタイルできるよう。
このことは、
light ツリー内のテキストノードに対しても,slot にあてがわれる前に,そのような疑似要素が働く必要があることを含意する。
なので、
これは,ただの ::slotted()
の変種にはなり得ない。
Luckily, this is a long-standing request!【何が Luckily?】
A non-obvious result of this is that elements assigned to a slot inherit from that slot, not their light-tree parent or any deeper slots their slot gets assigned to. This means that text nodes are styled by the shadow tree of their parent, with nobody else capable of intervening in any way. Do we want an additional pseudo-element for targeting those text nodes so they can be styled at all slot-assignment levels, like normal elements can be? This implies it needs to work for text nodes in the light tree before they’re assigned downwards, so this can’t just be a ::slotted() variant. Luckily, this is a long-standing request!
2.4.1. shadow ツリー内の slot とそれにあてがわれる要素
slot は、[
UA 出自内の規則を介して,その display
には contents
があてがわれていた
]かのように動作するものとする。
これは、
display
を介して上書きできるものとする
— 欲されるときには、
slot がボックスを生成できるよう。
Slots must act as if they were assigned display: contents via a rule in the UA origin. This must be possible to override via display, so they do generate boxes if desired.
【
[HTML] においては、
これは,UA スタイルシートの
slot{ display: contents }
規則として実装される。
】
注記: slot に要素をあてがうことによる明白でない結果は、 要素は,その slot から【スタイルを】継承することである。 [ light ツリーにおける要素の元の親 ]/[ その slot もまた 他の slot にあてがわれたとするときの,他の slot ]は、 継承には影響しない。 Note: A non-obvious result of assigning elements to slots is that they inherit from the slot they’re assigned to. Their original light tree parent, and any deeper slots that their slot gets assigned to, don’t affect inheritance.
2.5. 名前を定義する構成子と継承
shadow ツリーは、 カプセル化の境界になること — 独立な作者たちが、 互いの名前空間を不用意に汚すことなくコードを共有するのを許容すること — が意図される。 例えば要素 ID は、 一般に,文書の中で一意になることが意図されるが、 異なる shadow ツリー内であれば,複数回利用されても妥当になる。 Shadow trees are meant to be an encapsulation boundary, allowing independent authors to share code without accidentally polluting each other’s namespaces. For example, element IDs, which are generally meant to be unique within a document, can be validly used multiple times as long as each use is in a different shadow tree.
同様に,CSS における at-規則のうちいくつか
— @keyframes
や @font-face
など —
は、[
プロパティ/他の at-規則
]が[
後で,それを参照できる名前
]を定義する。
これらの名前は,ID の様に[
大域的に公開され,同じ文書の中で一意になる
]が、
この制約もまた,今や ID の様に[
所与の shadow ツリーの中で一意になる
]よう緩められる。
Similarly, several at-rules in CSS, such as @keyframes or @font-face, define a name that later at-rules or properties can refer to them by. Like IDs, these names are globally exposed and unique within a document; also like IDs, this restriction is now loosened to being unique within a given shadow tree.
しかしながら,プロパティ継承は、 あるツリーから別のツリーへ値を運ぶこともあるため,所与の名前から正しい定義への参照法は複雑化する。 これは,素朴に行われた場合、 作者を[ 驚かす/惑わす ]結果を生産し得る。 この節では、 “大域的” な名前を — カプセル化を尊重して,驚かす結果を与えない仕方で — [ 定義する/参照する ]ときに利用される概念を定義する。 However, property inheritance can carry values from one tree to another, which complicates referencing the correct definition of a given name. Done naively, this can produce surprising and confusing results for authors. This section defines a set of concepts to use in defining and referencing "global" names in a way that respects encapsulation and doesn’t give surprising results.
[
at-規則/プロパティ
]のうち,他の CSS 構成子から参照できる名前
(例:
@font-face
の font-family
に与える名前,
@keyframes
に与える名前)
を定義するものは、
それを
ツリー視野な名前
( tree-scoped name )
— その視野は あるツリーに絞られる名前 —
として定義しなければならない。
ツリー視野な名前は、
他が指定されない限り,ある特定のノードツリーの中で “大域的” になり、
当の[
at-規則/プロパティ
]を定義したスタイルシートをホストしている要素の根が結び付けられる。
If an at-rule or property defines a name that other CSS constructs can refer to it by, such as a @font-face font-family name or an @keyframes name, it must be defined as a tree-scoped name. Tree-scoped names are "global" within a particular node tree; unless otherwise specified, they’re associated with the root of the element hosting the stylesheet that the at-rule or property is defined in.
“大域的” な名前を参照する[
プロパティ/記述子
]
(例: font-family
, animation-name
)
は、
その値を
ツリー視野な参照
( tree-scoped reference )
— その視野は あるツリーに絞られる参照 —
として定義しなければならない。
ツリー視野な参照は、
指定された値とともに,暗黙的にノードツリーの根を捕捉する
— それは、
他が指定されない限り,当の[
プロパティ/記述子
]が定義されているスタイルシートをホストしている要素の根になる。
この[
根への参照
]は、
継承されてもツリー視野な参照に伴い続ける。
Properties or descriptors that reference a "global" name, such as the font-family or animation-name properties, must define their value as a tree-scoped reference. Tree-scoped references implicitly capture a node tree root along with their specified value: unless otherwise specified, the root of the element hosting the stylesheet that the property or descriptor is defined in. This root reference stays with the tree-scoped reference as it is inherited.
ツリー視野な参照 参照 を[ それが参照している CSS 構成子を見出すために参照解決する所 ]では、 まず,ツリー視野な名前のうち[ それに結び付けられた根が 参照 に結び付けられた根と同じになるもの ]に限り探索するものとする — 該当するツリー視野な名前は見出されなかった場合、 参照 に結び付けられた根は shadow 根であるならば,根のホストが属するノードツリー内でこの探索を繰り返すとする (言い換えれば、 ツリー視野な名前は,子孫 shadow ツリーの中へ — 子孫ツリー自身が同じ名前を定義していない限り — “継承される” )。 Whenever a tree-scoped reference is dereferenced to find the CSS construct it is referencing, first search only the tree-scoped names associated with the same root as the tree-scoped reference must be searched. If no relevant tree-scoped name is found, and the root is a shadow root, then repeat this search in the root’s host’s node tree. (In other words, tree-scoped names "inherit" into descendant shadow trees, so long as they don’t define the same name themselves.)
[ 大域的な名前を定義する すべての at-規則/ それらを参照する すべてのプロパティ ]は、 これらの概念を利用するよう修正する必要がある: TODO: Fix all the at-rules that define global names, and the properties that reference them, to use these concepts.
-
font-family
から参照される@font-face
@font-face, referenced by font-family -
font-family
から参照される@font-feature-values
@font-feature-values, referenced by font-family -
animation-name
から参照される@keyframes
@keyframes, referenced by animation-name -
list-style-type
から参照される@counter-style
@counter-style, referenced by list-style-type -
color()
関数 から参照される@color-profile
@color-profile, referenced by the color() function -
font-palette
から参照される@font-palette-values
@font-palette-values, referenced by font-palette - その他には? others?
例えば,次の文書において
(仮想のマークアップ[
<::shadow>
… </::shadow>
]は、
要素の shadow ツリーを指示する):
For example, given the following document (using the imaginary <::shadow></::shadow> markup to indicate an element’s shadow tree):
<p class=outer> ここでは、 light ツリーの "foo
" フォントが利用される。 Here's some text in the outer document's "foo" font. </p> <style> @font-face { font-family: foo; src: url(https://example.com/outer.woff); } body { font-family: foo; } my-component::part(text) { font-family: foo; } </style> <my-component> <::shadow> <p class=inner-default> これは、 light ツリーのfont-family
を継承している。 I'm inheriting the outer document's font-family. </p> <p class=inner-styled> ここでは、my-component
内の "foo
" フォントを利用するよう,明示的にスタイルされる。 And I'm explicitly styled to be in the component's "foo" font. </p> <p class=part-styled part=text> これは、 light ツリーにより明示的にスタイルされ, light ツリーから "foo
" フォントを取得する。 I'm explicitly styled by the outer document, and get the outer document's "foo" font. </p> <style> @font-face { font-family: foo; src: url(https://example.com/inner.woff); } .inner-styled { font-family: foo; } </style> </::shadow> </my-component>
.outer
要素は、
外縁な @font-face
を参照するので,
"outer.woff
" フォントリソースを利用する。
The .outer element references the outer @font-face, using the "outer.woff" file.
.inner-default
要素は、
.outer
と同じツリー視野な参照を利用しているので,
font-family
の値 foo
を light ツリーから継承する。
したがって、
それも "outer.woff
" フォントリソースを利用する。
The .inner-default element inherits the font-family: foo value from the outer document, using the same tree-scoped reference as .outer, and thus also uses the "outer.woff" font file.
他方, .inner-style
要素は、
shadow の内側にあるスタイルシートから font-family
の値 foo
を受け取る
— そのツリー視野な参照は shadow の @font-family
を参照するので,
"inner.woff
" フォントリソースを利用する。
The .inner-style element, on the other hand, receives a font-family: foo from the stylesheet inside the shadow, and thus its tree-scoped reference refers to the shadow’s @font-family, and it uses the "inner.woff" file.
.part-styled
要素も,自身のスタイルを light ツリーから受け取るが、
継承によらずに,直に設定されている。
したがって、
そのツリー視野な参照も light ツリーを参照するので,
"outer.woff
" フォントリソースを利用する。
The .part-styled element also receives its style from the outer document, tho by being directly set rather than by inheritance. Thus, its tree-scoped reference also refer’s to the outer document, and it uses the "outer.woff" file.
[ ツリー視野な名前, ツリー視野な参照 ]がどう継承されるかを精確に説明するため、 3 レベルのツリーからなる,もっと複階的な例を次に示す: Here is a more complex example, showing three levels of trees, and illustrating precisely how tree-scoped names and tree-scoped references inherit.
<style> @font-face { font-family: foo; src: url(https://example.com/outer.woff); } body { font-family: foo; } </style> <child-component> <::shadow> <style> @font-face { font-family: foo; src: url(https://example.com/inner.woff); } </style> <grandchild-component> <::shadow> <p class=inner-default> これは、 light ツリーの "foo
" フォント を継承している。 I’m inheriting the outer document’s "foo" font. </p> <p class=inner-search> 局所的な "foo
" フォントは見出せなかったので、 ツリーをさらに遡るよう探索した結果,shadow の "foo
" フォントが見出される。 And I can’t find a local "foo" font, so I’m searching further up the tree, and find the shadow’s "foo" font. </p> <style> .inner-search { font-family: foo; } </style> </::shadow> </grandchild-component> </::shadow> </child-component>
ここでの .inner-default
は、
前の例と同じく,light ツリー内に宣言された font-family
を継承している
— その結果[
light ツリーの @font-face
を参照する
]ようになるので,
"outer.woff
" フォントリソースで描画される。
Here, just as in the previous example, .inner-default is inheriting the font-family: foo declared in the outer document, and so it ends up referencing the outer document’s @font-face, and is rendered with the "outer.woff" file.
他方, .inner-search
は、[
自身のスタイルを grandchild-component
の shadow ツリー内のスタイルシートから受け取る
]ので,[
そのツリー内の foo
フォントを定義している @font-face
]を見出そうと試みる。
そのような @font-face
は無いので、[
shadow ツリーを遡って,
child-component
内に適切な @font-face
を見出す
]ことになり,
"inner.woff
" フォントリソースで描画される。
On the other hand, .inner-search receives its style from a stylesheet in <grandchild-component>’s shadow tree, so it attempts to find a @font-face defining a foo font in that tree. There is no such @font-face, so it starts walking up the shadow trees, finding an appropriate @font-face in <child-component>, so it’s rendered with the "inner.woff" file.
2.5.1. ツリー視野な参照が直列化されるとき
ツリー視野な参照が直列化される場合、 その値しか直列化されず,結び付けられた根は失われる。 If a tree-scoped reference is serialized, it serializes only its value; the associated root is lost.
このことは、
要素.style.foo = getComputedStyle(要素).foo;
は
— shadow ツリーが存在しなければ、
概して何もしないのと違って —
何もしないとは限らないことを含意する。
This implies that `el.style.foo = getComputedStyle(el).foo;` is not necessarily a no-op, like it typically was before shadow trees existed.
例えば,次の文書において
(仮想のマークアップ[
<::shadow>
… </::shadow>
]は、
要素の shadow ツリーを指示する):
For example, given the following document (using the imaginary <::shadow></::shadow> markup to indicate an element’s shadow tree):
<p class=outer> ここでは、 light ツリーの "foo
" フォントが利用される。 Here’s some text in the outer document’s "foo" font. </p> <style> @font-face { font-family: foo; src: url(foo.woff); } body { font-family: foo; } </style> <my-component> <::shadow> <p class=inner-default> これは、 light ツリーのfont-family
を継承している。 I'm inheriting the outer document's font-family. </p> <p class=inner-styled> ここでは、my-component
内の "foo
" フォントを利用するよう,明示的にスタイルされる。 And I'm explicitly styled to be in the component's "foo" font. </p> <style> @font-face { font-family: foo; src: url(https://example.com/foo.woff); } .inner-styled { font-family: foo; } </style> <script> const innerDefault = document.querySelector('.inner-default'); const innerStyled = document.querySelector('.inner-styled'); const defaultFont = getComputedStyle(innerDefault).fontFamily; const styledFont = getComputedStyle(innerStyled).fontFamily; console.log(defaultFont == styledFont); // true! </script> </::shadow> </my-component>
.outer
要素は、
light ツリーの "foo
" @font-face
でスタイルされる。
.inner-default
要素 innerDefault は、
light ツリーから font-family
を継承するので,
light ツリーを参照しているツリー視野な参照も継承する
— その結果, .outer
要素と同じフォントが利用される。
The .outer element is styled with the outer document’s "foo" @font-face. The .inner-default element inherits font-family from the outer document, meaning it inherits a tree-scoped reference referencing that outer document, and so it’s in the same font as .outer.
その一方, .inner-styled
要素 innerStyled は、
当の shadow 根の内側から明示的にスタイルされるので、
それを根とする shadow ツリーを参照しているツリー視野な参照を新規に受け取る
— その結果、
この shadow の自前の "foo
" @font-face
でスタイルされる。
Meanwhile, .inner-styled is explicitly styled from inside the shadow root, so it receives a fresh tree-scoped reference referencing its shadow tree, and it is instead styled the shadow’s own "foo" @font-face.
にも関わらず,my-component
の内側で走っているスクリプトからは、
innerDefault, innerStyled
の font-family
用の値は同じに見える
— ツリー視野な参照の[
根への参照
]を成す部分は、
直列化により保全されないので。
仮に,
innerDefault.style.fontFamily = defaultFont;
のように設定した場合、
innerDefault 用のフォントは,いきなり
innerStyled 用のフォントに切り替わる
— [
shadow ツリー内に住まう,
innerDefault の CSS スタイル属性のスタイルシート
]内で font-family
プロパティが設定されるので。
Despite that, the script running inside the component sees the two elements as having the same value for font-family, because the root-reference part of a tree-scoped reference is not preserved by serialization. If it were to set innerDefault.style.fontFamily = defaultFont; (thus setting the font-family property of the element’s attribute stylesheet, which lives in the shadow tree), the .inner-default element would suddenly switch to the same font as .inner-styled!
注記: [css-typed-om-1] は、[ 値を具象化する規則において,ツリー視野な参照の[ 根への参照 ]も反映する ]ことにより,次を作者に許容するものと期待される :当の参照は,どのノードツリーから その値を得るかについて、伝えること/ 2 つのノードツリー間で,値の意味が変化しないように値をトランスポートすること Note: The [css-typed-om-1] is expected to reflect the root reference of a tree-scoped reference in its reification rules for values, allowing authors to tell what node tree the reference is taking its values from, and allowing values to be transported across node trees without changing their meaning.
変更点
2014年 4月 3日 作業草案 からの有意な変更点は: The following significant changes were made since the 3 April 2014 Working Draft.
- ツリー視野な名前は、 子孫 shadow ツリーの中へ継承されるものと定義した。 Defined that tree-scoped names inherit into descendant shadow trees
-
::content
を::slotted
に改称した。 Renamed ::content to ::slotted. - 平坦化された要素ツリーを定義した。 Define the flattened tree.
- § shadow DOM を,現在の [DOM] に基づくように編成し直した。 Generally reorg and rebase the Shadow DOM section on top of current DOM.
-
@scope
,::region
に関係するものを次のレベルの草案まで先送りした。 Punt @scope and related things, and ::region and related things, to the next level of the draft. -
次に挙げるものの詳細度を定義した
:
:host
,:host()
,:host-context()
,::slotted()
Define the specificity of :host, :host(), :host-context(), and ::slotted() -
結合子
>>>
(過去には/deep/
と呼ばれていた)を除去した。 Remove the >>> (previously called /deep/) combinator. -
ツリーに留まる疑似要素は、
::slotted()
の後にも許容されるものと定義した。 Define that tree-abiding pseudos are allowed after ::slotted(). - すべての[ 疑似要素/疑似クラス ]に <compound-selector> を許容した。 Allow <compound-selector-list> in all the pseudos.
- 所与の要素用の既定の要素スタイルを成すスタイルシートを作成する仕方を定義した。 Define a way to create a stylesheet of default element styles for a given element.
- 無特能な要素には、 何も合致しないようにした。 Make featureless elements match nothing.
- “shadow ツリーの文脈下” を定義した。 Define in the context of a shadow tree.
プライバシーの考慮点
この仕様は,shadow DOM および,ある[ shadow を貫く能力 ]を導入するが、 それがプライバシーの課題を導入することはない — 現在の shadow DOM は、 プライバシー境界にならないよう,意図的に指定されているので (また、 UA の[ shadow DOM を利用する,かつプライバシー境界がある ]各部は、 暗黙的に,未だ指定されていない保護に依拠している — それは、 それらをこの仕様にて定義されるものから保護する)。 This specification introduces Shadow DOM and some shadow-piercing capabilities, but this does not introduce any privacy issues—shadow DOM, as currently specified, is intentionally not a privacy boundary (and the parts of the UA that use shadow DOM and do have a privacy boundary implicitly rely on protections not yet specified, which protect them from the things defined in this specification).
【 この文脈における “プライバシー境界( privacy boundary )である” とは、 何を意味する? その背景にある原則は何か? 】
セキュリティの考慮点
【“プライバシー” を “セキュリティ” に読み替える下で, § プライバシーの考慮点と同じ(なので、和訳は省略する)。】 This specification introduces Shadow DOM and some shadow-piercing capabilities, but this does not introduce any security issues—shadow DOM, as currently specified, is intentionally not a security boundary (and the parts of the UA that use shadow DOM and do have a security boundary implicitly rely on protections not yet specified, which protect them from the things defined in this specification).