https://drafts.csswg.org/css-scoping/#scoping-markup names the scoped
attribute on HTML’s <style>
element as example for scoping markup and references the WHATWG HTML spec, but the attribute has been removed from HTML in both WHATWG’s and W3C’s version.
https://github.com/whatwg/html/issues/552
https://github.com/w3c/html/issues/231
On a side note, is there hope that the very useful @scope
CSS rule will be implemented by browsers or is scoping completely dead?
It's likely to be dead; I suspect that we should remove it from the Scoping draft. It looks like, at least for now, browsers are settling on shadow DOM as the sole scoping mechanism. (While being somewhat more complex to use, it _is_ much more powerful and feature-ful; <style scoped>
is basically equivalent to just putting an ID on the container and using that in every rule.)
Thanks for the information, though it is sad to hear.
Shadow DOM may be more powerful, but requires JavaScript, which makes it less reliable or unusable in some contexts. Shadow DOM encapsulates code in two directions, i.e. styles in the shadow tree don’t affect outside markup and outside styles don’t affect shadow markup.
@scope
would be different: It is about nesting. It would prevent inside styles from affecting outside markup, but allow outside styles to affect scoped markup. I understand that there are ways to pierce through shadow DOM’s shadow boundary from outside, but that has to be made explicit while it would automatically work for @scope
.
I understand that @scope {…}
would basically be equivalent to putting an ID on a container and using that in every rule, but sometimes we only have limited control over part of the rules and it would be very helpful to be able to encapsulate them against influencing anything outside a container easily. In my case, the alternative is to write/use a whole server-side CSS parser in order to be able to inject IDs at all the right and no wrong places automatically.
Compared to using a container ID in every rule, @scope
would reduce redundancy (→ less typing, less bandwidth, less work/errors when changing code) which all users could benefit from, even if they have total control over their styles.
Nesting is a headline feature of CSS pre-processors like Less [1] and Sass [2] and CSS-Crush [3]. I think that shows that nesting capabilities are a desired and useful feature which @scope
would provide.
[1] http://lesscss.org/features/#features-overview-feature-nested-rules
[2] http://sass-lang.com/guide#topic-3
[3] http://the-echoplex.net/csscrush/#core--nesting
CSS Nesting (that preprocessors do) has nothing to do with @scope
.
I recognize the benefits of scoping; they're minor but real. But browsers have not considered them worthwhile in the form of <style scoped>
, and changing the syntax to @scope
isn't going to change their minds, so removing it from the spec as a dead feature is the most accurate thing to do.
Yes, I fully agree that removing things from the spec that aren’t going to be implemented is the right thing to do. I didn’t mean to suggest anything else.
I have difficulties to understand why @scope
has nothing to do with nesting as done by CSS pre-proccessors though. To me all these have the same effect:
Less:
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
}
}
Scoped CSS:
#header {
color:black;
}
@scope #header {
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
}
}
CSS:
#header {
color: black;
}
#header .navigation {
font-size: 12px;
}
#header .logo {
width: 300px;
}
Now that you’ve said it, I have found the css-nesting draft which does offer some useful features. Using it, the same code as above would look like this, if I’m not mistaken:
Nested CSS:
#header {
color: black;
& .navigation {
font-size: 12px;
}
& .logo {
width: 300px;
}
}
It looks quite similar to the Less code, maybe even more so than the scoped code, but due to the &
in every rule, nested CSS can’t do what both Less nesting and @scope
achieve: Take some CSS code, say
h2 {color: red}
p {color: green}
and encapsulate the whole code without modifications by nesting/scoping it with a container element’s ID.
Less:
#container {
h2 {color: red}
p {color: green}
}
Scoped CSS:
@scope #container {
h2 {color: red}
p {color: green}
}
So, in this case, I’d say that the pre-processor’s nesting has more to do with css-scoping than with css-nesting. I may be wrong though.
I'm sad to see this discussion. I've been excited by this spec, and it does seem to have progressed since I last checked about a year ago (no more dependence on the HTML attribute, for one).
I disagree that @scope is akin to just adding an id. Because of the way scope works in the cascade, nested scopes can do so much more than just ids. With normal id selectors, you would have to write every possible permutation to make them target correctly when nested, whereas styles from the innermost scope will inherently apply over the outer scope.
This would be hugely valuable in highly-modular webapps. It seems to me this is the most direct answer to Christopher Chedeaux and all the CSS-in-JS discussion.
To really drive home the point, consider three selectors inside of three scopes:
@scope #one {
.foo {}
.bar {}
.baz {}
}
@scope #two {
.foo {}
.bar {}
.baz {}
}
@scope #three {
.foo {}
.bar {}
.baz {}
}
To get equivalent cascading behavior out of IDs, you need to take every permutation of every scope's id, and add that to every selector in that scope. Here is the equivalent of just scope #one
:
#one .foo,
#two #one .foo,
#three #one .foo,
#two #three #one .foo,
#three #two #one .foo {}
#one .bar,
#two #one .bar,
#three #one .bar,
#two #three #one .bar,
#three #two #one .bar {}
#one .baz,
#two #one .baz,
#three #one .baz,
#two #three #one .baz,
#three #two #one .baz {}
Then repeat ALL of that again for each of the other two scopes. Every time you add a selector to a scope, or add a new scope to the stylesheet, you exponentially increase the number of selectors you need everywhere.
@scope
takes all of this complexity away.
Yes, I understand the benefits of scoped styles over just using an ID. But that doesn't change the calculus; browsers didn't end up accepting scoped styles in the form of <style scoped>
, so there's no reason to believe they'll accept them in the form of @scope
.
It's likely to be dead; I suspect that we should remove it from the Scoping draft. It looks like, at least for now, browsers are settling on shadow DOM as the sole scoping mechanism. (While being somewhat more complex to use, it is much more powerful and feature-ful;
<style scoped>
is basically equivalent to just putting an ID on the container and using that in every rule.)
This is really going past the demand. People are using Wordpress and non-wellformed-non-valid div-soup day to day. ShadowDOM is really great but a solution that works for regular DOM/HTML without a preprocessor and not only ShadowDOM is the way to go. ReactJS' and Elms adoption is also picking up. Unless you want another dead 'standard' as going for only ShadowDOM won't be adopted by masses.
This seems to be related, also: https://github.com/css-modules/css-modules
If scope is being removed, is there another way to include styles as part of your module(s) that is nested in the body tag without breaking w3c standards?
@unilobo
Yes, the W3C HTML version allows style in body.
https://w3c.github.io/html/document-metadata.html#the-style-element
ok, just when validating I get the following error:
Error: Element style not allowed as child of element div in this context. (Suppressing further errors from this subtree.)
>↩</div>↩↩<style>↩↩@med
But as you say the latest spec states that it can be used In the body, where flow content is expected.
i.e. most html tags
I think you could file a bug at https://github.com/validator/validator/issues . Not sure if they are going to fix this as long as WHATWG's version of HTML forbids style in body. See the related issue there: https://github.com/whatwg/html/issues/1605
@tabatkins I had some thoughts about this here:
https://github.com/w3c/csswg-drafts/issues/3547
My only goal is to export a <style>
tag that I can guarantee will not conflict with global styles in the wild, and it is admittedly frustrating that this was in the spec for years and got removed.
I guess it is possible to accomplish this with flat HTML, with large amounts of data redundancy; namely, generating a sufficiently long hash to put in the root element's id
field, and prefixing all styles with #id [your-style-here]
.
Most helpful comment
Thanks for the information, though it is sad to hear.
Shadow DOM may be more powerful, but requires JavaScript, which makes it less reliable or unusable in some contexts. Shadow DOM encapsulates code in two directions, i.e. styles in the shadow tree don’t affect outside markup and outside styles don’t affect shadow markup.
@scope
would be different: It is about nesting. It would prevent inside styles from affecting outside markup, but allow outside styles to affect scoped markup. I understand that there are ways to pierce through shadow DOM’s shadow boundary from outside, but that has to be made explicit while it would automatically work for@scope
.I understand that
@scope {…}
would basically be equivalent to putting an ID on a container and using that in every rule, but sometimes we only have limited control over part of the rules and it would be very helpful to be able to encapsulate them against influencing anything outside a container easily. In my case, the alternative is to write/use a whole server-side CSS parser in order to be able to inject IDs at all the right and no wrong places automatically.Compared to using a container ID in every rule,
@scope
would reduce redundancy (→ less typing, less bandwidth, less work/errors when changing code) which all users could benefit from, even if they have total control over their styles.Nesting is a headline feature of CSS pre-processors like Less [1] and Sass [2] and CSS-Crush [3]. I think that shows that nesting capabilities are a desired and useful feature which
@scope
would provide.[1] http://lesscss.org/features/#features-overview-feature-nested-rules
[2] http://sass-lang.com/guide#topic-3
[3] http://the-echoplex.net/csscrush/#core--nesting