WICG / webcomponents

Web Components specifications
Other
4.38k stars 372 forks source link

How should various document internal references work when SVG is being used in shadow DOM #179

Closed hayatoito closed 1 year ago

hayatoito commented 9 years ago

Title: [Shadow] How should various document internal references work when SVG is being used in shadow DOM (bugzilla: 27380)

Migrated from: https://www.w3.org/Bugs/Public/show_bug.cgi?id=27380


comment: 0 comment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=27380#c0 Olli Pettay wrote on 2014-11-20 12:37:34 +0000.

hayatoito commented 8 years ago

@smaug---- , if you have a change, could you elaborate this issue?

annevk commented 8 years ago

I think this is similar to the fragment identifier issue and we should resolve it in the same way. E.g., filter: url(#element-id) should not cross the shadow boundary.

hayatoito commented 8 years ago

I see. I think we can agree that it should not cross the shadow boundary. If SVG spec is using a node tree correctly, I do not think we need any action.

smaug---- commented 8 years ago

So stuff like

<defs>
    <linearGradient id="Gradient01">
      <stop offset="20%" stop-color="#39F" />
      <stop offset="90%" stop-color="#F3F" />
    </linearGradient>
  </defs>
  <rect x="1cm" y="1cm" width="6cm" height="1cm" 
        fill="url(#Gradient01)"  />

won't be possible in shadow DOM. Doesn't that make it rather hard to use any real world SVG within Shadow DOM? (perhaps that is ok?)

But yes, I guess that is the same as filter: url(#element-id) issue.

annevk commented 8 years ago

As long as the SVG is inside the shadow tree, it will work, no?

smaug---- commented 8 years ago

It does? Then I've missed some spec change which makes that fragment identifier to work.

annevk commented 8 years ago

Perhaps the language in SVG assumes a document tree at the moment, but it seems reasonable for that to work in the same way that <form> can work when fully contained in a shadow tree, no?

smaug---- commented 8 years ago

Sure. But need to make sure the specs actually end up defining that. (though, not sure I understand where in <form> handling there are random urls being used as id refs)

jwatt commented 8 years ago

Ah, I asked about this here: http://www.w3.org/mid/89c91562-7e1b-42f3-6cfa-2e651757f32b@jwatt.org

Good to see this has already been discussed.

devingfx commented 7 years ago

I assume that is the same issue as inline <svg> symbol library :

<!DOCTYPE html>
<html>
    <head>
        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" 
             xmlns:xlink="http://www.w3.org/1999/xlink">
            <symbol id="icon-cog">
                <path d="...."/>
            </symbol>
            <symbol id="icon-close">
                <path d="...."/>
            </symbol>
        </svg>
    </head>
    <body>
        <custom-element>
            #shadow-root
                <svg xmlns="http://www.w3.org/2000/svg" 
                     xmlns:xlink="http://www.w3.org/1999/xlink">
                    <use xlink:href="#icon-cog"/>
                </svg>
                <svg xmlns="http://www.w3.org/2000/svg" 
                     xmlns:xlink="http://www.w3.org/1999/xlink">
                    <use xlink:href="#icon-close"/>
                </svg>
            /shadow-root
        </custom-element>
    </body>
</html>

I would say here that the fragment identifier should cross shadow boundary in this case. By replacing the <svg> library by another one (loaded via xhr) following the same symbol naming, you can swith he whole app icon set on the fly. Theme authors can distribute several icons set this way, following the use-land library icon's namming convention it's targetting.

The workaround to this if not crossing is to reference an external file like so:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <custom-element>
            #shadow-root
                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"
                     onclick="root.toggleMenu( settingsMenu )">
                    <use xlink:href="icons/library.svg#icon-cog"/>
                </svg>
                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"
                     onclick="window.close()">
                    <use xlink:href="icons/library.svg#icon-close"/>
                </svg>
            /shadow-root
        </custom-element>
    </body>
</html>

But if you need to change the <svg> library on the fly, you'll have to loop on each node to find shadow root to find nested <svg><use> and change the xlink:href manually, what can be a pain ...


I assume fragment identifier issue have to resolve the same way for all use cases, so maybe it's not possible to specify that "fragment identifier don't cross boundaries, but not in case of embed svg"

I don't have recommendation here, I'm just pointing out a use case to take care of for this issue !

rniwa commented 7 years ago

SVG use element is indeed an interesting use case to consider. We probably need to come up with a new syntax / feature to make it work across shadow boundaries.

yGuy commented 7 years ago

With the advent of the implementations of Shadow DOM, this needs to be adressed: Devs who are trying to use the Shadow DOM cannot use non-trivial SVG at the same time, because Safari does not implement (or probably rather "actively disables") SVG Use elements inside shadow trees: https://bugs.webkit.org/show_bug.cgi?id=174977

They refer to this bug and say that it is because of the missing spec that they cannot implement svg use elements inside shadow doms.

I disagree, though and agree with @annevk that at least as long as the SVG in question is fully contained inside a shadow tree, it should work just like it would work at the root document level. However because of the (missing clarification in the) spec, it does not work in Safari.

Could you please reconsider the priority of this bug? Because without a resolution web developers will either have to make the choice between not using Shadow Dom, not using SVG, and not using Safari. I am sure they will decide not to use Shadow Dom, which would be a pity.

hayatoito commented 7 years ago
  1. Regarding this:

    as long as the SVG in question is fully contained inside a shadow tree, it should work just like it would work at the root document level.

I think everyone would agree that this should work. What clarification is required in SVG spec?

  1. Regarding this:

    I would say here that the fragment identifier should cross shadow boundary in this case.

This is questionable. I object to it.

annevk commented 7 years ago

https://drafts.fxtf.org/filter-effects/#FilterProperty seems to define this property (though maybe it's defined elsewhere too?) and it's basically super vague.

yGuy commented 7 years ago

I think everyone would agree that this should work. What clarification is required in SVG spec?

Unfortunately the Safari team disagrees here. Their implementation does not work for the "simple" case and they say it is because of the spec not being clear enough here.

rniwa commented 7 years ago

Since filter property as well as use element use a URL to reference an element, I don't think we can make it work without defining how an element inside a shadow tree can be referenced using a URL.

annevk commented 7 years ago

Does any browser actually support full URLs there or just local fragment references? I thought it is mostly the latter, but if it isn't this is indeed more complicated.

rniwa commented 7 years ago

Firefox definitely supports referencing a fragment in another file although Safari & Chrome don't support that.

yGuy commented 7 years ago

@rniwa - while I agree that it is not defined how it should work (and I also believe that probably the best solution would be to not make it work at all) to reference a fragment inside another document buried in a shadow dom or inside another shadow tree in the same dom, my concern right now is that the Safari/Webkit team claims that the SVG spec is not even clear enough about local fragments inside the same shadow tree dom. Please correct me (and them) if I'm wrong, but IMHO at least this should work, or shouldn't it:

anywhere on the page (be it inside a closed, or open shadow dom tree or at the top-level) this must work:

<svg width="10cm" height="3cm" viewBox="0 0 100 30" version="1.1"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <rect id="MyRect" width="60" height="10"/>
  </defs>
  <use x="20" y="10" xlink:href="#MyRect" />
</svg>

(slightly stripped down version from here https://www.w3.org/TR/SVG/struct.html#UseElement )

However according to them "because of the unclear spec" this svg does not work inside Safari in a shadow DOM.

This makes all of our SVGs break if they are used inside a shadow dom in Safari, and thus all of our customers cannot use shadow dom in their products if they need to target Safari and I would greatly appreciate it if you could somehow make a clear statement that at least this use-case must work according to the spec so that they will adjust their current implementation.

Thank you!

rniwa commented 7 years ago

My concern right now is that the Safari/Webkit team claims that the SVG spec is not even clear enough about local fragments inside the same shadow tree dom. Please correct me (and them) if I'm wrong, but IMHO at least this should work, or shouldn't it:

You keep saying that this is a claim but it's not a claim. It's a fact that there is no spec at W3C that either defines or mandates the behavior you're describing. The fact Blink behaves in the way you'd like is almost a coincidence.

anywhere on the page (be it inside a closed, or open shadow dom tree or at the top-level) this must work

I'm not at all certain that everyone would agree to that proposition. xml:href in SVG use element uses an URL and an URL has a very well defined semantics. To make the behavior you're describing work, we'd have to override its semantics so that #foo references another node within the same shadow tree with the ID value of foo. If we're making this change for all fragment URLs then that would have serious implications on anchor elements and any other SVG and HTML elements that use href and xml:href attributes. On the other hand, introducing an arbitrary inconsistency like making this semantics change only to SVG use element is also bad for the Web platform as the whole.

yGuy commented 7 years ago

OK, thanks a lot for the clarification. So I think it should be clearly communicated and stated that SVGs and shadow DOM don't work together nicely if implemented according to the current spec and that devs cannot rely on the implementations that currently do support this "against the spec". Even Anne van Kesteren thought that this feature should work according to the current spec if I interpret this comment correctly: https://github.com/w3c/webcomponents/issues/179#issuecomment-198231619 - without a clear statement how should the majority of "normal devs" understand the current situation?

SVG 'use' elements are a very important part for SVGs, at least if you use SVG to programmatically create vector graphics. So if they don't actually work in shadow DOMs that is a huge problem for shadow doms, IMHO: Shadow doms are used for creating and encapsulating complex web components. If those components cannot use sophisticated vector graphics, then this is a blocker for many component developers (like us) and they won't be adopting shadow doms, which would be a pity because they would benefit the most from shadow doms.

I understand that it may be difficult to change the spec so that this will work formally, but I think that absolutely needs to be done (and that's basically what this ticket is all about). It's almost as if you had decided not to support a rather basic feature like background colors or margins in shadow doms - people will choose to have background colors and margins over using shadow doms if that is the only way they can get background colors and margins to work. I say that if you want shadow dom to become widely adopted, this SVG use-case absolutely needs to be supported, whatever it takes. Thank you!

annevk commented 7 years ago

The problem is that SVG uses URLs for both local and non-local references and most browsers only implement the local part. In CSS at least there was a plan to make these local reference special (URLs starting with #) and that probably applies here too given it's a CSS property. @tabatkins?

It seems that hasn't really propagated to all specifications yet.

tabatkins commented 7 years ago

Oh gosh, I didn't even think about the effect of scoped-IDs on frag-references. I guess it's the same issue as dealing with @font-face-defined names inside of a shadow tree.

So yeah, frag urls are special in url() - https://drafts.csswg.org/css-values/#local-urls. They stay fragments and are always treated as "local" to the referencing document no matter what the base url is.

It's a small hop from there to specifying that, within a shadow tree, they are scoped to referring only to the IDs defined in the shadow. I'm fine with that - is that how we want to proceed? If so, I can bring it to the CSSWG and get it approved.

annevk commented 7 years ago

@tabatkins yeah, that's basically the proposal. Search within your tree for IDs not within your document.

rniwa commented 7 years ago

I don't think that solves SVG use element since it uses xml:href. Overriding its semantics inside a shadow tree is going to be quite ugly unless we're going to change it for everything else.

yGuy commented 7 years ago

:-(

Better "ugly and working" than "nice and unusable", though, IMHO.

annevk commented 7 years ago

You mean xlink:href? It seems that has very similar considerations to CSS. Also, if we forget about shadow trees, would

<html:base href="https://elsewhere.com/"/>
<svg:use xlink:href="#test"/>
<svg:blah id="test">...</svg:blah>

end up finding svg:blah or not? If it does and the base URL gets ignored I think that would be a very strong argument for having similar semantics to CSS.

rniwa commented 7 years ago

@grorg @hober

yGuy commented 7 years ago

@annevk The base Url problematic with svg:use is a huge annoyance for devs in browsers other than Chrome (see https://gist.github.com/leonderijke/c5cf7c5b2e424c0061d2 and http://kb.yworks.com/article/706/ among others): In those UAs it does not resolve and thus breaks otherwise "self-contained" svgs. In Chrome, though the base URL is currently ignored at least for the svg:use use-case.

That behavior is so annoying (you need to replace all fragment urls with absolute urls which then again would not work inside shadow doms) - for me that alone would be a reason to adjust the spec.

yGuy commented 7 years ago

Could we please raise the priority of this issue?

IMHO this issue is an absolute show-stopper for the adoption of webcomponents.

E.g.: We had to refactor our application that was using Polymer to basically get rid of all web components that used SVG. We had to pull those components to the document top-level and make them plain HTML instead of web components to make the application work in Safari. This worked for some components but was not feasible for others, where the functionality is still broken, now.

With the webcomponents shims the situation was actually better for us, but now that Safari has an implementation which does not allow using SVG with use elements the only workaround for devs is to drop web components.

Also I fear that our applications (which work great in Chrome right now) might cease to work in Chrome, too, once they decide to "stick to the spec" and cripple the (now working) SVG functionality in Chrome, too.

rniwa commented 6 years ago

What if we just added a new content attribute for the use element? e.g. src or ref or from?

annevk commented 6 years ago

@rniwa can we first clarify https://github.com/w3c/webcomponents/issues/179#issuecomment-321477375? (I think the SVG WG is receptive to adding new attributes to replace namespaced ones, but we should first figure out how the existing setup works.)

cc @AmeliaBR

AmeliaBR commented 6 years ago

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:

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, but note that this does not yet include a resolved change 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. 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, 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 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:

<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 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 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.

rniwa commented 6 years ago

Thanks for the elaborate description, @AmeliaBR!

@annevk : Sorry, yes, I meant to say xlink:href in https://github.com/w3c/webcomponents/issues/179#issuecomment-321475640

Note that WebKit doesn't support href on SVG's use element so only xlink:href works (see https://webkit.org/b/153854).

I would not be comfortable changing the definition of xlink:href just for use element. On the other hand, I expect changing the behavior of xlink:href for all cases involving shadow DOM to be even more controversial and not web/enterprise-content compatible.

Given that, I'm inclined to say that we should introduce a new SVG content attribute for use element which resolves like CSS ID.

annevk commented 6 years ago

The question is how xlink:href works today. Does it special case values starting with # or does it parse the value against a base URL?

smaug---- commented 6 years ago

It is still unclear to me whether people want inside shadow DOM to be able to (A) refer test element in light DOM, or (B) test element in shadow DOM, or (C) both?

https://github.com/w3c/webcomponents/issues/179#issuecomment-392605203 seems to hint both, so that id reference could be either within a shadow DOM, or between shadow DOM and and ancestor shadow DOM, or shadow DOM and light DOM. That would be very strange and if one implements component and has on purpose unresolved idref there (for example temporarily while some script is building the idref target), such shadow DOM idref could magically refer outside of shadow DOM. And also, other idrefs don't work that way.

http://mozilla.pettay.fi/moztests/svg_shadow.html Chrome shows red circle in first one, Nightly in second one, and I was told Safari doesn't show a red circle at all.

emilio commented 6 years ago

Note that since <svg:use> is defined to use a shadow tree, if we special-case shadow trees it's going to probably behave unexpectedly for nested <use> elements, for example.

annevk commented 6 years ago

@smaug---- I would expect that if we treat those references starting with # in a special way, #test would only refer to elements within the same tree, so you cannot get into the light from a shadow, or into a shadow from the light. That's how ID references work elsewhere already.

smaug---- commented 6 years ago

And if one uses absolute url, there wouldn't be any magic? Apparently blink applies the magic also when absolute url (pointing to the document's url) + fragment is used. And that is rather weird. The idref explicitly points to an element in light DOM, yet shadow DOM is used.

annevk commented 6 years ago

I'm not sure, having magic there might be okay too, if that's how CSS does it. I do agree it'd be a little weird.

AmeliaBR commented 6 years ago

It is still unclear to me whether people want inside shadow DOM to be able to (A) refer test element in light DOM, or (B) test element in shadow DOM, or (C) both? (@smaug---- )

Both have their use cases (which is why I suggested the "search outwards" approach).

If I had to choose one or the other, though, I'd pick (B) for web components. If a web component contains a complete, self-contained inline SVG within its shadow DOM, cross references within the shadow tree need to work as normal. Anything else basically means no inline SVG inside web components.

But if hash references in the shadow tree always resolve inside that tree, there are some consequences:


Consequence 1:

If a web page author wants to use an SVG icon in their web component that references definitions in the main document (i.e., to link from shadow to light), they would need to refer to the main document by its full URL, and deal with any complications from <base> and location changes.

Alternatively, an <svg><use xlink:href="#icon" /></svg> fragment could be defined in the light tree, and pulled into the shadow tree using a <slot>. I would assume that in this case, since the <use> was defined in the light tree, it's attributes would be evaluated in the light tree, similar to how I'd expect this jump link to still work even if I pulled it into a web component shadow widget:

<fancy-jump-link>
<a href="#section2">Next Section</a>
</fancy-jump-link>

Consequence 2:

I would expect that the same rules would apply to other (xlink:)href attributes inside the shadow DOM. So, if I wanted to generate a separate, completely shadow <a> element inside my <fancy-jump-link> that would link out to the main document, I would need to use the full document URL, including any base adjustments.

But, this may be a web compat problem of its own by now. I don't know.


Consequence 3:

We need to add some magic to <use> element shadow trees to get them to work, since nested <use> elements that were cloned from the light document need to be able to reference the light tree, to maintain web compatibility. Specifically:

The magic required to solve that is to make the URLs in the <use> element shadow tree absolute when the elements are cloned, or define a new base URL for the entire subtree. Which happens to be the magic already proposed in the spec for handling <use> elements cloned from other documents, so that's not too bad.

But xlink:href is the easy part, because it's an attribute and always attached to a specific element. So it's fairly straightforward to apply modifications to the value when the element is cloned.

The harder part will be the url(#effect) references in CSS, because CSS properties can inherit from light tree into shadow.

These also need to work for web compatibility:

Both of those are references from the shadow tree back into the light.

The following should also work (although current web compat is sketchy):

Which means you need to keep track of whether the style property was defined in the light tree and inherited into the shadow, or whether it was defined in a different document and cloned into the shadow tree.

Keeping track of the source file is consistent to how CSS URLs have traditionally been handled, but inconsistent with the new special CSS rules for hash-only URLs. It also means that you can't just think of the use-element shadow tree as having a separate base URL and have everything fall into place. The current SVG text says that the hash-only CSS URL defined in the other file would be made absolute relative to that file's address as part of the cloning process, so that once it gets to the shadow tree context it is no longer "hash-only". But that does create an extra complication for implementation.


The question is how xlink:href works today. Does it special case values starting with # or does it parse the value against a base URL? (@annevk)

For a use element in the light DOM, the xlink:href parses against the base URL. That is generally considered Not A Good Thing by web developers, as it breaks the page if you use <base>, but also if you push a new URL without using <base>. This is the same problem that prompted the new CSS rules (implemented in Chrome) for hash-only.

The current SVG 2 spec text was an attempt to work around this, by resolving the URL against the base URL, and then comparing it against the current base URL of the document to decide whether to treat it as a same-page reference or not. (But if that could be defined in a more authoritative spec, that would be an improvement, to me.)

Since the current spec text works with the base URL, it doesn't get any better or worse if we use base URLs to define shadow tree URL-resolution behavior. We'd just need to rewrite it to talk about the "tree" base URL, instead of the "document" base URL.


Note that since <svg:use> is defined to use a shadow tree, if we special-case shadow trees it's going to probably behave unexpectedly for nested <use> elements, for example. (@emilio)

Yes, indeed. We need to handle both cases, and that's not easy, which is why we're talking about adding "magic" to the use-cloning process to make it all fit together.

tabatkins commented 6 years ago

I'm generally of the opinion that:

  1. Fragids should be local to the shadow tree, like what HTML forms do.
  2. URLs should use CSS's rules, where fragment-only URLs are specially treated as always-local, and thus act like fragids and be scoped to the shadow tree.
  3. All other name-defining things (and the properties that reference them) should use my suggested resolution rules for name-defining CSS constructs, which we need to converge on for various CSS things anyway.

Ideally, tho, this would mean that SVG references would need to grow a CSS-ish reference syntax, so they could use scoped() too to refer to things defined up-tree. But that's something we can solve later.

smaug---- commented 6 years ago

http://mozilla.pettay.fi/moztests/svg_shadow.html Chrome shows red circle in first one, Nightly in second one, and I was told Safari doesn't show a red circle at all.

FWIW, Nightly changed behavior here, and is now same as Chrome. And Safari resolves #ids within Shadow DOM in non-use element case https://bugzilla.mozilla.org/show_bug.cgi?id=1483882#c3

rniwa commented 6 years ago

Hm... perhaps we should make this work just for href and not xlink:href. WebKit just added the support for href so we'd have less concerns for compatibility if we did that.

AmeliaBR commented 6 years ago

Hm... perhaps we should make this work just for href and not xlink:href.

I hope not! Authors are advised to keep using xlink:href for backwards compatibility reasons. And besides, both attributes map to the same DOM property. It would be very confusing if they behaved differently.

rniwa commented 6 years ago

@AmeliaBR, clearly there is no compatibility risk for SVG use elements inside a shadow tree since it doesn't work at all in WebKit?? I'd be concerned about changing the semantics of xlink:href just in SVG use elements.

yGuy commented 6 years ago

+1 for doing anything to make SVGs work - I have yet to see someone (a developer, not a spec writer) who prefers a standard conforming implementation where the standard says that it "must not work" over an implementation that actually works. I never thought I would say this, but I would even appreciate a new "workinghref" property that works!

-1 for not doing anything and waiting until either SVG or webcomponents or both are dead

That said - for us and our customers you did it: webcomponents are dead and we highly recommend against using them because SVG does not work. Sorry for the rant, but "years" is just too long to wait for a working implementation. Let's just hope that Angular, React and Vue and whatever will come next will never switch to webcomponent technology.

sergio91pt commented 6 years ago

@yGuy Here's an implementation, it's not that hard to workaround this issue...

if (isNativeShadow && isWebKit) {
    svg.querySelectorAll('[*|href^="#"]').forEach(node => {
        const xlinkNS = 'http://www.w3.org/1999/xlink';

        let href;
        if (node.hasAttributeNS(null, 'href')) {
            href = node.getAttributeNS(null, 'href');
        } else {
            href = node.getAttributeNS(xlinkNS, 'href');
        }

        if (href === null || !href.startsWith('#')) {
            return;
        }

        const refNode = svg.getElementById(href.slice(1));
        if (!refNode) {
            return;
        }

        const refClone = refNode.cloneNode(true);
        refClone.removeAttribute('id');

        Array.from(node.attributes).forEach(attr => {
            if (attr.localName === 'href') {
                if (attr.namespaceURI === null || attr.namespaceURI === xlinkNS) {
                    return;
                }
            }
            refClone.setAttributeNodeNS(attr.cloneNode(true));
        });

        node.parentNode.replaceChild(refClone, node);
    });
}
yGuy commented 6 years ago

@sergio91pt thanks, but this is not really helpful - it will only be water to the spec people's mills who think that the situation isn't actually as bad as it is, "now that we have a workaround". :-(

For everyone pointing to this workaround: This will not work in many cases: Don't try this on any dynamic, reasonably sized SVG. The performance is horrible, especially on iOS devices (which would require this workaround). It only works for small, static SVGs (which you could include as a regular, spec-conforming SVG image, too), but not for the dynamic use-case. And of course it does not work with nested 'use' elements, either. The easier and better workaround is to simply ditch webcomponents.

AmeliaBR commented 6 years ago

FYI, I tried gathering some author feedback via Twitter poll. Didn't get a lot of responses, but the expectation seems to be that <use href="#svg" clip-path="#web"/> should look for those references in the same shadow tree, possibly falling back to searching parent trees if there is no match in the shadow.

Web dev nerds! It's poll time again!

If you're using a shadow-DOM web component, and an element includes a # url reference, like: <use href="#svg" clip-path="#web"/>

Where would you expect the browser to look for the element with that id value?

(IDs are only unique per tree)

  • Only in that shadow tree 53%
  • Only in the main document 12%
  • Search shadow, then main 30%
  • Something else (reply) 5%

43 votes · Final results