Skip to content

Commit 43c34fd

Browse files
committed
[css-scoping-2] Initial draft of @scope, :in(), and scope proximity
1 parent 612ebb4 commit 43c34fd

File tree

1 file changed

+191
-13
lines changed

1 file changed

+191
-13
lines changed

css-scoping-2/Overview.bs

Lines changed: 191 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,123 @@ Shadow Encapsulation</h2>
8181
██████ ██████ ███████ ██ ████ ██ ██ ██████
8282
-->
8383

84-
<h2 id='scope'>
84+
<h2 id='scoped-styles'>
8585
Scoped Styles</h2>
8686

87-
Issue: Introduce scoped styles
87+
A <dfn>scope</dfn> is a subtree or fragment of a document,
88+
which can be used by selectors for more targeted matching.
89+
[=Scopes=] are described in CSS through a combination of two selector lists:
90+
91+
* The <dfn><<scope-start>></dfn> is a <<forgiving-selector-list>>.
92+
Each element matched by <<scope-start>> is a [=scoping element=],
93+
creating a scope with itself as the [=scoping root=].
94+
* The <dfn><<scope-end>></dfn> is a <<forgiving-selector-list>>.
95+
Each element matched by <<scope-end>> is a [=scope boundary=].
96+
<dfn>Scope boundary</dfn> elements provide lower bounds to a scope,
97+
so that [=scoped selectors=] are not able to match more deeply nested elements.
98+
99+
Each resulting [=scope=] includes a [=scoping root=] and all it's descendants,
100+
up to and including any [=scope boundary=] elements,
101+
but not the descendants of those boundaries.
102+
103+
In contrast to <a href="#shadow-dom">Shadow Encapsulation</a>,
104+
which describes a persistent one-to-one relationship in the DOM
105+
between a [=shadow host=] and it's nested [=shadow tree=],
106+
multiple overlapping [=scopes=] can be defined in relation to the same elements.
107+
108+
<div class=example>
109+
For example,
110+
An author might have wide-reaching color-scheme scopes,
111+
which overlap more narrowly defined design patterns
112+
such as a media object:
113+
114+
<pre class=lang-css>
115+
@scope (.light-scheme) {
116+
a { color: darkmagenta; }
117+
}
118+
119+
@scope (.dark-scheme) {
120+
a { color: plum; }
121+
}
122+
123+
@scope (.media-object) {
124+
.media-image { border-radius: 50%; }
125+
.media-content { padding: 1em; }
126+
}
127+
</pre>
128+
</pre>
129+
130+
</div>
131+
132+
<div class=example>
133+
By providing [=lower boundaries=],
134+
an author can limit matching more deeply nested descendants.
135+
For example:
136+
137+
<pre class=lang-css>
138+
@scope (.media-object) to (.content) {
139+
img { border-radius: 50%; }
140+
141+
/* it is also possible to style the lower boundary itself */
142+
.content { padding: 1em; }
143+
}
144+
</pre>
145+
146+
The ''img'' selector will only match image tags that are inside a ''.media-object'',
147+
without any intervening ''.content'' matches between it and the [=scoping root=].
148+
</div>
149+
150+
<!--
151+
██ ████ ██ ██
152+
████ ██ ███ ██
153+
██ ██ ████ ██
154+
██ ██ ██ ██
155+
██ ██ ██ ████
156+
████ ██ ██ ███
157+
██ ████ ██ ██
158+
-->
159+
160+
<h3 id='in-scope-selector'>
161+
The in-scope pseudo-class '':in()''</h3>
162+
163+
The in-scope pseudo-class, <dfn>:in()</dfn>,
164+
is a functional pseudo-class with the following syntax:
165+
166+
<pre class='prod'>
167+
:in(<<scope-start>> [/ <<scope-end>>]?)
168+
</pre>
169+
170+
If, after parsing, <<scope-start>> is an empty list,
171+
the pseudo-class is valid but matches nothing, and defines no scopes.
172+
Otherwise, the pseudo-class matches any element that is in a [=scope=]
173+
described by the given <<scope-start>> and <<scope-end>> selectors.
174+
175+
Note: This does not effect the [=:scope elements=] for the selector.
176+
177+
The specificity of the '':in()'' pseudo-class
178+
is replaced by the specificity of
179+
the most specific [=complex selector=] in its <<scope-end>> argument.
180+
181+
<div class=example>
182+
The purpose of the in-scope pseudo-class
183+
is to allow adding [=scope boundaries=] to a selector:
184+
185+
<pre class=lang-css>
186+
.title:in(.post / .comments) { font-size: 2em; }
187+
</pre>
188+
189+
Without any such lower boundaries,
190+
the ''in()'' pseudo-class is similar to other descendant selectors.
191+
These three selectors will all select the same elements,
192+
with the same specificity:
193+
194+
<pre class=lang-css>
195+
.child:in(.ancestor) { color: darkmagenta; }
196+
.child:is(.ancestor *) { color: darkmagenta; }
197+
.ancestor .child { color: darkmagenta; }
198+
</pre>
199+
</div>
200+
88201

89202
<!--
90203
███████ ██████ ██████ ███████ ████████ ████████
@@ -99,25 +212,86 @@ Scoped Styles</h2>
99212
<h3 id='scope-atrule'>
100213
Scoping Styles in CSS: the ''@scope'' rule</h3>
101214

102-
The <dfn>@scope</dfn> at-rule allows authors to create scoped style rules using CSS syntax.
215+
The <dfn at-rule id="at-ruledef-layer">@scope</dfn> [=block at-rule=]
216+
allows authors to create scoped stylesheets in CSS,
217+
with the addition of [=scope proximity=] weighting in the cascade.
103218
The syntax of the ''@scope'' rule is:
104219

105220
<pre class='prod'>
106-
@scope (<<selector-list>>) [to (<<selector-list>>)]? {
221+
@scope (<<scope-start>>) [to (<<scope-end>>)]? {
107222
<<stylesheet>>
108223
}
109224
</pre>
110225

111-
Issue: Define the ''@scope'' rule
112-
Issue: Define scope proximity in the cascade (cross-reference css-cascade)
226+
The ''@scope'' rule has three primary effects on the style rules in <<stylesheet>>.
227+
For each [=scope=] that is described by the given <<scope-start>> and <<scope-end>>:
113228

114-
<h3 id='in-scope-selector'>
115-
Selecting inside a scope: the '':in-scope'' pseudo-class</h3>
229+
* Selectors are given the added specificity of
230+
the most specific [=complex selector=] in the <<scope-start>> argument.
231+
This is designed to match the behavior of the ''in()'' and '':is()'' selectors.
232+
* [=scoped selectors|Selectors are scoped=] to the [=scope=] in question,
233+
with the [=:scope element=] being the [=scoping root=].
234+
* The cascade prioritizes rules with a [=scope proximity|more proximate=] [=scoping root=],
235+
regardless of source order.
236+
237+
<div class=example>
238+
When scoped declarations overlap—
239+
applying to the same elements
240+
with the same cascade origin, importance, and specificity—
241+
then one with closer [=scope proximity=] takes precedence.
242+
Using our
116243

117-
The <dfn>:in-scope</dfn> pseudo-class allows authors to
118-
select elements that are within a given scope.
244+
<pre class=lang-css>
245+
@scope (.light-scheme) {
246+
a { color: darkmagenta; }
247+
}
248+
249+
@scope (.dark-scheme) {
250+
a { color: plum; }
251+
}
252+
</pre>
253+
254+
If ''light-scheme'' and ''dark-scheme'' classes are nested,
255+
whichever is closer to a given link in the DOM tree
256+
will take precedence for styling that link,
257+
regardless of their order in the source:
258+
259+
<pre class=lang-html>
260+
&lt;section class="light-scheme">
261+
&lt;a href="#">
262+
light scope:
263+
darkmagenta link color
264+
&lt;/a>
265+
&lt;aside class="dark-scheme">
266+
&lt;a href="#">
267+
both scopes, but dark-scheme is a closer ancestor:
268+
plum link color
269+
&lt;/a>
270+
&lt;/aside>
271+
&lt;/section>
272+
</pre>
273+
</div>
274+
275+
''@scope'' rules can be nested.
276+
In this case, just as with the nested style rules,
277+
the selectors of the inner ''@scope'' are [=scoped selectors|scoped by=]
278+
the selectors of the outer one.
279+
280+
<h4 id='scope-cascade'>
281+
Scope Proximity in the Cascade</h3>
282+
283+
Issue: This likely belongs in the css-cascade specification.
284+
285+
<dfn>Scope proximity</dfn> is considered in the cascade sort order
286+
after specificity, and before order of appearance.
287+
288+
If the [=:scope elements=] of two declarations
289+
have an ancestor/descendant relationship,
290+
then the declaration whose [=:scope element=] is the descendant wins.
291+
292+
Note: When the [=:scope element=] is not otherwise defined for a declaration,
293+
it is the document root element.
119294

120-
Issue: Define an '':in-scope'' selector (cross-reference css-selectors)
121295

122296
<h2 id="changes">
123297
Changes</h2>
@@ -128,8 +302,12 @@ Additions Since Level 1</h3>
128302
The following features have been added since
129303
<a href="https://www.w3.org/TR/css-scoping-1/">Level 1</a>:
130304

131-
* The ''@scope'' rule
132-
* The '':in-scope()'' pseudo-class
305+
* The definition of a [=scope=],
306+
as described by a combination of <<scope-start>> and <<scope-end>> selectors.
307+
* The in-scope ('':in()'') pseudo-class for selecting with lower-boundaries
308+
* The ''@scope'' rule for creating scoped stylesheets
309+
* The definition of [=scope proximity=] in the cascade
310+
133311

134312
Privacy and Security Considerations {#priv-sec}
135313
===============================================

0 commit comments

Comments
 (0)