Skip to content

Commit ed18327

Browse files
committed
[css-properties-values-api] Add explainer for why property registration is global rather than shadow-scoped
1 parent da6e8f9 commit ed18327

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

css-properties-values-api/Overview.bs

+81
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,87 @@ with a <<length>> or <<length-percentage>> syntax component:
452452
and ''font-size'' will behave as if the value ''unset'' was specified.
453453
</div>
454454

455+
Shadow DOM {#shadow-dom}
456+
------------------------
457+
458+
Unlike many concepts in CSS
459+
(see [[css-scoping-1#shadow-names]]),
460+
property registrations are <strong>not</strong> scoped to a tree scope.
461+
All registrations,
462+
whether they appear in the outermost document
463+
or within a shadow tree,
464+
interact in a single global registration map for the {{Document}}.
465+
466+
<details class=note>
467+
<summary>Why can't registrations be scoped?</summary>
468+
469+
There are clear use-cases for property registrations to be scoped--
470+
a component using Shadow DOM
471+
and registering some custom properties
472+
for its own internal use
473+
probably doesn't intend for the outer page
474+
to see the registration,
475+
since the outer page doesn't even know the component is using that property.
476+
477+
However, there are also reasons to not scope the registration--
478+
custom properties are used to pipe data <em>into</em> a component,
479+
and it's useful for the outer page
480+
to be able to set such custom properties
481+
and have them syntax-checked by the registration;
482+
similarly, concepts such as a property's initial value
483+
don't make much sense
484+
unless the property registration exists globally,
485+
so it applies to the property even at the document's root.
486+
487+
But the above just means that registration scope
488+
might be something that should be controllable,
489+
not that it should be forced to be global.
490+
491+
The reason registrations must be global
492+
is because elements can exist in multiple tree scopes
493+
at the same time,
494+
with styles from each tree scope
495+
intermingling and cascading together.
496+
This applies to the [=host element=],
497+
which lives in the outer tree
498+
but is stylable from the shadow tree
499+
by the '':host'' selector,
500+
but also elements inside a shadow DOM
501+
that are targetable from the outer tree
502+
by the ''::part()'' pseudo-element.
503+
504+
If registrations could be scoped to a tree scope,
505+
and a single property was registered
506+
both inside and outside,
507+
it's not clear which registration should be applied
508+
to parse the value.
509+
Even if we tracked which tree a value came from
510+
(something we do for other tree-scoped values)
511+
and applied the corresponding registration,
512+
it's not clear that this would give a reasonable result--
513+
the shadow DOM might expect a property to have a particular value space,
514+
and be surprised when it receives something completely different
515+
due to the outer tree winning the cascade
516+
and applying its own registration.
517+
</details>
518+
519+
When custom properties are exposed
520+
as part of a Shadow DOM-using component's public API,
521+
this global registration behavior works as intended.
522+
If the outer page is using a custom property of the same name
523+
for different purposes,
524+
that is already a conflict that needs to be resolved,
525+
and the registration behavior does not make it worse.
526+
527+
If a custom property is intended for private internal usage for a component, however,
528+
it is recommended that the property
529+
be given a likely-unique name,
530+
to minimize the possibility of a clash with any other context.
531+
This can be done, for example,
532+
by including the project name,
533+
or some short random string of text,
534+
in the name of the property.
535+
455536

456537

457538
<!--

0 commit comments

Comments
 (0)