2

It's strange that I couldn't find anyone else reporting this problem; that makes me think perhaps I am doing something wrong.

I have a <style> tag within an SVG that contains a :hover pseudo-class, it works properly when the SVG is directly embedded into the HTML, but when I put it within a symbol and reference it with a <use> tag, the styles inside the <style> tag are not applied.

SVG Directly-embedded:

<svg width="400" height="110">
  <style>
    #myRect:hover {
      fill: red;
    }
  </style>
  <rect id="myRect" width="300" height="100" />
</svg>

Defined in a symbol, and referenced via the <use> tag.

<svg style="display: none">
  <symbol id="rectangle">
      <style>
        #myRect:hover {
          fill: red;
        }
      </style>
      <rect id="myRect" width="300" height="100" />
  </symbol>
</svg>

<svg width="400" height="110">
    <use href="#rectangle"></use>
</svg>

Why is this happening?! Seems like a weird behavior, am I missing something?!

UPDATE: As Temani Afif mentioned in the comments, this problem exists only in Chrome, Firefox seems to work as expected. (Haven't tested on any other browsers)

Arad
  • 4,010
  • 5
  • 30
  • 50
  • @TemaniAfif Ok, could you refer me to some specs or something? And **why** is it invalid?! How are you supposed to achieve a hover effect in a symbol then? – Arad Nov 01 '20 at 15:03
  • make the style outside the symbol – Temani Afif Nov 01 '20 at 15:03
  • 1
    it's seems to be a chrome bug, Firefox works fine. (or one of them is violating the spec) – Temani Afif Nov 01 '20 at 15:04
  • 2
    In the second case you are mousing over the use element not over the myRect – enxaneta Nov 01 '20 at 15:05
  • @enxaneta No, it's a Chrome issue, it works properly in Firefox, as TemaniAfif mentioned. – Arad Nov 01 '20 at 15:07
  • IDK why people downvote, understand the issue first for god's sake! – Arad Nov 01 '20 at 15:07
  • @TemaniAfif Well, if I write the styles outside of the symbol it would still not work since the `` tag creates a shadow DOM, and the elements inside of the `` tag (like the `` element) can't be accessed with CSS like that. – Arad Nov 01 '20 at 15:10
  • @GuyIncognito That's true for HTML. There is no `` tag in SVG. – Arad Nov 01 '20 at 15:11
  • 1
    Just for completeness, the spec: https://www.w3.org/TR/SVG2/struct.html#UseStyleInheritance – ccprog Nov 01 '20 at 15:20
  • @ccprog Thanks. Does that mean Chrome is violating the specs or Firefox? – Arad Nov 01 '20 at 15:24

2 Answers2

3

An alternative using CSS variables that can cross the shadow with inheritance:

use[href*="rectangle"]:hover {
  --f:red;
}
<svg style="display: none">
  <symbol id="rectangle">
      <rect style="fill:var(--f)"  width="300" height="100" />
  </symbol>
</svg>

<svg width="400" height="110">
    <use href="#rectangle"></use>
</svg>

Works without inline style:

use[href*="rectangle"]:hover {
  --f:red;
}
<svg style="display: none">
  <symbol id="rectangle">
    <style>
      rect {
        fill:var(--f);
      }
    </style>
      <rect  width="300" height="100" />
  </symbol>
</svg>

<svg width="400" height="110">
    <use href="#rectangle"></use>
</svg>
Temani Afif
  • 211,628
  • 17
  • 234
  • 311
  • Clever solution +1. But it would be inconvenient for more complex styles and animations. – Arad Nov 01 '20 at 15:18
  • @Arad I think you can also use it with complex styles. I used inline styles but you can keep the use of external styles (see the updates) – Temani Afif Nov 01 '20 at 19:13
3

This is actually an interesting case, and while Temani Afif gave the right solution, I think it is worth a few more words in a separate answer.

First off, the question is not where the <style> tag sits. It could really be anywhere. The real question is raised by the :hover selector.

<svg style="display: none">
  <symbol id="rectangle">
      <style>
        #myRect {
          fill: blue;
        }
        #myRect:hover {
          fill: red;
        }
      </style>
      <rect id="myRect" width="300" height="100" />
  </symbol>
</svg>

<svg width="400" height="110">
    <use href="#rectangle"></use>
</svg>

The previous SVG 1.1 spec had a short paragraph that said "CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree", but the SVG 2 spec dropped that sentence.

It now has a lot to say about how style inheritance works for <use> elements. but all of it concerns the question: "If there are style rules for the corresponding element (the <symbol>), how are they applied to the shadow instance (what is inside the <use>)?"

But one question I really could find no answer to is: If a pseudo-class state applies to a shadow host, can the shadow instance elements also have that state? Or, to state it more clearly: If a pointer hovers over a <use> element, does it also hover over the elements inside the shadow tree?

There are no obvious answers in CSS Selectors or CSS Scoping, to name the other two relevant specs. And while Temani Afif alludes to the second one (and what was proposed when ::shadow was removed), this is not the same: nobody tries to select into the shadow tree, it is just that the rule selects a corresponding element.

That is where Firefox answers "yes" and Chrome answers "no". Which one is the bug? Interestingly, I could not find a bug report in either of the bug trackers.

ccprog
  • 16,196
  • 3
  • 20
  • 39
  • 1
    *If a pointer hovers over a element, does it also hover over the elements inside the shadow tree?* --> I would say yes because it works with Custom Elements: https://jsfiddle.net/pq2fLg7n/ so I would vote for a bug on Chrome – Temani Afif Nov 01 '20 at 19:17
  • I didn't actually know that the problem was in fact the `:hover` pseudo-class, not the ` – Arad Nov 02 '20 at 00:38
  • 1
    The problem is that it drastically changed between [svg1.1](https://www.w3.org/TR/SVG11/struct.html#UseElement) and [svg2](https://svgwg.org/svg2-draft/struct.html#UseElement). Previously the rule was "CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree", now it is "The cloned content inherits styles from the ‘use’ element and can be the target of user events". – Kaiido Nov 07 '20 at 14:09