Why doesn't :hover work inside of a <symbol> in SVG? (In Chrome) [duplicate]

穿精又带淫゛_ 提交于 2021-01-27 20:32:11

问题


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)


回答1:


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.




回答2:


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>


来源:https://stackoverflow.com/questions/64633294/why-doesnt-hover-work-inside-of-a-symbol-in-svg-in-chrome

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!