为什么:hover无法在SVG中的<symbol>内部工作? 在Chrome中

问题描述

奇怪的是我找不到其他人报告此问题;这让我觉得也许我做错了。

我在包含<style>伪类的SVG中有一个:hover标记,当SVG直接嵌入HTML时,但是当我将其放在符号和引用中时,它可以正常工作带有<use>标签标签,则不会应用<style>标签内的样式。

SVG直接嵌入:

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

以符号定义,并通过<use>标记进行引用。

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

为什么会这样?似乎是一种怪异的行为,我错过了什么吗?!

更新:正如注释中提到的Temani Afif一样,此问题仅存在于Chrome中,Firefox似乎可以正常工作。 (尚未在其他任何浏览器上进行测试)

解决方法

这实际上是一个有趣的案例,尽管Temani Afif提供了正确的解决方案,但我认为在一个单独的答案中再说几句话是值得的。

首先,问题不在于<style>标签所在的位置。它可能真的在任何地方。真正的问题是由:hover选择器提出的。

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

先前的SVG 1.1 spec有一小段文字说“ CSS2选择器不能应用于(从概念上来说)克隆的DOM树”,但是SVG 2 spec删除了该句子。

关于<use>元素的样式继承如何工作,现在有很多话要说。但所有这些都涉及一个问题:“如果corresponding element<symbol>有样式规则,如何将它们应用于shadow instance({{1}内部是什么) })?”

但是我确实找不到答案的一个问题是:如果伪类状态适用于shadow host,那么影子实例元素也可以具有该状态吗?声明得更清楚:如果指针悬停在<use>元素上,它是否也悬停在阴影树内的元素上?

CSS SelectorsCSS Scoping中没有明显的答案来命名其他两个相关规范。尽管Temani Afif提到了第二个(以及::shadow was removed时提出的内容),但这并不相同:没有人尝试选择阴影树,只是规则选择了一个相应的元素。>

那是Firefox回答“是”而Chrome回答“否”的地方。错误是哪一个?有趣的是,我在两个错误跟踪器中都找不到错误报告。

,

使用CSS变量的另一种选择可以继承继承性的阴影:

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>

没有内联样式的作品:

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>