WICG / webcomponents

Web Components specifications
Other
4.36k stars 370 forks source link

SVG use element can't reference an element within the same shadow tree #772

Open rniwa opened 5 years ago

rniwa commented 5 years ago

Because SVG's use element uses href to reference another element, its reference is always resolved against the base URI as an URL. Because there is no way to reference an element inside a shadow tree using an URL, use element can't reference an element inside a shadow tree.

This issue was split out of https://github.com/w3c/webcomponents/issues/179.

rniwa commented 5 years ago

The rough consensus at TPAC is that URLs in SVG href content attribute should use CSS's rules, where fragment-only URLs are specially treated as always-local, and thus act like fragment IDs and be scoped to the shadow tree.

rniwa commented 5 years ago

Also see https://github.com/w3c/csswg-drafts/issues/2715

rniwa commented 5 years ago

Looks like the CSS Values and Units Module Level 4 doesn't quite specify what we want. Filed https://github.com/w3c/csswg-drafts/issues/3320 to track that issue in the CSS WG.

yGuy commented 5 years ago

To make this more search engine friendly and clear for the reader:

There is no efficient workaround or polyfill for this. The only options you are left with is to either ditch browser compatibility and hope that everybody uses a working version of Chrome or Firefox or shadow DOM, or SVG.

Personal recommendation: Don't use Shadow DOM until this is fixed in the spec and in all browsers. Don't hold your breath, though; the original issue was opened almost four years ago and affects users in the real world for more than a year, now. Not using SVG or not supporting all major browsers is not a good alternative.

caridy commented 5 years ago

@yGuy my understanding of the rough consensus this is that your example (from another issue) will work fine:

<template>
    <p>You should see a black and a red circle.</p>
    <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px" viewport="0 0 100 100">
        <defs>
           <circle id="myBlackCircle"      r="10" cx="10" cy="10" fill="black"></circle>
           <circle id="myRedCircle"         r="10" cx="14" cy="14" fill="red"></circle>
        </defs>
       <use href="#myBlackCircle"></use>
       <use xlink:href="#myRedCircle"></use>
    </svg>
</template>

It certainly works fine in Chrome and FF as far AFAIK. @rniwa we should add this topic to the agenda for the next F2F meeting to see if we can consolidate that consensus.

aderaaij commented 5 years ago

@caridy This example will not work in Safari / iOS. Example: https://jsfiddle.net/wqfbkju7/

I'm not sure if that's a browser bug or if there's still lack of consensus on how to handle fragment identifiers in general.

yGuy commented 5 years ago

@aderaaij - It's the latter - everyone basically agrees that this should work, but no one seems to understand the importance this has for a potential success of webcomponents and they don't seem to be interested in actually fixing it: See #179 for the complete history of the issue - it all started 4 years ago....

rniwa commented 5 years ago

This should be working on iOS 12.2 and macOS 10.14.4 betas now. Given all major browser engines support this, the only remaining work is to update the spec accordingly.

aderaaij commented 5 years ago

@rniwa that is great news, thank you! I just found this WebKit bug report: https://bugs.webkit.org/show_bug.cgi?id=174977 so I'm guessing you're partially responsible for squashing this one. Thanks. On another note, do you have any idea if there is an actual consensus reached at W3C at this point, or did browser vendors just went ahead and implemented this one way or the other?

rniwa commented 5 years ago

@aderaaij : I think there was a rough consensus in the last TPAC about making SVG use element's reference work as well as other kinds of in-tree referencing in SVG work. So I've implemented that far but there doesn't seem to be much effort trying to update the standards so it's hard to tell to what extent we all agree.

devingfx commented 1 year ago

I can see that this question is not resolved for years...

To me, this whole decision to make shadow DOM too much cutted from outside world leads to more problems than solutions...

Why not just let it go? And make the shadow DOM features opt-in/out able ?

elem.attachShadow({
    events: 'traverse' | 'hybrid' | 'boundary'',
    baseURI: 'parent' | 'none' | 'https://...',
    css: 'traverse' | 'confine' | 'only shared' | 'only --var',
    mode: 'close' | 'open',
})
// actual elem.attachShadow would be something like 
elem.attachShadow({
    events: 'boundary'',
    baseURI: 'none',
    css: 'only --var',
    mode: 'open',
})
// and complete open DOM like if .append() would add clear DOM
const shadow = elem.attachShadow({
    events: 'traverse',
    baseURI: 'parent',
    css: 'traverse',
    mode: 'close',
})

// Defaults would be as it's defined right now for backward compatibility

Note the vocabulary here is not a spec ^^; but just to get the idea...