- From: Rich Harris via GitHub <sysbot+gh@w3.org>
- Date: Fri, 03 Sep 2021 15:21:13 +0000
- To: public-css-archive@w3.org
Rich-Harris has just created a new issue for https://github.com/w3c/csswg-drafts:
== [css-scoping] Inclusive vs exclusive lower boundary ==
https://drafts.csswg.org/css-scoping-2/ describes the possible use of CSS Scoping by component frameworks, with the following example:
```css
@scope ([data-scope='main-component']) to ([data-scope]) {...}
```
Since the lower boundary is inclusive, this matches the behaviour of the scoped styles in Vue Single-File Components: CSS declared in an SFC's `<style>` element apply to all elements of the current component, _plus_ the root element of child components.
But not all userland scoping systems work this way. Svelte has stricter encapsulation: by design, styles declared in one component can't affect a child component at all unless you opt-in to that behaviour with the `:global(...)` modifier ([demo](https://svelte.dev/repl/98d22b1bbf63462199a0215b3a905834?version=3.42.4)):
```html
<div>
<p>red on yellow</p>
<Widget/>
</div>
<style>
/* this will affect any <p> elements inside <Widget/> or its children
in addition to this component's elements */
div :global(p) {
text-decoration: underline;
}
/* these styles only affect the <div> and the <p> above, regardless of
whether the selectors match top-level elements in <Widget/> */
div {
background-color: yellow;
}
p {
color: red;
}
</style>
```
Svelte compiles this to the following CSS:
```css
div.svelte-185puzw p {
text-decoration: underline;
}
div.svelte-185puzw {
background-color: yellow;
}
p.svelte-185puzw {
color: red;
}
```
The above suggested approach would look like this...
```css
@scope ([data-scope='main-component']) to ([data-scope]) {
div p {
text-decoration: underline;
}
div {
background-color: yellow;
}
p {
color: red;
}
}
```
...which would incorrectly apply `color: red` to `<p data-scope="sub-component">`.
We on the Svelte team would love to be able to use CSS Scoping one day, but we think it's important that a component's styles don't leak into its children unless the author explicitly opts in. If the lower boundary is inclusive, then as far as I can see we would have to do something like this...
```css
@scope ([data-scope='main-component']) to (:not([data-scope='main-component'])) {...}
```
...and also apply the `data-scope="main-component"` attribute to every element. It's not clear that this would be an improvement on the current situation.
Is there a way we might only apply styles _until_ the lower boundary is reached? For example:
```css
@scope ([data-scope='main-component']) until ([data-scope]) {...}
```
```css
@scope ([data-scope='main-component']) to ([data-scope]) exclusive {...}
```
More controversially, perhaps the lower boundary should always be exclusive? It's worth noting that you can express the current semantics with an exclusive lower boundary...
```css
@scope ([data-scope='main-component']) to ([data-scope]:not(:scope) > *) {...}
```
...but the reverse isn't true, which to my mind is a strong argument in favour — it gives all authors more expressive power.
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6577 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Friday, 3 September 2021 15:21:15 UTC