SVG填充不适用于FireFox

时间:2015-01-09 18:28:11

标签: css3 firefox svg

我似乎无法弄清楚为什么Firefox使用默认的svg填充颜色而不是类的填充。

以下是查看FF检查员时的3次填充:

CSS

正在通过

插入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,那么它可以正常工作。为什么我不能使用类而是显式地声明元素??

我是否遗漏了一些关于Firefox如何填充SVG的明显内容?这个CSS在其他浏览器中运行良好。

5 个答案:

答案 0 :(得分:37)

如果该行为在版本56之前是Firefox独有的,那是因为#menu-bag引用了<symbol>元素。

规格说重新使用<symbol> should be implemented as if it were replaced by a nested <svg>。 Firefox过去常常在他们的影子DOM中对待它。阴影DOM在DOM检查器中不可见,但它受CSS选择器的限制。

这意味着这段代码:

<a href="#" class="skip-link">
    <svg class="icon">
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
    </svg>
</a>

WAs的实施方式如下:

<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规则设置样式。当您将选择器更改为.skip-link svg或触发a:hover svg规则时,隐藏的内部元素将直接应用样式,因为该SVG也是链接的后代。

正如Robert Longson在评论中指出的那样,假设的工作原理并非如此。这是Firefox将<use>元素实现为完整克隆DOM树的方式的副作用,这些DOM树恰好隐藏在DOM检查器中。

这是&#34;工作&#34;原始问题的例子。也就是说,在Chrome,Safari,Opera,Firefox 56+或IE上,您会看到一个绿色圆圈,当您将其悬停时,它不会被改变,但在版本56之前的Firefox上,您将看到一个蓝色圆圈悬停/焦点时红色。

&#13;
&#13;
svg {
    fill: navy;
}
a:hover svg, a:focus svg {
    fill: red;
}
.skip-link .icon {
    fill: green;
}
.icon {
    height: 50;
    width: 50;
}
&#13;
 <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>
&#13;
&#13;
&#13;

那么如果您需要支持旧版本的Firefox,该怎么做?您有两种选择,其中一种已经通过反复试验找出:

  1. 避免使用svg标记选择器设置默认样式,并依赖<use>元素的正常样式继承。

  2. 使用有意选择阴影的选择器 - <svg>来取消默认值,同时确保它们在其他浏览器上具有预期效果。

  3. 一种选择是使用如下规则,这将保持原始规则对其他浏览器的特异性:

    .skip-link .icon, .skip-link .icon use>svg {
        fill: green;
    }
    

    use>svg选择器永远不会将以外的任何内容与Firefox bug匹配,因此使用时没有副作用是安全的。 (最初,我只是建议在选择器的末尾添加svg,但在某些情况下这可能会有问题。)

答案 1 :(得分:3)

基于@AmeliaBR提供的答案,更通用的选择是简单地做一些事情:

svg use svg { 
    fill: inherit;
}

将使阴影元素继承填充颜色。

答案 2 :(得分:2)

罗伯特是正确的,<use>并不总是一致地应用。当然,当您将SVG用作图像时,它不知道如何应用您已添加到页面中的任何CSS规则。

但是这里还有很多其他的东西可以决定元素的风格,所以一个例子可能会有所帮助。

这是一个用于讨论的堆栈片段。

&#13;
&#13;
svg {
  fill: blue;
}
a:hover svg {
  fill: red;
}
.skip-link .icon {
  fill: purple;
}

.green {
  fill: green;
}
&#13;
<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>
&#13;
&#13;
&#13;

特异性

SVG元素本身的样式有几个相互冲突的规则。决定哪条规则获胜的因素与[特异性和顺序]有关。在这种情况下,SVG元素本身将以紫色结束。例如,悬停锚定规则将永远不会显示,因为它的特定性不如.skip-link .icon

SVG

继承

某些属性允许从父级继承,但仅限于未指定的属性。任何规范都将覆盖继承的值。如果问题是,我的<svg>元素具有某种风格,为什么它不能同等地应用于所有子元素,答案很简单。对于子元素来说,指定自己的值并覆盖继承的值是完全正确的。

<text x="5" y="65" style="fill:green;" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>

使用&amp;的xlink

棘手的部分成为涉及使用时发生的事情。在这种情况下,可能很难跟踪正在应用的实际样式。使用将创建由xlink属性标识的元素的内联表示,但您无法直接访问此元素。因此,在开发人员工具中选择use只会显示应用于元素父级的样式。元素本身可能会覆盖继承的属性,我们无法在开发面板中观察它。

例如,这里应用的样式是从父级继承的。在开发人员工具中,似乎获胜规则是紫色的,但这只是因为它没有考虑被拉入的元素。这是一个可以被覆盖的 soft 值如果元素指定任何值。

use

但是内联文本的完整选择器实际上看起来像这样:

text

具体情况

我将来建议的一件事是提供可运行代码,其他人可以使用它来轻松重现问题,因为它可以节省大量额外的调试时间。但是,我怀疑你的确切情况正在发生:

&#13;
&#13;
svg {
  fill: #002649;
}
a:hover svg {
  fill: #8A8B8C;
}
.skip-link .icon {
  fill: #FFF;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

在body或html标记上设置默认的svg填充颜色,它将作为默认值继承,但您只需使用类就可以轻松覆盖它。

body {
    fill: black;
}
.green {
    fill: green;
}
.red {
    fill: red;
}

现在只需在任何地方使用颜色类来更改填充颜色。将颜色类添加到svg,或包含svg的span或其他元素。也适用于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>

答案 4 :(得分:0)

我的情况并不完全相同,但我还是同意。 我正在使用svg作为背景图像,如下面的示例(用谷歌搜索,不记得在哪里)。并且在Firefox中,“填充”颜色存在问题。

  • 作为填充值,我必须以RGB模式编写它并正常工作(fill:rgb(237,237,237);)。
  • 如果我用十六进制(fill:#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;
    

    }