You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If I understand the highlight inheritance model correctly, such global custom properties would not be available on ::selection (etc), unless you modify the custom-property-defining rule to something like :root, :root::selection {}. In principle what the author would be doing is creating two separate mega-blobs of custom properties. This may or may not be easy to optimize depending on how the usage patterns will actually end up.
Authors can use @property w/ initial value to address it. Is that enough, or we do something else about this?
Same context as the previous issue (#6774). Frontend frameworks often define a whole bunch of custom properties for things like colour palettes, on the root originating element, which used to be available to highlights “for free”. But now they won’t be, and authors will need to define those properties on both the originating element and each highlight pseudo.
We've discussed using variable values in other contexts that don't inherit from root as well (like in @font-palette, for example).
Having an author-defined env() might work, but would require an author to duplicate values across properties and env(), or else decide for each whether they want to express it as a var or an env().
The idea that's been presented a few times is to special-case properties defined on the root, and make them available more globally, so any context that's not an element with :root as an ancestor can use var() to obtain the root values of the custom property. Would this be reasonable impl-wise?
Having an author-defined env() might work, but would require an author to duplicate values across properties and env(), or else decide for each whether they want to express it as a var or an env().
Yeah, I see how that would be annoying.
OK, then maybe we can specify that var() in non-element contexts use the initial value of custom properties, and then provide a new way of specifying those initial values (if @property is too verbose).
Would [root special case] be reasonable impl-wise?
If we're going to generalize that, I suspect that creates way more complexity than it's worth. We'd be smuggling in the full weight of "computed-value-time", and we'd be unable to interpret any at-rules sooner than that, which is probably not a good thing. For example, the custom properties on :root may be animated, or they may depend on the computed font metrics of the selected font (e.g. with --x:10ch + @property with syntax:"<length>". Fun times if var(--x) is then used in @font-face somehow).
Ah yeah that's true, we don't want animation and whatnot to come in. Initial value seems fine to me, and we can just lean on @property unless/until we decide it's too annoying.
In a later comment in #6099, I suggested something that perhaps could solve this use case, although I did not consider it at the time:
@prefix ns {
/* global final namespaced custom properties */--global: val;
}
:root {
--miss:var(--global); /* no value */--tree:var(-ns-global); /* value: val */
}
::selection {
--fail:var(--tree); /* no value */--miss:var(--global); /* no value */--okay:var(-ns-global); /* value: val */
}
The CSS Working Group just discussed custom properties on :root.
The full IRC log of that discussion
<emilio> topic: custom properties on :root
<emilio> github: https://github.com//issues/6641
<emilio> delan: there's a lot of content out there where a bunch of custom properties are specified on the :root
<emilio> ... historically that's been fine for highlight pseudos because they inherited from the element
<emilio> ... as spec'd now each highlight pseudo has a separate inheritance tree so it'll break that pattern
<emilio> ... so there's a compat issue in that but I don't think that's a huge issue because we've determined that some breakage is acceptable for these highlight pseudo
<emilio> ... but there's two complications for this, one is that authors at least they'd have to switch their stylesheets to `:root, :root::selection, ...` etc
<TabAtkins> :root, :root::selection, :root::highlight, ... { /* set up all the custom props here */ }
<emilio> ... it's also a bit of a perf issue because we might end up with a bunch of property blobs
<emilio> ... there's another option which is using `@property` with an initial value
<emilio> ... it's a lot more verbose and it should work
<TabAtkins> q+
<emilio> ... I guess question is "is that good enough"? Or can we simplify it somehow for authors?
<Rossen_> ack fantasai
<emilio> fantasai: Wondering about two things we could possibly do. One of them is making highlights inherit from the root by default
<emilio> ... which might be a reasonable thing to do?
<emilio> ... or specifying that variables are special and they inherit from the originating element
<fantasai> probably can't inherit from :root for all properties, but for variables might be OK
<emilio> delan: I think the first idea seems cleaner
<emilio> ... I worry if there are any unintended side-effects
<emilio> q+
<emilio> fantasai: I think the idea is "if you're on the root selection" the variable properties would inherit from the root to `:root::selection`
<emilio> ... I wonder if we want to make this work for every element
<Rossen_> ack TabAtkins
<fantasai> TabAtkins: inheriting from originating element appeals, but assuming we want to inherit from a single place could address a larger concern
<emilio> TabAtkins: Inherit from originating element is appealing but if that doesn't happen this could be an opportunity to address a larger concern
<fantasai> TabAtkins: ....
<fantasai> TabAtkins: Argument for root, animations can play into that don't want to play into other places in the tree
<fantasai> scribenick: fantasai
<fantasai> TabAtkins: Few other suggestions, but if we are going to inherit all the highlights from a single place should do in a way that addresses larger concern
<fantasai> TabAtkins: either use initial value from register Properties
<fantasai> TabAtkins: or .... doesn't have animations apply to it
<fantasai> emilio: Want to point out that ::backdrop has the same issue, ::backdrop doesn't inherit from :root
<TabAtkins> s/..../a more ergonomic way to set initial values that/
<fantasai> emilio: it hasn't come up often, but it hsa come up sometimes
<fantasai> emilio: I would rather avoid inheriting from multiple places, because that's messy
<fantasai> emilio: very special-casy
<TabAtkins> like `@root { /* only custom props here */ }`
<fantasai> emilio: we do something like that for ::first-line, and it's a massive pain. Don't wish that to anyone
<fantasai> Rossen_: where do we go from here?
<fantasai> delan: Agree with emilio in general
<fantasai> delan: I think especially highlight inheritane, but a lot about highlight pseudos, is full of special cases
<fantasai> delan: would prefer to avoid adding more
<fantasai> delan: so maybe it's fine?
<Rossen_> q?
<Rossen_> ack emilio
<emilio> ack emilio
<fantasai> delan: Tab does have an interesting point though, that there's a general problem to be solved. Not sure
<fantasai> Rossen_: I'm a bit lost on where we're going from here. What would you like to see, delan?
<fantasai> delan: Leaving aside the more general issue of how we can use variables in non-element contexts
<fantasai> delan: for the core issue, I think consensus was that the best workaround so far is using custom property registrations with initial values
<emilio> having an `@root` or `@document {}` rule that applies to the whole document makes sense to me fwiw
<fantasai> delan: I guess the question I'm unsure about is do we think that is too annoying and unergonamic? No one had an opinion on that in the thread
<fantasai> delan: do we think that's already too annoying?
<fantasai> Rossen_: for developers?
<fantasai> delan: yeah
<argyle> q+
<emilio> q+
<fantasai> TabAtkins: Lea expresses that she find that's too unergonomic to be worthwhile and would prefer something else here
<Rossen_> ack argyle
<fantasai> argyle: I have lots of experience with custom properties, and it's very tedious to ...
<fantasai> argyle: I have a library called openprops with 350 properties
<TabAtkins> Also I'm not 100% sure off the top of my head how @Property interacts with being nested in @media and @supports.
<fantasai> argyle: I'm not going to hand-author 300 @Property rules so that they can drop into highlight pseudos
<fantasai> argyle: so some kind of higher level place to find these would be great
<fantasai> argyle: would be annoying to convert all my simple props and waiting for browsers to even support that
<Rossen_> ack emilio
<TabAtkins> (to be fair, both of these require waiting for support. but this is simpler than @Property, yeah)
<fantasai> emilio: Mentioned on IRC, but having @document or @root or whatever to apply properties to the initial style makes a lot of sense
<Rossen_> ack fantasai
<emilio> fantasai: one advantage of inheriting from their originating element is that if you need to set variables deeper in the tree you can do that
<emilio> ... and then they'd behave as you expect, you might need to change your ::selection rules a bit
<fantasai> emilio: That was the thing I was thinking about. From an author's perspective, what you want is inheriting from originating element
<TabAtkins> I think we'd define @document in cascade?
<fantasai> emilio: Higher-level thing works for some cases, but might also be more confusing
<fantasai> Tab, but it wouldn't inherit that's the problem
<fantasai> Rossen_: Sounds like we need more discussion, suggest we take it back to the issue
<fantasai> Rossen_: maybe you all can start formalizing the various ideas, would be great
<argyle> 👍🏻
<fantasai> Rossen_: and maybe next time we can be closer to a resolution
<fantasai> delan: sounds good
Just for the record, the latest variant of my (shot-down) proposal for prefixes in constant custom properties (#6099) included the @prefix block with rules directly inside of it instead of rulesets with selectors like :root.
@prefix"foo"url("https://example.org/framework.css");
@prefix"foo" {
--bar: baz; /* available as `-foo-bar` everywhere */
}
@prefix {
--bar: baz; /* available as `--bar` everywhere */
}
@prefix could become @define, @var, @global, @custom or whatever.
@document and @global and @root are the 3 front runners right? enabling an API like this?
Is it correct that you could use this as a replacement for the pattern where a lot of these values are declared in :root now?
If so, I think this is also more inline with the intent behind the author pattern.
I don't think anyone wants to use the whole list of properties on the :root element itself.
As I understand the feature now it also seems possible to downgrade this with tooling, which is always nice.
Just pasting my comments here from the other thread since the issue is discussed here now:
This keeps coming up. We don't want authors to be duplicating colors in these rules, but also we don't want a dependency on the root element's computed style. What if we define a new rule (::document?) where authors can define values for custom properties that are above the root node, i.e. akin to applying to the actual document node. Then media queries and other at rules can use var() references, and they'd resolve relative to that, and because it's not an element, nothing depends on any element's computed style.
@LeaVerou do you have an objection to the suggestion Anders made, to rely on the initial value of custom props, as defined by @property? Note that you can nest @Property in MQs and other conditionals if needed, to supply the "right" initial value.
I think that's a clumsy solution, as it requires a new @property rule for every single property. Authors tend to define A LOT of properties in their root rules (eg). Even when @property is widely supported, I don't see authors using it for every single custom property they define. Certainly better than nothing though!
Do note that another problem with the "just use initial values from @property" proposal is that these initial values cannot depend on other custom properties, whereas it's common today to do things like:
--color-red-h:0;
--color-red-s:90%;
--color-red-l:50%;
--color-red:hsl(var(--color-red-h) var(--color-red-s) var(--color-red-l));
--color-accent:var(--color-red);
h2 { color:var(--color-accent); /* any color that happens to be the accent color */
.error { border:1px solid var(--color-red); /* color that needs a specific hue */ }
With an @document (or whatever) rule, would properties inherit down to root etc or would they need to be re-specified on :root?
Reacted by Milan Raj and Marek ‘saji’ Augustynowicz
Activity
delan commentedon Dec 8, 2021
(summary for meeting)
andruud commentedon Jan 5, 2022
Author-defined
env()could be something to consider for this.tabatkins commentedon Jan 6, 2022
We've discussed using variable values in other contexts that don't inherit from root as well (like in @font-palette, for example).
Having an author-defined env() might work, but would require an author to duplicate values across properties and env(), or else decide for each whether they want to express it as a var or an env().
The idea that's been presented a few times is to special-case properties defined on the root, and make them available more globally, so any context that's not an element with :root as an ancestor can use var() to obtain the root values of the custom property. Would this be reasonable impl-wise?
andruud commentedon Jan 6, 2022
Yeah, I see how that would be annoying.
OK, then maybe we can specify that
var()in non-element contexts use the initial value of custom properties, and then provide a new way of specifying those initial values (if@propertyis too verbose).If we're going to generalize that, I suspect that creates way more complexity than it's worth. We'd be smuggling in the full weight of "computed-value-time", and we'd be unable to interpret any at-rules sooner than that, which is probably not a good thing. For example, the custom properties on :root may be animated, or they may depend on the computed font metrics of the selected font (e.g. with
--x:10ch+@propertywithsyntax:"<length>". Fun times ifvar(--x)is then used in@font-facesomehow).tabatkins commentedon Jan 7, 2022
Ah yeah that's true, we don't want animation and whatnot to come in. Initial value seems fine to me, and we can just lean on
@propertyunless/until we decide it's too annoying.Crissov commentedon Jan 8, 2022
In a later comment in #6099, I suggested something that perhaps could solve this use case, although I did not consider it at the time:
css-meeting-bot commentedon Mar 16, 2022
The CSS Working Group just discussed
custom properties on :root.The full IRC log of that discussion
<emilio> topic: custom properties on :root<emilio> github: https://github.com//issues/6641
<emilio> delan: there's a lot of content out there where a bunch of custom properties are specified on the :root
<emilio> ... historically that's been fine for highlight pseudos because they inherited from the element
<emilio> ... as spec'd now each highlight pseudo has a separate inheritance tree so it'll break that pattern
<emilio> ... so there's a compat issue in that but I don't think that's a huge issue because we've determined that some breakage is acceptable for these highlight pseudo
<emilio> ... but there's two complications for this, one is that authors at least they'd have to switch their stylesheets to `:root, :root::selection, ...` etc
<TabAtkins> :root, :root::selection, :root::highlight, ... { /* set up all the custom props here */ }
<emilio> ... it's also a bit of a perf issue because we might end up with a bunch of property blobs
<emilio> ... there's another option which is using `@property` with an initial value
<emilio> ... it's a lot more verbose and it should work
<TabAtkins> q+
<emilio> ... I guess question is "is that good enough"? Or can we simplify it somehow for authors?
<Rossen_> ack fantasai
<emilio> fantasai: Wondering about two things we could possibly do. One of them is making highlights inherit from the root by default
<emilio> ... which might be a reasonable thing to do?
<emilio> ... or specifying that variables are special and they inherit from the originating element
<fantasai> probably can't inherit from :root for all properties, but for variables might be OK
<emilio> delan: I think the first idea seems cleaner
<emilio> ... I worry if there are any unintended side-effects
<emilio> q+
<emilio> fantasai: I think the idea is "if you're on the root selection" the variable properties would inherit from the root to `:root::selection`
<emilio> ... I wonder if we want to make this work for every element
<Rossen_> ack TabAtkins
<fantasai> TabAtkins: inheriting from originating element appeals, but assuming we want to inherit from a single place could address a larger concern
<emilio> TabAtkins: Inherit from originating element is appealing but if that doesn't happen this could be an opportunity to address a larger concern
<fantasai> TabAtkins: ....
<fantasai> TabAtkins: Argument for root, animations can play into that don't want to play into other places in the tree
<fantasai> scribenick: fantasai
<fantasai> TabAtkins: Few other suggestions, but if we are going to inherit all the highlights from a single place should do in a way that addresses larger concern
<fantasai> TabAtkins: either use initial value from register Properties
<fantasai> TabAtkins: or .... doesn't have animations apply to it
<fantasai> emilio: Want to point out that ::backdrop has the same issue, ::backdrop doesn't inherit from :root
<TabAtkins> s/..../a more ergonomic way to set initial values that/
<fantasai> emilio: it hasn't come up often, but it hsa come up sometimes
<fantasai> emilio: I would rather avoid inheriting from multiple places, because that's messy
<fantasai> emilio: very special-casy
<TabAtkins> like `@root { /* only custom props here */ }`
<fantasai> emilio: we do something like that for ::first-line, and it's a massive pain. Don't wish that to anyone
<fantasai> Rossen_: where do we go from here?
<fantasai> delan: Agree with emilio in general
<fantasai> delan: I think especially highlight inheritane, but a lot about highlight pseudos, is full of special cases
<fantasai> delan: would prefer to avoid adding more
<fantasai> delan: so maybe it's fine?
<Rossen_> q?
<Rossen_> ack emilio
<emilio> ack emilio
<fantasai> delan: Tab does have an interesting point though, that there's a general problem to be solved. Not sure
<fantasai> Rossen_: I'm a bit lost on where we're going from here. What would you like to see, delan?
<fantasai> delan: Leaving aside the more general issue of how we can use variables in non-element contexts
<fantasai> delan: for the core issue, I think consensus was that the best workaround so far is using custom property registrations with initial values
<emilio> having an `@root` or `@document {}` rule that applies to the whole document makes sense to me fwiw
<fantasai> delan: I guess the question I'm unsure about is do we think that is too annoying and unergonamic? No one had an opinion on that in the thread
<fantasai> delan: do we think that's already too annoying?
<fantasai> Rossen_: for developers?
<fantasai> delan: yeah
<argyle> q+
<emilio> q+
<fantasai> TabAtkins: Lea expresses that she find that's too unergonomic to be worthwhile and would prefer something else here
<Rossen_> ack argyle
<fantasai> argyle: I have lots of experience with custom properties, and it's very tedious to ...
<fantasai> argyle: I have a library called openprops with 350 properties
<TabAtkins> Also I'm not 100% sure off the top of my head how @Property interacts with being nested in @media and @supports.
<fantasai> argyle: I'm not going to hand-author 300 @Property rules so that they can drop into highlight pseudos
<fantasai> argyle: so some kind of higher level place to find these would be great
<fantasai> argyle: would be annoying to convert all my simple props and waiting for browsers to even support that
<Rossen_> ack emilio
<TabAtkins> (to be fair, both of these require waiting for support. but this is simpler than @Property, yeah)
<fantasai> emilio: Mentioned on IRC, but having @document or @root or whatever to apply properties to the initial style makes a lot of sense
<Rossen_> ack fantasai
<emilio> fantasai: one advantage of inheriting from their originating element is that if you need to set variables deeper in the tree you can do that
<emilio> ... and then they'd behave as you expect, you might need to change your ::selection rules a bit
<fantasai> emilio: That was the thing I was thinking about. From an author's perspective, what you want is inheriting from originating element
<TabAtkins> I think we'd define @document in cascade?
<fantasai> emilio: Higher-level thing works for some cases, but might also be more confusing
<fantasai> Tab, but it wouldn't inherit that's the problem
<fantasai> Rossen_: Sounds like we need more discussion, suggest we take it back to the issue
<fantasai> Rossen_: maybe you all can start formalizing the various ideas, would be great
<argyle> 👍🏻
<fantasai> Rossen_: and maybe next time we can be closer to a resolution
<fantasai> delan: sounds good
argyleink commentedon Apr 1, 2022
@documentand@globaland@rootare the 3 front runners right? enabling an API like this?channel values from Open Props
Crissov commentedon Apr 2, 2022
Just for the record, the latest variant of my (shot-down) proposal for prefixes in constant custom properties (#6099) included the
@prefixblock with rules directly inside of it instead of rulesets with selectors like:root.@prefixcould become@define,@var,@global,@customor whatever.romainmenke commentedon Apr 2, 2022
Is it correct that you could use this as a replacement for the pattern where a lot of these values are declared in
:rootnow?If so, I think this is also more inline with the intent behind the author pattern.
I don't think anyone wants to use the whole list of properties on the
:rootelement itself.As I understand the feature now it also seems possible to downgrade this with tooling, which is always nice.
LeaVerou commentedon Apr 25, 2022
Just pasting my comments here from the other thread since the issue is discussed here now:
LeaVerou commentedon Apr 25, 2022
Do note that another problem with the "just use initial values from
@property" proposal is that these initial values cannot depend on other custom properties, whereas it's common today to do things like:With an
@document(or whatever) rule, would properties inherit down to root etc or would they need to be re-specified on:root?25 remaining items
Resolve highlight custom properties from the root
[css-pseudo-4] Add spec for resolving custom properties
Resolve highlight custom properties from the root
Resolve highlight custom properties from the root
Resolve highlight custom properties from the root
Resolve highlight custom properties from the root
Resolve highlight custom properties from the root
Bug 1850768 [wpt PR 41716] - Resolve highlight custom properties from…
Bug 1850768 [wpt PR 41716] - Resolve highlight custom properties from…
[css-pseudo-4] Add spec for resolving custom properties
Resolve highlight custom properties from the root
fantasai commentedon Oct 15, 2024
This resolution has been overtaken by #7591 see #7591 (comment)
Resolve highlight custom properties from the root