Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
[css-properties-values-api] Should property registration be scoped? #939
The fact that property registration is document global makes it impossible to use a custom property privately in a shadow tree. Maybe registration should be scoped somehow, optimally to a style sheet or shadow scope.
Like other features that would benefit from scoping (
If limited to a shadow scope:
If limited to a style sheet:
I strongly agree that it would be great to scope these, in the same way as we intend to scope other CSS values. (And on that point, will someone please either commit to this proposal or offer a credible alternative?)
This means scoping to tree scopes, and the registration you use depends on the scope the stylesheet is in. (Tho this has some issues, which I'll discuss in a sec.)
I think inheritance should happen with the synthesized token stream, as if you'd just set that token stream directly in the new context. Syntax has only a relatively small effect on registered properties, just making it go iacvt if necessary, and affecting how it reifies in Typed OM.
You already have to track the stylesheet separately in each location it's inserted into, as the separate locations can already clash and have to be resolved based on document order/shadow origin/etc. (Eg a stylesheet can be inserted into both the outer page and a shadow, targeting the same element with a
I think the biggest conflict here is: what registration does an element use when it's a shadow host? That is, if the main page registers
Perhaps it matters based on where that rule comes from? Aka, a custom property's value carries the value's scope with it, and once you run the cascade and figure out which value wins, you know how to process it as a computed value? I think this matches with the proposed behavior in w3c/csswg-drafts#1995 for other properties -- setting
However, it does mean that a script trying to use the Typed OM to interact with the property might be confused by what it gets! In my example, if the outer page asks for the value, it'll be expecting a CSSNumericValue, but it might instead get a CSSColorValue if the declaration from the shadow wins. Maybe that's okay?
An alternative is that the element uses the declaration of the tree it's in, always. This means that a shadow tree can't reliably register a property and then use that property on the
I don't think there's any completely ideal answer here.
The Houdini Task Force just discussed
The full IRC log of that discussion<myles_> Topic: Scoping property registrations in the shadows
<TabAtkins> github: https://github.com//issues/939
<iank_> scribenick: iank_
<iank_> TabAtkins: Simon brought up, if we want prop registration scooped to shadow trees.
<iank_> TabAtkins: Best case an custom element will unregister a property, and reregister it.
<iank_> TabAtkins: There is a meta issue around things not being scoped in CSS.
<iank_> TabAtkins: 1) What happens when a property registered in the light dom, inherits into the shadow dom, and there is different property registrations.
<iank_> TabAtkins: I suspect that we can basically, it keeps around a synthesized property string, as it goes into the new thing, it can be reinterpreted.
<iank_> TabAtkins: This sounds similar if it wasn't registered.
<iank_> TabAtkins: If you do a size property, it'll probably be a <length> it both places.
<iank_> TabAtkins: You can code defensively, but resetting at the top of the shadow root.
<iank_> TabAtkins: If it crosses the boundary it just gets reinterpreted as a token stream.
<iank_> heycam: A broader problem seems to be what .... there is no good way to partition these properties.
<iank_> heycam: If you have multiple registrations.
<iank_> TabAtkins: Nothing more specific.
<iank_> heycam: I could imagine 2 custom element authors, both coming up with a --theme property independently.
<iank_> heycam: No way to handle that these could be interpreted differently.
<iank_> TabAtkins: As long as the two components are siblings you could set it above the CEs.
<iank_> TabAtkins: If they are nested, the outer CE knows that it nested the child.
<iank_> iank_: Has CE scoping occured yet?
<iank_> masonfreed: Still not solved yet.
<iank_> heycam: If we expect component authors to use suitably named properties to avoid conflicts, then the solution you described sounds fine.
<iank_> heycam: 90% of CP usage I see, is setting the properties on the root.
<iank_> fremy: Another option would be to, have a map of token streams, and when you read it , it can switch based on the reading context.
<iank_> fremy: Its consistent within a property tree, downside if you have slots you can't reset these.
<iank_> fremy: We might want to ask people who are using CEs on how they use them.
<TabAtkins> problem case: Light-dom author sets a theming property expecting it to apply to whole page. Shadow-dom author uses colliding name in their shadow. Shadow version of the property is what the slotted content sees, not the light-author's intended light value.
<iank_> heycam: Can you describe other discussions?
<iank_> TabAtkins: Yes
<iank_> TabAtkins: discussion was about font-face but was about other things.
<iank_> TabAtkins: not just font-face, fill: url(#something), etc.
<iank_> TabAtkins: A lot of confusion.
<iank_> TabAtkins: People think that you just walk upwards, but this would be bad, as unreliably interpreted differently.
<iank_> TabAtkins: My idea - each value which has this context depedence, it keeps around a link to where it was declared. As its passed around contexts, it keeps a reference to what defined it.
<iank_> TabAtkins: The reference would be explicitly caught, and reflected in the TypedOM version.
<iank_> TabAtkins: It'll be Document, or ShadowTree, etc, could grab the value, and use it elsewhere.
<iank_> heycam: On font-face specifically not sure how this effects document.fonts
<iank_> TabAtkins: ShadowTree would have a tree.fonts, conceptually.
<iank_> TabAtkins: keyframes rules, etc would also be what was defined within your scope, but would still work if you interited a keyframe across a shadow root boundary.
<iank_> heycam: Does this match what fremy described?
<iank_> TabAtkins: Yes.
<iank_> TabAtkins: That would solve the problem which i minuted earlier. Keeping the simple keeping the value with a single reference. Complexity is a little worrying.
<iank_> smfr: Is any of this written down anywhere?
<iank_> TabAtkins: Only present within that issue thread. As nobody has said this is good.
<iank_> TabAtkins: <snark>
<iank_> smfr: I'll try and get our CSS folks to review it.
<iank_> emilio: I don't think @font-face works within a shadow tree.
<iank_> emilio: keyframes don't work, blink/ff do something different to webkit.
<iank_> TabAtkins: Yeah would like to get a consistent answer.
<emilio> s/don't work/don't work the same across browsers
<iank_> TabAtkins: What registration use when it is a Shadow Host. Light DOM sees it as a normal element, Shadow DOM sees it as a :root.
<iank_> TabAtkins: Which registration should it use?
<iank_> TabAtkins: Not sure.
<iank_> TabAtkins: 1) Uses the reg. of whereever that style came from, outer uses outer reg. for example.
<iank_> Good thing: styles always work, as long as they don't touch at the same time. But unpredictable for what TypedOM returns.
<iank_> fremy: But if you do what I said it can support both.
<iank_> TabAtkins: If we do the multiple scopes, we need to define how to get all the versions of the property.
<iank_> fremy: Yes - that's another question, how do you read the values.
<iank_> TabAtkins: None of my proposals have to worry about what context the script is in.
<iank_> TabAtkins: Big problem is what happens w/ typed om.
<iank_> fremy: I don't have a good idea for that.
<iank_> TabAtkins: 2) Always use the context which the element lives within. This means always get the Light DOM version. Means that you can never set the :host of the shadow DOM.
<iank_> plinss: That seems not good.
<iank_> TabAtkins: I agrree its not great, but simple and pretictable.
<iank_> TabAtkins: Not sure which one I want to do.
<iank_> TabAtkins: If anyone has opinions let me know.
<iank_> TabAtkins: As far as I can tell that is the major issue.
<iank_> TabAtkins: Lets get our browser folks about how this should work.
<iank_> TabAtkins: At some point I'll commit text about how this should work.
<iank_> heycam: What happens with constructable stylesheets.
<iank_> heycam: What happens to style elements which haven't been inserted within the point yet.
<iank_> heycam: ... e.g. you can access these from the TypedOM for these.
<iank_> emilio: This is at specified value time, and the grammer isn't applied yet.
<iank_> TabAtkins: ... yes - only at computed value time this is applied.
<iank_> TabAtkins: I'm good with this issue then, can move only the next one.
<iank_> fremy: Last thing you proposed, it'll use the Light DOM reg., the advantage is that you can always use both. If you are within the light tree, you can't pass information into the shadow tree.
<iank_> fremy: Component - wants to have a custom prop e.g. --grid-type
<iank_> TabAtkins: You can still set it, it won't get corrected until it hits the shadow tree.