SVG精灵中的多个颜色

8

我有一个如下所示的SVG精灵。

在使用<use>标签技术时,似乎无法从CSS访问SVG的各个部分。

我知道通过使用fill: currentColor(请参见#icon-two-parts符号中的.path1),可以通过同时使用colorfill值从CSS向同一SVG的不同部分应用两种不同的颜色。

在以这种方式使用SVG时,是否有任何方法可以将多于两种颜色应用于同一元素?

例如,是否可以将四个颜色应用于#icon-four-part符号中的四个路径?

div {
    display: inline-block;
}

.icon {
  display: inline-block;
  width: 80px;
  height: 40px;
  fill: currentColor;
}

.icon-one-part {
    color: green;
}

.icon-two-part {
    color: green;
    fill: red;
}
<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <symbol id="icon-one-part" viewBox="0 0 670 1024">
        <title>icon-one-part</title>
        <path class="path1" d="M355.486 512l-343.355-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.362-105.551c16.148-15.833 42.023-15.833 58.171 0l479.823 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.862 471.473c-16.108 15.833-41.984 15.833-58.171 0l-107.362-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.394-337.408z"></path>
    </symbol>

    <symbol id="icon-two-part" viewBox="0 0 1339 1024">
        <title>icon-two-part</title>
        <path class="path1" fill="currentColor" d="M314.092 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.513c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.447z"></path>
        <path class="path2" d="M1025.024 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
    </symbol>
    
    <symbol id="icon-four-part" viewBox="0 0 2272 1024">
        <title>icon-four-part</title>
        <path class="path1" d="M777.413 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.823-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.394 337.408z"></path>
        <path class="path2" d="M1488.384 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
        <path class="path3" d="M314.092 512l343.355 337.408c16.148 15.911 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.408z"></path>
        <path class="path4" d="M1958.203 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.236 0-57.147l343.355-337.408z"></path>
    </symbol>
</defs>
</svg>

<div>
    <svg class="icon icon-one-part"><use xlink:href="#icon-one-part"></use></svg>
</div>
<div>
    <svg class="icon icon-two-part"><use xlink:href="#icon-two-part"></use></svg>
</div>
<div>
    <svg class="icon icon-four-parts"><use xlink:href="#icon-icon-four-part"></use></svg>
</div>


为什么不使用普通的类选择器,像这样:链接 - Harry
请查看规格5.6 'use'元素:“*对于支持使用CSS进行样式设置的用户代理,将引用元素在非公开DOM树中的概念深度克隆也会复制由于CSS级联在引用元素及其内容上产生的任何属性值。可以将CSS2选择器应用于原始(即引用)元素,因为它们是正式文档结构的一部分。不能将CSS2选择器应用于(概念上)克隆的DOM树,因为其内容不是正式文档结构的一部分。” - insertusernamehere
<use>标签用于创建相同的副本。如果这不是您想要的用例,那么<use>并不是正确的答案。 - Robert Longson
3个回答

6
事实上,<use>元素是一个引用,它将指向的内容克隆到影子DOM中。它不是一个占位符,也不会被SVG定义替换掉。这就是为什么您可以为符号定义本身设置样式,而不是图标。样式定义会传播到图标,就像任何CSS属性一样。祖先不知道子级,但可继承的样式仍然会被传播...
但是我们想要每个路径填充不同的颜色,而不改变其他实例,并且我们希望在必要时能够覆盖它。
为了做到这一点,我们可以使用CSS变量。
CSS变量在规则集内声明,就像任何其他属性一样。然后,您将其声明为自身或任何子属性的值,它将被继承
让我们将这个概念应用于我们的SVG元素:

div {
    display: inline-block;
    margin-bottom: 20px;
}

.icon {
  display: inline-block;
  width: 80px;
  height: 40px;
  fill: currentColor;
}

.icon-one-part.green {
  --color-1: green;
}
.icon-one-part.red {
  --color-1: red;
}

.icon-two-part.style1 {
  --color-1: #ff9900;
  --color-2: #78ae90;
}
.icon-two-part.style2 {
  --color-1: #2124af;
  --color-2: #ef5b59;
}

.icon-four-part.style1 {
  --color-1: #FB7C1F;
  --color-2: #F38D68;
  --color-3: #FB7C1F;
  --color-4: #F38D68;
}
.icon-four-part.style2 {
  --color-1: #007978;
  --color-2: #23518C;
  --color-3: #83B692;
  --color-4: #4AA0CF;
}
<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <symbol id="icon-one-part" viewBox="0 0 670 1024">
        <title>icon-one-part</title>
        <path class="path1" fill="var(--color-1)" d="M355.486 512l-343.355-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.362-105.551c16.148-15.833 42.023-15.833 58.171 0l479.823 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.862 471.473c-16.108 15.833-41.984 15.833-58.171 0l-107.362-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.394-337.408z"></path>
    </symbol>

    <symbol id="icon-two-part" viewBox="0 0 1339 1024">
        <title>icon-two-part</title>
        <path class="path1" fill="var(--color-1)" d="M314.092 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.513c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.447z"></path>
        <path class="path2" fill="var(--color-2)" d="M1025.024 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
    </symbol>
    
    <symbol id="icon-four-part" viewBox="0 0 2272 1024">
        <title>icon-four-part</title>
        <path class="path1" fill="var(--color-1)" d="M777.413 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.823-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.394 337.408z"></path>
        <path class="path2" fill="var(--color-2)" d="M1488.384 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
        <path class="path3" fill="var(--color-3)" d="M314.092 512l343.355 337.408c16.148 15.911 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.408z"></path>
        <path class="path4" fill="var(--color-4)" d="M1958.203 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.236 0-57.147l343.355-337.408z"></path>
    </symbol>
</defs>
</svg>

<div>
    <svg class="icon icon-one-part green"><use xlink:href="#icon-one-part"></use></svg>
</div>
<div>
    <svg class="icon icon-one-part red"><use xlink:href="#icon-one-part"></use></svg>
</div>
<br>

<div>
    <svg class="icon icon-two-part style1"><use xlink:href="#icon-two-part"></use></svg>
</div>
<div>
    <svg class="icon icon-two-part style2"><use xlink:href="#icon-two-part"></use></svg>
</div>
<br>

<div>
    <svg class="icon icon-four-part style1"><use xlink:href="#icon-four-part"></use></svg>
</div>
<div>
    <svg class="icon icon-four-part style2"><use xlink:href="#icon-four-part"></use></svg>
</div>

我们不必为所有CSS变量声明颜色。相反,我们可以声明一个单独的 fill,因为CSS变量未定义,它将退回到这个 fill 声明。
我们还可以对CSS变量应用默认值:var(--color-1, red),避免为每个图标声明默认颜色。
最重要的是,CSS变量现在与大多数现代浏览器兼容了!

4

您可以样式化符号定义本身。例如:

#icon-one-part {
    fill: green;
}

#icon-two-part .path1 {
    fill: green;
}
#icon-two-part .path2 {
    fill: red;
}

但是,如果你需要重复使用同一个图标,并且每个实例的颜色都不同,那么你只能使用currentColor技术。


3
是的,这就是问题所在。我需要能够单独地为每个符号实例设置样式。哦,好吧,内联SVG看起来是最好的解决方案。虽然我一直试图避免使用它。 - Turnip

2
除了ManUtopiK的CSS自定义属性方法外,您还可以通过混合color(通过currentcolor)和带有不透明度的fill地址的SVG元素来创建第三种颜色。 演示(Codepen项目) | 详细解释(Twitter线程) 此外,您还可以使用stroke来提供3种以上可寻址颜色,如果您的精灵可以由仅描边 (fill: none)和仅填充 (stroke: none)元素组成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接