Re: Shadow DOM: Hat and Cat -- if that's your real name.

On Feb 4, 2014, at 10:56 AM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:

> On Tue, Feb 4, 2014 at 10:02 AM, Edward O'Connor <eoconnor@apple.com> wrote:
>> Hi Dimitri,
>> 
>> You wrote:
>> 
>>> As indicated by Tab at the F2F, Blink currently implements the cat/hat
>>> combinators proposed by yours truly [3].
>>> 
>>> FWIW, I don't fully understand why it would be so terrible to leave
>>> cat and hat alone (in talking with Tab, there's only a weak precedent
>>> for preferring pseudo element functions to combinators with
>>> ::content), but I am okay with renaming them. Ultimately, it's this
>>> WG's shed, I just store my bike there.
>> 
>> I don't think host documents should be able to select arbitrary elements
>> in the shadow DOM. A much better model, which IIRC was in one of your
>> documents at one point, is to let the component author explicitly export
>> certain shadow elements as pseudos. Something like:
>> 
>> # In shadow tree
>> 
>>    <div pseudo=foo>...</div>
>> 
>> # in CSS, if that shadow tree is attached to el with id bar
>> 
>>    #bar::pseudo(foo) { ... }
>> 
>> In this model, the component author is only signing up for a contract
>> for which they know the terms.

I'm very much in favor of this approach on a conceptual level at least. We can work on the syntax to make it easier to use.

Piercing the shadow dom explicitly is a fundamental violation of the encapsulation that it's supposed to be providing. Having some kind of model for the component to export it's stylistic structure preserves the encapsulation and allows modification or substitution of components without breaking the styling (which is supposed to be separate to the best extent possible).

> 
> I didn't get into depth about this during the f2f, but we tried this,
> and it doesn't work.  It's an attractive nuisance, because it's
> actually way weaker and more annoying than you think from looking at
> it.
> 
> For one, it requires explicit annotations on every element you want to
> expose to styling.  If you want to expose all or most of a component's
> internals, that's extremely annoying.

Understood but there are several other ways the "style targets" (for want of a better term) within the component could be exposed that could reduce the annoyance. For example, we could use simple flags to turn export on and off that nest (like we do in our spec markup for exporting links) and derive the pseudo-element names from the element names by default (with an optional override via attribute). 

Another approach could be to provide an explicit style map as part of the component that defines a pseudo-element structure and maps it to shadow dom nodes (perhaps via selectors). We could also mix and match the models.

> 
> For two, the pseudo name is roughly a class analogue, and a class by
> itself is too weak of a mechanism for useful styling - you can't, for
> example, style based on an attribute on the element, or on
> :nth-child(), or anything else like that.  (It's actually weaker than
> class as originally specified, since you can only provide one name per
> element.  But that's obviously a detail that could be tweaked.)

Those types of uses can be achieved by relaxing the restrictions on pseudo-element selectors, what would be wrong with:
::shadow-thing[foo=bar]
or
::shadow-thing:nth-child(even)

> 
> For three, it's only a rough analogue for hat ^, not cat ^^.  If you
> only surface the pseudos that the given component defines, you can't
> style anything further down.  If you surface all the pseudos defined
> by the component and anything internal, you run into lots more
> problems - name collisions, can't distinguish between things when a
> component uses two copies of another component internally, etc.

Again achievable by relaxing restrictions on pseudo-element selectors:
::shadow-thing ::nested-shadow-thing.foo:nth-child(3)

The whole reason that I proposed distinguishing pseudo-elements via '::' instead of ':' in the first place was to make it a user-extensible space to allow selecting arbitrary non-dom node "things" (originally extra CSS boxes but equally applicable to shadow dom nodes), let's leverage that.

Peter

> 
> By exposing the structure directly via the shadow combinators, you do
> lose some of the benefits of encapsulation, but the usability wins are
> *enormous* over any other solution we've seen so far.
> 
> ~TJ
> 

Received on Tuesday, 4 February 2014 19:32:41 UTC