如何更改“svg”元素的颜色?

1169
我希望您能够使用这种技术并改变SVG颜色,但迄今为止我无法做到。我在CSS中使用了这个,但我的图片始终是黑色的,无论如何。

我的代码:

.change-my-color {
  fill: green;
}
<svg>
    <image class="change-my-color" xlink:href="https://svgur.com/i/AFM.svg" width="96" height="96" src="ppngfallback.png" />
</svg>


1
我不是SVG专家,但你尝试过将fill更改为background-color吗? - Meg
5
在SVG中,背景颜色使用“fill”属性指定,边框使用“stroke”(就像在Illustrator中一样)指定。http://www.w3.org/TR/SVG/propidx.html - Barbara
14
<img />标签内的SVG元素不会应用来自HTML文档中的CSS。 - pawel
8
现在可以实现。这里有一个简单而功能性的答案:https://dev59.com/gmEh5IYBdhLWcg3wk0Sz#53336754 - mtyson
3
你应该修改已接受的答案(查看得票最高的答案)。 - djcaesar9114
显示剩余5条评论
46个回答

1490

2020年答案

CSS滤镜适用于所有当前的浏览器

要更改任何SVG的颜色

  1. 使用<img>标签添加SVG图像。

    <img src="dotted-arrow.svg" class="filter-green"/>
    
  2. 要筛选特定颜色,请使用Codepen(点击此处打开Codepen)将十六进制颜色代码转换为CSS滤镜:

    例如,#00EE00的输出为

    filter: invert(42%) sepia(93%) saturate(1352%) hue-rotate(87deg) brightness(119%) contrast(119%);
    

    在此生成适用于任何颜色的filter

  3. 将CSS的filter添加到此类中。

    .filter-green{
        filter: invert(48%) sepia(79%) saturate(2476%) hue-rotate(86deg) brightness(118%) contrast(119%);
    }
    

11
这里需要提醒的是,这种方法在较老的浏览器版本中可能不被支持:https://developer.mozilla.org/zh-CN/docs/Web/CSS/filter#浏览器兼容性。 - Kevin Wang
159
在CodePen中提到,如果你的SVG不是黑色(我的是灰色),在过滤器列表的开头添加brightness(0) saturate(100%)将首先将其变为100%黑色,这样其他过滤器才能将其更改为正确的颜色。 - jdunning
8
此外,这个StackOverflow问题中提供了许多有关解决方案的引人入胜的背景信息,这些信息为CodePen提供了支持。 - jdunning
11
伙计,支持看起来是可接受的 https://caniuse.com/#feat=css-filters。 - Sam Doidge
24
但是你如何指定特定的颜色? - phil123456
显示剩余20条评论

533

要更改任何SVG的颜色,您可以直接通过在任何文本编辑器中打开SVG文件更改SVG代码。 代码可能看起来像下面的代码:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">

    <g>
        <path d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
                 C181.113,454.921,171.371,464.663,161.629,474.404z"/>

    /* Some more code goes on */
    </g>
</svg>

您可以观察到一些XML标记,如path、circle、polygon等。您可以通过style属性添加自己的颜色。请参考下面的示例。

<path fill="#AB7C94" d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
                        C181.113,454.921,171.371,464.663,161.629,474.404z"/>

将style属性添加到所有标签中,这样您就可以获得所需颜色的SVG。

根据Daniel的评论,我们可以直接使用填充属性而不是在style属性内部使用填充元素。


145
为什么不直接使用 fill = "#AB7C94" 属性?不确定为什么需要使用 style 属性。 - bg17aw
7
嗨丹尼尔,是的,它有效。我不知道fill可以用作属性。很抱歉我没有注意到你的评论那么长时间@bg17aw。 - Sushant Pachipulusu
5
这应该是最佳答案,因为它提供了相同的结果,但代码量要少得多。代码越少,越好的代码。 - NDi
1
我看到的问题是,如果我们需要许多不同的颜色,它会增加项目的大小并减慢页面加载速度。但是SVG通常很小。在我的情况下,添加一些图像并不是问题。但这是一个好答案。谢谢! - Dinith Rukshan Kumara
1
美观且可能是最安全的选择考虑。 - Akindele Michael
显示剩余3条评论

462

如果您想动态更改颜色:

  1. 在代码编辑器中打开SVG

  2. 将每个pathfill属性添加或重写为fill="currentColor"

  3. 现在,该SVG将采用您的字体颜色,因此您可以执行以下操作:

svg {
    color : "red";
}

40
这是真实且最简单的答案。 - Ahsan
22
你可能需要将stroke属性更改为stroke="currentColor" - marsnebulasoup
131
如果将SVG保存为文件并使用<img>标签显示,它就不起作用了。 - Niksr
21
你是如何包含SVG的,是使用内联方式还是img标签?请在回答中包含相关信息。 - racitup
17
应该补充说明,这仅适用于在HTML中内联使用SVG的情况。 - darrendev
显示剩余7条评论

346

您无法通过这种方式更改图像的颜色。如果将SVG作为图像加载,您无法使用CSS或JavaScript在浏览器中更改其显示方式。

如果要更改SVG图像,则必须使用<object><iframe>或者内联使用<svg>

如果要在页面中使用这些技术,则需要使用 Modernizr 库,您可以通过检查SVG支持并有条件地显示或不显示回退图像。然后,您可以将SVG内联并应用所需的样式。

请参阅:

#time-3-icon {
   fill: green;
}

.my-svg-alternate {
  display: none;
}
.no-svg .my-svg-alternate {
  display: block;
  width: 100px;
  height: 100px;
  background-image: url(image.png);
}
<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<path id="time-3-icon" d="M256,50C142.229,50,50,142.229,50,256c0,113.77,92.229,206,206,206c113.77,0,206-92.23,206-206
    C462,142.229,369.77,50,256,50z M256,417c-88.977,0-161-72.008-161-161c0-88.979,72.008-161,161-161c88.977,0,161,72.007,161,161
    C417,344.977,344.992,417,256,417z M382.816,265.785c1.711,0.297,2.961,1.781,2.961,3.518v0.093c0,1.72-1.223,3.188-2.914,3.505
    c-37.093,6.938-124.97,21.35-134.613,21.35c-13.808,0-25-11.192-25-25c0-9.832,14.79-104.675,21.618-143.081
    c0.274-1.542,1.615-2.669,3.181-2.669h0.008c1.709,0,3.164,1.243,3.431,2.932l18.933,119.904L382.816,265.785z"/>
</svg>

<image class="my-svg-alternate" width="96" height="96" src="ppngfallback.png" />

您可以将SVG内联。使用类名标记备用图像(my-svg-alternate):

<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<path id="time-3-icon" .../>
</svg>

<image class="my-svg-alternate" width="96" height="96" src="ppngfallback.png" />

在CSS中使用Modernizr的no-svg类(CDN:http://ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.7.2.js)检查SVG支持情况。如果没有SVG支持,SVG块将被忽略且图像将被显示,否则图像将从DOM树中移除(display: none):

.my-svg-alternate {
  display: none;
}
.no-svg .my-svg-alternate {
  display: block;
  width: 100px;
  height: 100px;
  background-image: url(image.png);
}

然后您可以更改内联元素的颜色:

#time-3-icon {
   fill: green;
}

20
嵌入式的 object SVG 无法从承载文档中进行样式设置。 - Javier Rey
2
@JavierRey 你可以通过 JavaScript 将样式注入到 object 标签的内容中。但是如果你只将它添加到承载文档的样式表中,它是不会生效的,你是对的。 - Robert Longson
3
我正在使用@manish-menaria的解决方案,它完美地运行着。 - Ryan Ellis
3
接受的答案应该更改为:https://dev59.com/gmEh5IYBdhLWcg3wk0Sz#53336754 - mtyson
5
有一种方法可以实现,只需要给svg添加fill="currentColor"属性,它就会从CSS颜色(字体颜色)中获取颜色。详见此回答https://dev59.com/gmEh5IYBdhLWcg3wk0Sz#65147574。 - justdvl
显示剩余4条评论

106

仅限具有路径信息的SVG。您不能对图像执行此操作...因为您可以更改路径的描边和填充信息,然后完成操作。就像Adobe Illustrator

因此,通过CSS,您可以覆盖路径的fill值:

path { fill: orange; }

但是,如果您想要更灵活的方式,在进行某些悬停效果时将其更改为文本,请使用:

path { fill: currentColor; }

body {
  background: #ddd;
  text-align: center;
  padding-top: 2em;
}

.parent {
  width: 320px;
  height: 50px;
  display: block;
  transition: all 0.3s;
  cursor: pointer;
  padding: 12px;
  box-sizing: border-box;
}

/***  desired colors for children  ***/
.parent{
  color: #000;
  background: #def;
}
.parent:hover{
  color: #fff;
  background: #85c1fc;
}

.parent span{
  font-size: 18px;
  margin-right: 8px;
  font-weight: bold;
  font-family: 'Helvetica';
  line-height: 26px;
  vertical-align: top;
}
.parent svg{
  max-height: 26px;
  width: auto;
  display: inline;
}

/****  magic trick  *****/
.parent svg path{
  fill: currentcolor;
}
<div class='parent'>
  <span>TEXT WITH SVG</span>
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 32 32">
<path d="M30.148 5.588c-2.934-3.42-7.288-5.588-12.148-5.588-8.837 0-16 7.163-16 16s7.163 16 16 16c4.86 0 9.213-2.167 12.148-5.588l-10.148-10.412 10.148-10.412zM22 3.769c1.232 0 2.231 0.999 2.231 2.231s-0.999 2.231-2.231 2.231-2.231-0.999-2.231-2.231c0-1.232 0.999-2.231 2.231-2.231z"></path>
</svg>
</div>


2
这是一个简单而伟大的解决方案,我已经尝试过了,对我很有效。谢谢。 - Md Abul Bashar
是的,我现在知道了,在SVG的path中使用fill,而不是在svg本身中使用。谢谢! - Fauzan Edris

68

解决方案1-编辑SVG以指向currentColor

<svg>... fill: currentColor stroke: currentColor ...</svg>

然后您可以通过CSS内容控制描边和填充的颜色:

svg {
  color: blue; /* Or any color of your choice. */
}

优点和缺点:

  • 简单且使用传统支持的CSS。

适用于:

  • 您控制SVG
  • SVG可以内联包含在HTML中。

解决方案2 - CSS mask属性

<i class="icon"></i>
  .icon {
    -webkit-mask-size: cover;
    mask-size: cover;
    -webkit-mask-image: url(https://url.of.svg/....svg);
    mask-image: url(https://url.of.svg/....svg);
    background-color: blue; /* Or any color of your choice. */
    width: 20px;
    height: 20px;
  }

}

优点和缺点

  • 相对易于使用
  • mask CSS 属性的浏览器支持是部分的。

如果符合以下情况,则适合使用:

  • SVG 是外部的,并通过 URL 包含
  • 旨在在现代已知的浏览器上使用。

解决方案3 - CSS 滤镜属性 - 固定颜色

如果事先知道颜色,可以使用 https://codepen.io/sosuke/pen/Pjoqqp 查找所需的滤镜来将 SVG 更改为所需的颜色。例如,将 svg 转换为 #00f

<img src="https://url.of.svg/....svg" class="icon">
.icon {
    filter: invert(8%) sepia(100%) saturate(6481%) hue-rotate(246deg) brightness(102%) contrast(143%);
}

如果您的原始颜色不是黑色,请在过滤器列表前加入 brightness(0) saturate(100%),先将其转换为黑色。

优点和缺点:

  • 结果与期望的颜色可能存在微小且不显著的差异。

适用于:

  • 预先知道所需的颜色。
  • 外部图像。

关于解决方案3的优缺点,值得一提的是,在复杂的SVG图像上使用多个过滤器会对性能产生巨大的负面影响。如果必须使用,也应该谨慎使用。 - umbriel
C风格的/* */是CSS中唯一有效的注释字符序列,否则后果可能是CSS内容被静默忽略。CSS验证器将报告一个错误:"7 Parse Error // Or any color of your choice. width: 20px"。 - Peter Mortensen
谢谢@PeterMortensen!! 这就是当你在Stackoverflow上编辑代码而不是在代码编辑器上时会发生的事情... - Ben Carp
1
怎么可能我喜欢这个多次!就是这样。如果原始颜色不是黑色,你真的需要先通过在前面加上“brightness(0) saturate(100%)”来转换为黑色。真的非常有帮助。 - Chidiebere Ezeokwelume

58

2
谢谢,你刚刚救了我一命。.custom-disabled > svg {filter:invert(0.2) sepia(1) saturte(0) hue-rotate(0);} 正好完成了我需要禁用图标的工作。 - roger
这个答案帮助我在鼠标悬停时改变图像的颜色,并将十六进制颜色转换为CSS滤镜。我找到了以下在线十六进制颜色到CSS滤镜转换器。 https://angel-rs.github.io/css-color-filter-generator/ https://isotropic.co/tool/hex-color-to-css-filter/ - undefined

33

在一个带有背景色的盒子元素上应用SVG遮罩将会产生以下效果:

body{ overflow:hidden; }

.icon {
  --size: 70px;
  display: inline-block;
  width: var(--size);
  height: var(--size);
  transition: .12s;
  
  -webkit-mask-size: cover;
  mask-size: cover;
}

.icon-bike {
  background: black;
  animation: 4s frames infinite linear;
  
  -webkit-mask-image: url(https://image.flaticon.com/icons/svg/89/89139.svg);
  mask-image: url(https://image.flaticon.com/icons/svg/89/89139.svg);
}

@keyframes frames {
  0% { transform:translatex(100vw) }
  25% { background: red; }
  75% { background: lime; }
  100% { transform:translatex(-100%) }
}
<i class="icon icon-bike" style="--size:150px"></i>


注意 - 在 Internet Explorer 浏览器中不支持 SVG 蒙版功能


4
非常感谢,@vsync 这是我需要的最好的 hack。 - Vixson
这很棒。然而,采用这种方法后,我们使用的是img alt字段,以实现可访问性。你有什么想法来解决这个问题吗?谢谢! - Will59
1
@Will59 - 使用ARIA规则<i role="img" aria-label="描述"> - vsync

19

最简便的方法是使用像https://icomoon.io/app/#/select这样的服务将SVG转换为字体。上传你的SVG,点击“生成字体”,将字体文件和CSS内容包含在你的网页中,然后像任何其他文本一样使用和样式化它即可。我总是这样使用它,因为这样能让样式更容易。

但正如@CodeMouse92评论的文章所提到的,图标字体会破坏屏幕阅读器的功能(可能对SEO也不利)。所以还是坚持使用SVG吧。


7
它还会干扰屏幕阅读器。请参见Seren Davies的“图标字体之死”演讲。 - CodeMouse92
图标字体对于SEO并不是坏事。不理解SEO的工作原理才是SEO的问题所在。学习Section 508、ADA和WCAG,然后你就会更好地了解如何根据规定使用字体图标。你提到的视频已经被观看了8500次,获得了111个赞。你把这当做信仰吗? - Pegues

14

要更改SVG元素的颜色,我在检查Google搜索框搜索图标时发现了一种方法:

.search_icon {
  color: red;
  fill: currentColor;
  display: inline-block;
  width: 100px;
  height: 100px;
}
<span class="search_icon">
    <svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></svg>
</span>

我使用了一个带有"display:inline-block"、高度、宽度和特定样式"color: red; fill: currentColor;"的span元素,该样式被子svg元素继承。


这是最好的答案。将SVG包装在span或div中,并对其应用fill: currentColor;是关键。 - Jeremy Caris
不敢相信没有其他人提到这个。这就是答案。 - Vahid Amiri
需要明确的是,它并不需要被包裹在 span 中,几乎任何元素都可作为包装器。 - Vahid Amiri

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