Re: [w3c/webcomponents] How should various document internal references work when SVG is being used in shadow DOM (#179)

Thanks for looping me in, @annevk.  Sorry I wasn't aware of this discussion sooner.

When talking about SVG and shadow DOM, it is important to distinguish two cases:

- SVG `<use>` element shadow trees.
- inline SVG within HTML/web components shadow trees. 

Use-element trees already have some "magic" to them that isn't defined in the core shadow DOM specs, so they can have special behavior for URL references, too.  For inline SVG in web components, I would expect that URL references would behave in a way consistent with other handling of URLs and ID references.

For the combination of the two (use element references inside inline SVG inside web components), I would hope that we can specify behavior in a way that naturally compounds through each shadow up to the document level.

## SVG `<use>` element shadow trees

The SVG 2 spec [includes my attempt to make sense of this situation](https://svgwg.org/svg2-draft/struct.html#UseShadowTree), but note that this does not yet include a [resolved change](https://github.com/w3c/svgwg/issues/363) to make these trees "closed" mode, which will simplify some of the details, and hopefully be enough to get implementer commitments to actually work from the spec on other details.  That said, until we actually get implementers working from the spec, all of this is subject to change based on feedback!

As far as URL references go, I would expect the advice currently in the spec to persist: as part of the `<use>` cloning, make all URLs absolute, relative to the base URL of the source document.  With the benefit of a closed shadow tree, the implementation details can be left ambiguous, so it could instead be implemented by setting a `<base>` that applies within the shadow tree.

As a consequence of the absolute URL conversion, it doesn't matter if an SVG paint server or filter effect is included in the cloned document fragment (i.e., a child of the symbol versus a sibling): the reference will always be to the original element in the external file.  Since the external file and the cloned copy are both read-only, there shouldn't be any rendering difference either way. 

The current spec text only requires URLs to be made absolute when cloning content from external files.  

For same-file clones, the rule is that "The shadow tree itself uses the same document base URL as the document that includes it."  So URL references would be directly resolved against the original document tree.  I *think* I chose this behavior based on spec or implementation testing of how links were handled in web components, but I didn't include a spec cross-reference, so I'm not sure.

In this case, the original element in the main document is mutable, but since the clone is required to be kept in sync with the original, there again should be no rendering difference in the case of graphical effects like filters or gradients, compared with referencing a clone in the local shadow tree.

(There may be some implementation complexity for properties where user agents currently only support same-page URL references for graphical effects. But the best solution there would be for the user agents to match the spec and support cross-file effects! 😉)

However, there is [special behavior for animation element references](https://svgwg.org/svg2-draft/struct.html#UseAnimations).  In this cases, the target element is something rendered on screen, not just abstract processing instructions. You need to know which clone or original to animate.  To make interactive animations sensible, and consistent to how interactive CSS pseudoclasses are spec'd to behave, each clone can be animated independently. However, when animation is triggered by an event attached to an element `id`, it will be triggered "when any instance of an element with that ‘id’ receives the same event."  This rule was designed to be consistent with event listeners, which in turn was designed to be consistent with cloned `onEventX` attributes.

(Note that the SVG WG has resolved to remove this section from this version of the spec, probably deferring it to the [SVG Animations spec](https://svgwg.org/specs/animations/), so it should be considered less stable than the rest of the spec, and changes less urgent.)

In contrast, when handling ARIA ID references within use-element shadow trees, [SVG-AAM](https://w3c.github.io/svg-aam/#mapping_use_shadow_tree) currently recommends recursively searching out of the shadow tree for a match:

> - When processing WAI-ARIA attributes on elements within a shadow tree, the user agent MUST first attempt to match any IDREF values against other elements in the same shadow tree, before searching for a match in the host's node tree. If shadow trees are nested, the user agent MUST recursively search from the current shadow tree to the tree containing its host use element, until the document tree is reached.
> 
> - In all other cases, when matching IDREF values in WAI-ARIA attributes, the user agent MUST NOT consider elements in the shadow tree of a use element.

That is still an open issue on the SVG-AAM spec, with the intention to harmonize the behavior across all types of shadow trees, see https://github.com/w3c/svg-aam/issues/7 and https://github.com/w3c/core-aam/issues/4 Note that for ARIA, these are same-document ID references, not URLs, so generating an absolute URL is not an option.


## inline SVG within HTML/web components shadow trees

There's nothing in the SVG specs particular to this case. I would expect that URLs in this case would be resolved in a manner consistent with handling URLs and ID references in web components in general.

If the chosen approach is to treat a shadow tree simply as if it inherits the base URL of the document, then it would seem at first glance as if you couldn't create local references to elements that only exist in the shadow tree.

So in this structure, the `#outer` reference would work, but not the `#inner` reference:

```html
<svg>
  <symbol id="outer">...</symbol>
</svg>
<custom-element>
  #shadow-root
    <svg>
      <use href="#outer"/>
      <symbol id="inner">...</symbol>
      <use href="#inner"/>
    </svg>
</custom-element>
```

However...

[CSS Values and Units 4](https://drafts.csswg.org/css-values/#local-urls) defines special behavior for fragment-only URLs (defined by whether they start with a `#` character), so that they always resolve to an element in the current document, regardless of any `<base>` URL changes, and regardless of whether the CSS rule was declared in the current document or another one.

The [SVG 2 guidance on identifying a target element](https://svgwg.org/svg2-draft/linking.html#processingURL-absolute) was intended to create a similar effect, by dynamically comparing generated absolute URLs against the current base URL of the document to define whether it is a local or external reference.

Neither approach is well implemented yet, so both could be revised to create a definition of a "local" reference that takes shadow tree nesting into account.  For example, to follow the algorithm that I proposed in SVG-AAM, and find the nearest-matching element by starting in the local shadow tree and then moving toward the light.

I would strongly urge that any such algorithm be defined in the shadow DOM specs in a way that applies to *all* cross references, both ID references and local URL references, in SVG, CSS, HTML (e.g., `for` attributes), or ARIA.



-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/179#issuecomment-392605203

Received on Monday, 28 May 2018 21:22:19 UTC