Open emilio opened 6 years ago
The lack of browser interop on this and similar cases is related to the changes between SVG 1.1 and SVG 2 (there's a long note & example in the spec describing the difference).
So I don't think the problem is a lack of clarity in the spec. It's a lack of conforming implementations. Unfortunately, Firefox is the only browser team so far that has made an effort to standardize on the SVG 2 definitions -- and it had never matched the SVG 1.1 definitions in the first place.
The changes were made to be consistent with shadow DOM style handling in general, and to handle previously-undefined issues with dynamic styles (e.g., hover effects). With the decision to move to a closed shadow tree, we can re-incorporate a little bit of "magic" special behavior, but we would still need a clear specification of how to handle all the edge cases. If the other browser teams don't want to adopt the current spec, someone needs to write out an alternative proposal.
Note that even with a closed shadow tree, you can observe it if you allow <foreignObject>
with custom elements inside... I'll file another issue about <foreignObject>
and <svg:use>
.
I propose that document rules don't apply to cross-document <svg:use>
elements. I think the model can be sound and efficient with that.
While discussing this, we also should re-assess the same-document style matching rules.
Firefox now matches the SVG 2 spec in that case (only matching styles with selectors that can match in the cloned shadow tree fragment), but then gets bug reports from authors who are confused why their CSS selectors aren't matching, when they work in other browsers (from June 2017, from October 2018).
We need to either get commitments from other browser teams to move to the shadow DOM model for style matching, or we need to spec the "clone the cascaded style" approach & figure out all the details that SVG 1 never defined.
The SVG Working Group just discussed svg:use subtrees
.
I propose that document rules don't apply to cross-document
<svg:use>
elements. I think the model can be sound and efficient with that.
I'm tempted to agree.
A simpler option would be: any <style>
element or <html:link>
element that is a child of the cloned element gets cloned (just like any other child elements) & then acts as normal inside the Shadow DOM. That means that authors could use selector-based style rules and other advanced CSS features (media queries, keyframe animations) in their external files. By using a linked stylesheet, they could even share styles between icons in the file without repeating the code in each symbol, although it would require an extra file download. But, no styles need to be processed before cloning, only simple XML parsing.
The SVG Working Group just discussed Styling and Use Element shadow trees
.
I don't think we could implement the thing described above in Gecko without massive hacks or performance regressions.
@Emilio Thanks for the input. Do you see another way how we could keep backwards compatibility as much as possible? (Apply selector matches from outside of shadow tree.)
@tabatkins It would also be great to hear your feedback to <use>
based on web components with the minuted issue of selector matches from outside the shadow tree inside into the shadow tree.
For reference, at https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/SVG_and_CSS there is an example which is applying :hover
rules to elements referenced by <use>
elements.
I have just fixed that example, because it previously only used direct selectors (which I kept for now, as they worked in older versions of Firefox, but they may get removed), i.e. they matched the elements as if they were placed inside the <use>
elements (see https://github.com/mdn/sprints/issues/1987).
From an author point of view, applying all rules as if the elements were not referenced via <use>
elements is the expected behavior. It feels awkward when rules that normally apply to elements do not apply to them when they are referenced.
Sebastian
From an author point of view, applying all rules as if the elements were not referenced via
That's not the semantics of SVG 1. The semantics of SVG one mean that for this test-case:
<!doctype html>
<style>
rect {
fill: red;
}
rect:hover {
fill: green;
}
</style>
<svg width=300 width=300>
<g id="canvas">
<rect width=100 height=100></rect>
</g>
<use x=200 y=0 href="#canvas"></use>
</svg>
For SVG 1, you get two green squares when you hover over the square to the right.
For SVG 2, it behaves as you expect.
I think that implementing :host-context()
would solve a lot of the problems with firefox's approach as it allows selectors that span shadow DOM to be specified.
:host-context()
is pretty bad, generally... see https://github.com/w3c/csswg-drafts/issues/1914.
See my comment there for an alternate proposal
Another alternative would be to add part attributes to sub-components of a use that need to be styled, exposing them as pseudo-elements of the parent element.
@progers @fsoder @rniwa Any comment from WebKit and Blink?
I think that we (Blink) would ultimately like to implement the semantics specced in SVG2, but given the feedback from authors, it would be good to make sure that their use cases can be addressed in a way that is satisfactory for them.
(This comment would also apply to #367)
Implementing the SVG2 semantics could vastly simplify part of the blink animations stack (a fair bit of it is there to clean up clobbered styles on original elements when they get reparented to the clone's parent for styling. The ::part selector can allow selectors traversing shadow dom, simply requiring part attributes to be set on the originals.
I don't know if they are related, but I had a funky problem using <use>
with external SVG:
extern.svg
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="square">
<g class="inside-use">
<rect width="100" height="100"/>
</g>
</g>
</defs>
</svg>
page.html
<style>
.inside-use {
fill: red;
}
.shape .inside-use {
fill: green;
}
</style>
<svg viewBox="0 0 100 100" class="shape">
<use xlink:href="extern.svg#square"></use>
</svg>
Currently, the path .inside-use
matches the rect and makes it red.
But it doesn't notice that, I want to access the rect when it's inside the shape
class.
Because .shape .inside-use
isn't valid for the shadow content.
The goal is to color the different parts (in this example: inside-use
) depending on the class of the outer svg
tag
https://svgwg.org/svg2-draft/struct.html#UseStyleInheritance says:
I don't think that's reasonable if the referenced element is in another document, since it means that base URIs should differ and such, and that itself means that the sheets should be reparsed, which is not acceptable.
Instead, what everyone seems to do is that document rules apply to the elements in the
<use>
shadow tree. Which is itself a bit of a hack. Indeed, everyone but Firefox don't implement selector-matching correctly, and they just seem to return the style of the referenced element.For example, this should show green, but shows red in WebKit, Edge and Blink: