SVG 填充未在 FireFox 中应用
SVG Fill not being applied in FireFox
我似乎不明白为什么 Firefox 使用默认的 svg 填充颜色而不是 class 的填充颜色。
以下是查看 FF 检查器时的 3 个填充:
正在通过
插入 SVG
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
</svg>
它应该显示 .skip-link .icon 填充白色 (#fff) 但它实际上使用的是 #002649 的 SVG 填充;如果我将 .skip-link .icon 更改为 .skip-link svg 然后它工作正常。为什么我不能使用 class 而是明确说明元素?
我是否遗漏了一些关于 Firefox 如何填充 SVG 的明显信息? CSS 在其他浏览器中工作正常。
Robert 是正确的 <use>
并不总是应用一致。当然,当您将 SVG 用作图像时,它不知道如何应用您添加到页面的任何 CSS 规则。
但是这里还有很多其他因素可以决定元素的样式,所以举个例子可能会有帮助。
这里有一个堆栈片段来集中我们的讨论。
svg {
fill: blue;
}
a:hover svg {
fill: red;
}
.skip-link .icon {
fill: purple;
}
.green {
fill: green;
}
<a href="#" class="skip-link">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="icon" >
<def>
<text id="text" >use xlink</text>
<text id="over" class="green">use xlink override</text>
</def>
<text x="5" y="15" >Plain</text>
<use x="5" y="30" xlink:href="#text" />
<use x="5" y="50" xlink:href="#over" />
<text x="5" y="65" class="green" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>
</svg>
</a>
特异性
SVG 元素本身的样式设置有多个相互冲突的规则。决定哪个规则获胜的因素与[特异性和顺序]有关。在这种情况下,SVG 元素本身将变成紫色。例如,悬停锚规则将永远不会显示,因为它不如 .skip-link .icon
具体
继承
某些属性允许从其父项继承,但仅在未自行指定时才允许。任何规范都将覆盖继承的值。如果问题是,我的 <svg>
元素具有某种样式,为什么不将它平等地应用于所有子元素,答案很简单。子元素指定自己的值并覆盖继承的值是完全没问题的。
<text x="5" y="65" style="fill:green;" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>
使用 & Xlink
棘手的部分变成了涉及使用时会发生什么。在这种情况下,很难追踪实际应用的样式。使用将创建由 xlink
属性标识的元素的内联表示,但您不能直接访问该元素。因此,在开发人员工具中选择 use
只会显示应用于元素父元素的样式。元素本身可能会覆盖继承的属性,我们无法在开发面板中观察到它。
这里举例来说,应用使用的样式是继承自parent的。在开发者工具中,似乎获胜规则是紫色的,但这只是因为它没有考虑被拉入的元素。这是一个 soft 值,可以如果元素指定任何值,则被覆盖。
但是内联文本的全套选择器实际上看起来像这样:
具体情况
我将来建议的一件事是提供可运行的代码,其他人可以使用它来轻松重现问题,因为它可以节省大量额外的调试时间。但是,我怀疑您的具体情况是这样的:
svg {
fill: #002649;
}
a:hover svg {
fill: #8A8B8C;
}
.skip-link .icon {
fill: #FFF;
}
<a href="#" class="skip-link">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="icon" >
<def>
<svg xmlns="http://www.w3.org/2000/svg" id="menu-bag">
<rect height="100" width="100" />
</svg>
</def>
<use xlink:href="#menu-bag" />
</svg>
</a>
如果该行为是版本 56 之前的 Firefox 独有的,那是因为 #menu-bag
引用了 <symbol>
元素。
规格说重新使用 <symbol>
should be implemented as if it were replaced by a nested <svg>
。 Firefox 曾经在他们的影子 DOM 中按字面意思对待这个问题。阴影 DOM 在您的 DOM 检查器中不可见,但它受 CSS select 或
的约束
也就是说这段代码:
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
</svg>
</a>
WA 是这样实现的:
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag">
<!--Start of shadow DOM boundary-->
<svg><!-- replacement for <symbol> -->
<!-- graphics content -->
</svg>
<!--End of shadow DOM boundary-->
</use>
</svg>
</a>
svg.icon
匹配您的 .skip-link .icon
规则(正如 Kyle Mitt 指出的那样,该规则将始终优先于您的 a:hover svg
规则)。该值也由 <use>
元素继承。
然而,shadow-DOM <svg>
没有获得继承的值,因为它是直接使用 svg
规则设置样式的。当您将 selector 更改为 .skip-link svg
时,或者当您触发 a:hover svg
规则时,隐藏的内部元素将直接应用样式,因为该 SVG 也是 [= 的后代89=].
正如 Robert Longson 在评论中指出的那样,这不是 应该 工作的方式。这是 Firefox 将 <use>
元素实现为完全克隆的 DOM 树的方式的副作用,它恰好对你的 DOM 检查器隐藏了。
这是您的原始问题的 "working" 示例。也就是说,在 Chrome、Safari、Opera、Firefox 56+ 或 IE 上你会看到一个绿色圆圈,当你悬停它时它不会改变,但在版本 56 之前的 Firefox 上你会看到一个蓝色圆圈在 hover/focus.
时变为红色
svg {
fill: navy;
}
a:hover svg, a:focus svg {
fill: red;
}
.skip-link .icon {
fill: green;
}
.icon {
height: 50;
width: 50;
}
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
</svg>
</a>
<svg height="0" width="0">
<symbol id="menu-bag" viewBox="-10 -10 20 20">
<circle r="10" />
</symbol>
</svg>
那么如果你需要支持旧版本的 Firefox 怎么办?你有两个选择,其中之一你已经通过反复试验找到了:
避免使用 svg
标签设置默认样式 select 或者,依赖 <use>
元素的正常样式继承。
使用 select 或故意 select 影子-<svg>
来取消默认值,同时确保它们对其他人有预期的效果浏览器。
一种选择是使用如下规则,这将保持原始规则对其他浏览器的特异性:
.skip-link .icon, .skip-link .icon use>svg {
fill: green;
}
use>svg
selector 永远不会匹配任何 除了 与 Firefox bug,所以可以安全使用没有副作用。 (最初,我只是建议将 svg
添加到 selector 的末尾,但在某些情况下这可能会出现问题。)
在 body 或 html 标签上设置默认的 svg 填充颜色,它将作为默认值继承,但您可以使用 class.
轻松覆盖它
body {
fill: black;
}
.green {
fill: green;
}
.red {
fill: red;
}
现在只需在任何地方使用 class 颜色即可更改填充颜色。将颜色 class 添加到 svg,或添加到 span 或其他包装 svg 的元素。也适用于 Firefox。
<a href="#" class="skip-link green">
<svg>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
</svg>
</a>
<svg height="0" width="0">
<symbol id="menu-bag" viewBox="-10 -10 20 20">
<circle r="10" />
</symbol>
</svg>
基于@AmeliaBR 提供的答案的更通用的选项是简单地按照以下方式做一些事情:
svg use svg {
fill: inherit;
}
这将使阴影元素继承填充颜色。
我的情况不完全一样,但我还是分享一下。
我使用 svg 作为背景图片,就像下面的例子(谷歌搜索,不记得在哪里)。在 Firefox 中 "fill" 颜色有问题。
- 作为填充值,我不得不在RGB模式下编写它并正常工作(fill:rgb(237, 237, 237);)。
- 如果我用十六进制写入(填充:#ededed;),它不会呈现。
如果我写例如"fill: blue;"它也会正确显示。
.a-class {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none' height='130' style='background:var(--main-lt-green); fill:rgb(237, 237, 237);'><polygon points='100 0 100 10 0 10'></polygon></svg>");
background-repeat: no-repeat;
background-size: 100% 100px;
background-position-y: top;
margin-top: -100px;
padding-top: 100px;
}
我似乎不明白为什么 Firefox 使用默认的 svg 填充颜色而不是 class 的填充颜色。
以下是查看 FF 检查器时的 3 个填充:
正在通过
插入 SVG<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
</svg>
它应该显示 .skip-link .icon 填充白色 (#fff) 但它实际上使用的是 #002649 的 SVG 填充;如果我将 .skip-link .icon 更改为 .skip-link svg 然后它工作正常。为什么我不能使用 class 而是明确说明元素?
我是否遗漏了一些关于 Firefox 如何填充 SVG 的明显信息? CSS 在其他浏览器中工作正常。
Robert 是正确的 <use>
并不总是应用一致。当然,当您将 SVG 用作图像时,它不知道如何应用您添加到页面的任何 CSS 规则。
但是这里还有很多其他因素可以决定元素的样式,所以举个例子可能会有帮助。
这里有一个堆栈片段来集中我们的讨论。
svg {
fill: blue;
}
a:hover svg {
fill: red;
}
.skip-link .icon {
fill: purple;
}
.green {
fill: green;
}
<a href="#" class="skip-link">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="icon" >
<def>
<text id="text" >use xlink</text>
<text id="over" class="green">use xlink override</text>
</def>
<text x="5" y="15" >Plain</text>
<use x="5" y="30" xlink:href="#text" />
<use x="5" y="50" xlink:href="#over" />
<text x="5" y="65" class="green" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>
</svg>
</a>
特异性
SVG 元素本身的样式设置有多个相互冲突的规则。决定哪个规则获胜的因素与[特异性和顺序]有关。在这种情况下,SVG 元素本身将变成紫色。例如,悬停锚规则将永远不会显示,因为它不如 .skip-link .icon
继承
某些属性允许从其父项继承,但仅在未自行指定时才允许。任何规范都将覆盖继承的值。如果问题是,我的 <svg>
元素具有某种样式,为什么不将它平等地应用于所有子元素,答案很简单。子元素指定自己的值并覆盖继承的值是完全没问题的。
<text x="5" y="65" style="fill:green;" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>
使用 & Xlink
棘手的部分变成了涉及使用时会发生什么。在这种情况下,很难追踪实际应用的样式。使用将创建由 xlink
属性标识的元素的内联表示,但您不能直接访问该元素。因此,在开发人员工具中选择 use
只会显示应用于元素父元素的样式。元素本身可能会覆盖继承的属性,我们无法在开发面板中观察到它。
这里举例来说,应用使用的样式是继承自parent的。在开发者工具中,似乎获胜规则是紫色的,但这只是因为它没有考虑被拉入的元素。这是一个 soft 值,可以如果元素指定任何值,则被覆盖。
但是内联文本的全套选择器实际上看起来像这样:
具体情况
我将来建议的一件事是提供可运行的代码,其他人可以使用它来轻松重现问题,因为它可以节省大量额外的调试时间。但是,我怀疑您的具体情况是这样的:
svg {
fill: #002649;
}
a:hover svg {
fill: #8A8B8C;
}
.skip-link .icon {
fill: #FFF;
}
<a href="#" class="skip-link">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="icon" >
<def>
<svg xmlns="http://www.w3.org/2000/svg" id="menu-bag">
<rect height="100" width="100" />
</svg>
</def>
<use xlink:href="#menu-bag" />
</svg>
</a>
如果该行为是版本 56 之前的 Firefox 独有的,那是因为 #menu-bag
引用了 <symbol>
元素。
规格说重新使用 <symbol>
should be implemented as if it were replaced by a nested <svg>
。 Firefox 曾经在他们的影子 DOM 中按字面意思对待这个问题。阴影 DOM 在您的 DOM 检查器中不可见,但它受 CSS select 或
也就是说这段代码:
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
</svg>
</a>
WA 是这样实现的:
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag">
<!--Start of shadow DOM boundary-->
<svg><!-- replacement for <symbol> -->
<!-- graphics content -->
</svg>
<!--End of shadow DOM boundary-->
</use>
</svg>
</a>
svg.icon
匹配您的 .skip-link .icon
规则(正如 Kyle Mitt 指出的那样,该规则将始终优先于您的 a:hover svg
规则)。该值也由 <use>
元素继承。
然而,shadow-DOM <svg>
没有获得继承的值,因为它是直接使用 svg
规则设置样式的。当您将 selector 更改为 .skip-link svg
时,或者当您触发 a:hover svg
规则时,隐藏的内部元素将直接应用样式,因为该 SVG 也是 [= 的后代89=].
正如 Robert Longson 在评论中指出的那样,这不是 应该 工作的方式。这是 Firefox 将 <use>
元素实现为完全克隆的 DOM 树的方式的副作用,它恰好对你的 DOM 检查器隐藏了。
这是您的原始问题的 "working" 示例。也就是说,在 Chrome、Safari、Opera、Firefox 56+ 或 IE 上你会看到一个绿色圆圈,当你悬停它时它不会改变,但在版本 56 之前的 Firefox 上你会看到一个蓝色圆圈在 hover/focus.
时变为红色svg {
fill: navy;
}
a:hover svg, a:focus svg {
fill: red;
}
.skip-link .icon {
fill: green;
}
.icon {
height: 50;
width: 50;
}
<a href="#" class="skip-link">
<svg class="icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
</svg>
</a>
<svg height="0" width="0">
<symbol id="menu-bag" viewBox="-10 -10 20 20">
<circle r="10" />
</symbol>
</svg>
那么如果你需要支持旧版本的 Firefox 怎么办?你有两个选择,其中之一你已经通过反复试验找到了:
避免使用
svg
标签设置默认样式 select 或者,依赖<use>
元素的正常样式继承。使用 select 或故意 select 影子-
<svg>
来取消默认值,同时确保它们对其他人有预期的效果浏览器。
一种选择是使用如下规则,这将保持原始规则对其他浏览器的特异性:
.skip-link .icon, .skip-link .icon use>svg {
fill: green;
}
use>svg
selector 永远不会匹配任何 除了 与 Firefox bug,所以可以安全使用没有副作用。 (最初,我只是建议将 svg
添加到 selector 的末尾,但在某些情况下这可能会出现问题。)
在 body 或 html 标签上设置默认的 svg 填充颜色,它将作为默认值继承,但您可以使用 class.
轻松覆盖它body {
fill: black;
}
.green {
fill: green;
}
.red {
fill: red;
}
现在只需在任何地方使用 class 颜色即可更改填充颜色。将颜色 class 添加到 svg,或添加到 span 或其他包装 svg 的元素。也适用于 Firefox。
<a href="#" class="skip-link green">
<svg>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
</svg>
</a>
<svg height="0" width="0">
<symbol id="menu-bag" viewBox="-10 -10 20 20">
<circle r="10" />
</symbol>
</svg>
基于@AmeliaBR 提供的答案的更通用的选项是简单地按照以下方式做一些事情:
svg use svg {
fill: inherit;
}
这将使阴影元素继承填充颜色。
我的情况不完全一样,但我还是分享一下。 我使用 svg 作为背景图片,就像下面的例子(谷歌搜索,不记得在哪里)。在 Firefox 中 "fill" 颜色有问题。
- 作为填充值,我不得不在RGB模式下编写它并正常工作(fill:rgb(237, 237, 237);)。
- 如果我用十六进制写入(填充:#ededed;),它不会呈现。
如果我写例如"fill: blue;"它也会正确显示。
.a-class { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none' height='130' style='background:var(--main-lt-green); fill:rgb(237, 237, 237);'><polygon points='100 0 100 10 0 10'></polygon></svg>"); background-repeat: no-repeat; background-size: 100% 100px; background-position-y: top; margin-top: -100px; padding-top: 100px;
}