Re: [csswg-drafts] [css-scoping] Handling global name-defining constructs in shadow trees (#1995)

Thanks for the attention to this topic, @rniwa! Sorry it then slipped thru *my* net and languished for another month. ^_^

> What are use cases for which components declare @font-face and not use it?

I didn't say "not use", I said "not use immediately"; that is, declaring a font intended for use on *some* elements deeper in the component. However, because of the `font-face` inheritance, currently the component's version of the font name will end up accidentally being used on the component's top-level text, and all descendant text until `font-face` gets set to something explicitly.

<details>
<summary>example</summary>
<pre>
&lt;!doctype html>
&lt;style>
@font-face { font-family: foo; src: url(foo); }
body { font-family: foo; }
&lt;/style>
This text is in the outer page's "foo" font.
&lt;x-component>
 &lt;::shadow>
  &lt;style>
  @font-face { font-family: foo; src: url(bar); }
  p.special { font-family: foo; }
  &lt;/style>
  Whoops, this text is in the shadow's "foo" font accidentally!
  &lt;p class=special>This text is in the shadow's "foo" font on purpose.
 &lt;/::shadow>
&lt;/x-component>
</pre>
</details>

> Is it? This seems to be the same issue as other kinds of inheritance. If someone declares a CSS variable in the outer tree and the component also defines its own CSS variable, they would collide. But we didn't think that's not an issue. Why is this case so special?

Ah, no, this is quite a different situation.

Custom properties are declared on a particular element, and only visible to that element and its descendants. Their values are only referenced *explicitly*, when the author writes a `var()` function. Getting an unexpected collision requires the author to *make an authoring mistake*, using `var()` on an element accidentally when they hadn't declared an appropriate custom property for it, and then having the outer page accidentally declare a custom property of the same name for its own use.

Compare this to `@font-face`/`font-family`, where `@font-face` always declares a new name at the *topmost* level of the tree, visible to every single element in the tree, and *every single piece of text* **automatically** references the set of font-face names, even if the author never set the `font-family` property on an ancestor. When the top-level text of a shadow tree consults the inherited `font-family: foo;` declaration, nobody's made any mistake, that's just working as intended. The design of this ancient CSS1 property (and CSS2 at-rule) just didn't take multiple scopes into account.

> It does seem to me that fragment identifier would always have to be resolved against the tree in which the declaration first appeared.

Cool, it sounds like we're in agreement, then. ^_^ All "global" references in CSS have to (implicitly) carry around information about what tree they were declared in, so they can continue acting correctly as they inherit between trees, otherwise things will break. (Either due to accidental collisions, like `font-family`, or automatically, like `fill: url(#foo)`.)

So does my approach to solving this sound good? Adding a `scoped()` function that the references are automatically rewritten to use when they inherit across a tree boundary?

Or do you have a different approach in mind? If so, can you describe it?

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/1995#issuecomment-483450954 using your GitHub account

Received on Monday, 15 April 2019 23:05:54 UTC