Open tabatkins opened 2 months ago
(Another way of looking at this is that global() just changes the way we construct a tree-scoped name/ref. Normally it's a (name, scope) pair with the scope being an automatically-filled-in tree reference; if you use global(), we instead set the scope to the given ident. Matching rules still work otherwise the same, requiring both names and scopes to match. )
Hmm, tree-scoped lookup works by traversing the tree-scope chain, looking for a match (at least for some @-rule cases). We'd now need to place the thing constructed by @whatever global(--foo)
into a non-home tree-scope (for the first time), which might cause some issues.
But even with that, this sounds straightforward.
Regarding the scope-name
parameter: is it wise to add another scoping mechanism to the soup of (Shadow DOM, @scope
, timeline-scope
, anchor-scope
)? Is global(--foo, --wikipedia)
a huge improvement over global(--wikipedia-foo)
? Maybe we can drop this parameter, and just rely on prefixing. If dynamic prefixing is needed, maybe consider #9141.
It's possible that the correct answer to these requests is that we need a way to opt a shadow tree out of being encapsulated, so it acts like it's part of the outer page as much as possible (no more event censoring, etc either).
I'd expect many authors to prefer this. Related: #10420
(Sorry, me and Anders discussed this in person and I didn't come back to update the thread.)
Regarding the scope-name parameter: is it wise to add another scoping mechanism
Yeah, let's drop that. Having a scoping name is only useful if we can rely on some variety of defaults to let you avoid specifying the scope most of the time. But here it would be required in every instance, meaning it's just part of the name anyway; you might as well just bake it into the name itself.
So consider the proposal simplified: just a global(<custom-ident>)
The CSS Working Group just discussed [css-scoping] Breaking name encapsulation
.
Slightly aside, but related: another thing to think about in relation to the name encapsulation are things like a potential implicit anchor created by an anchor
attribute (see https://github.com/whatwg/html/pull/9144). Ideally, when we have such an implicit anchor, it would be nice to be able to “export” it as a named entity as well in some way from CSS.
Also, feels noteworthy to think if we could (and if we should) somehow make this consistent (at least in some ways) with the cross-root ARIA (and maybe other similar proposals for non-ARIA things; I don't know if there are any, but maybe?)
In case it's useful to the conversation: an example of passing anchor
via Reference Target API: https://github.com/web-platform-tests/wpt/blob/51a20f3fb332907bdaf041da5aa6ab2d8ace62e8/shadow-dom/reference-target/tentative/anchor.html#L4
The Scoping spec defines "tree-scoped names" and "tree-scoped references" to explain the encapsulation effects of Shadow DOM on CSS constructs. These concepts have been reused across many specs now, and overall seem to do what we want - shadows can safely define and reference names without having to worry about the outer page accidentally defining or referencing a conflicting name.
However, authors regularly ask for ways to defeat this encapsulation, and reference things across shadows. Generally this is because they're using shadow dom just as an organization tool, not an encapsulation boundary - it's the easiest way to use custom elements. It's possible that the correct answer to these requests is that we need a way to opt a shadow tree out of being encapsulated, so it acts like it's part of the outer page as much as possible (no more event censoring, etc either).
However, in the absence of that, it might make sense to have a CSS mechanism for this opt-out, to give authors a way to (a) write shadow CSS that can refer to names defined in the outer tree, or in other shadow trees entirely, and (b) write shadow CSS that defines names that the outer page, or other shadow trees, can reference.
As a conversation starter, I suggest a new
global(<ident>, <ident>?)
function, allowed anywhere that takes idents for tree-scoped names or tree-scoped references. If an identfoo
would define a tree-scoped name,global(foo)
defines it "globally" instead, without a tree scope. Similarly, if an identfoo
would be a tree-scoped reference, thenglobal(foo)
is a "global" reference, matching names without a tree scope.The second argument is a scope name; the name/ref is still global, but must match the scope name as well as the ident to be considered matching. Omitting the ident indicates the "default" global scope, and still only matches with other names/refs in the "default" global scope.
(Another way of looking at this is that
global()
just changes the way we construct a tree-scoped name/ref. Normally it's a (name, scope) pair with the scope being an automatically-filled-in tree reference; if you useglobal()
, we instead set the scope to the given ident. Matching rules still work otherwise the same, requiring both names and scopes to match. )For example, by default, using
anchor-name: --foo;
on an element in a shadow DOM, and thenposition-anchor: --foo;
in a light-dom positioned element, the two elements won't see each other. Each is tree-scoped, and the anchor-matching rules require the name and the reference to have the same tree scope. But if you usedanchor-name: global(--foo);
andposition-anchor: global(--foo);
, they'd find each other, because they have matching tree scopes (the default global scope).Coordinating components can still avoid accidentally clashing with globals from other sources by using the scope-name argument with a reasonably unique name, if they want, and pages can achieve hostile interoperability with those components by using the same scope name if they want.
(Note: The first draft of the tree-scoped idea, back in #1995, proposed something similar, but not as good. We ended up concluding that we didn't need the complexity of letting references switch into "global" mode at the time, but I think continuing author requests shows that was a wrong decision in the end.)
(Also, if we did this, we should probably define
<tree-scoped-ref>
and<tree-scoped-name>
productions, and do an audit to use those everywhere we're currently just using idents and declaring the tree-scoped-ness in prose.)