img src SVG使用CSS更改样式


373

html

<img src="logo.svg" alt="Logo" class="logo-img">

的CSS

.logo-img path {
  fill: #000;
}

上面的svg加载并且是本地的,fill: #fff但是当我使用上面的svg css尝试将其更改为黑色时,它并没有改变,这是我第一次使用SVG,我不确定为什么它不起作用。


25
您不能那样影响SVG 图像 ...仅内联SVG元素
Paulie_D 2014年


在这里检查我的答案以使用SVG和CSS的内容。stackoverflow.com/questions/11978995/...
本杰明

Answers:


154

如果您的目标只是更改徽标的颜色,而不必使用CSS,则不要使用以前的答案所建议的javascript或jquery。

要精确回答原始问题,只需:

  1. logo.svg在文本编辑器中打开。

  2. 寻找fill: #fff并替换为fill: #000

例如,logo.svg在文本编辑器中打开时,您可能看起来像这样:

<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
  <path d="M0 0h24v24H0z" fill="none"/>
  <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="#fff"/>
</svg>

...只需更改填充并保存。


6
...,如果没有“填充”,则可以将其添加到pathcircle项目中<path fill="#777777" d="m129.774,74.409c-5.523,...
SaeX

1
如果我的徽标的页眉有一种颜色,页脚有另一种颜色怎么办?
rubens.lopes

。@ ruben.lopes两个不同的文件或两个不同的内联将是最简单的
Rowe Morehouse

11
您还可以使用,fill="currentColor"然后color在父元素css-tricks.com/cascading-svg-fill-color上使用
Serge,

10
显然这是可能的,并不是真正有用的答案。
Timmmm

102

您可以将SVG设置为蒙版。这样,设置背景颜色将充当您的填充颜色。

的HTML

<div class="logo"></div>

的CSS

.logo {
    background-color: red;
    -webkit-mask: url(logo.svg) no-repeat center;
    mask: url(logo.svg) no-repeat center;
}

JSFiddle: https
: //jsfiddle.net/KuhlTime/2j8exgcb/ MDN:https : //developer.mozilla.org/zh-CN/docs/Web/CSS/mask

请检查您的浏览器是否支持此功能:https : //caniuse.com/#search=mask


3
因此,除了内部网站之外,其他任何东西都无法使用。
亨里克·文德尔博

9
截至2016
。– Gajus's

1
对于此处所述的情况,这是一个了不起的解决方案,在CSS中使用数据uris之外的任何内容都有些麻烦。谢谢!
加尔·加西亚

3
它不起作用。它说mask是一个invalid property value。我正在铬测试。
Eren555

1
@MadMac我正在运行相同版本的Chrome,但是我无法复制该行为。是您尝试过的JSFiddle还是您的代码?
安德烈·库尔曼


30

2018年:如果您想要动态颜色,不想使用javascript且不需要嵌入式SVG,请使用CSS变量。适用于Chrome,Firefox和Safari。编辑:和边缘

<svg>
    <use xlink:href="logo.svg" style="--color_fill: #000;"></use>
</svg>

在你的SVG,替换的任何实例style="fill: #000"style="fill: var(--color_fill)"


1
浏览器对此有什么支持
Kevin Goedecke '18

@KevinGoedecke Chrome,Firefox,Safari和Edge
北美

4
似乎SVG 2中
vsync

5
@northamerican-与其他stackoverflow答案的链接无关,因为“证明”不相关。任何人都可以在该平台上编写任何内容。MDN:"This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped"
vsync

8
似乎xlink:href已不赞成href。因此,这可能仍然有效。
本杰明·因塔尔

20

首先,您必须将SVG注入HTML DOM。

有一个名为SVGInject的开源库可以为您完成此操作。它使用该onload属性触发注入。

这是使用SVGInject的一个最小示例:

<html>
  <head>
    <script src="svg-inject.min.js"></script>
  </head>
  <body>
    <img src="image.svg" onload="SVGInject(this)" />
  </body>
</html>

加载图像后,onload="SVGInject(this)将触发注入,并且该<img>元素将被src属性中提供的SVG文件的内容替换。

它解决了SVG注入的几个问题:

  1. 可以隐藏SVG,直到完成注射。如果在加载期间已应用样式,则这很重要,否则会导致短暂的“未样式化内容闪烁”。

  2. <img>元素自动注入自己。如果您动态添加SVG,则不必担心再次调用注入函数。

  3. 如果将SVG多次注入,则将随机字符串添加到SVG中的每个ID,以避免在文档中多次具有相同的ID。

SVGInject是纯Javascript,可与所有支持SVG的浏览器一起使用。

免责声明:我是SVGInject的合著者


3
这是最直接的答案。我在Chrome,Firefox和Edge中对其进行了测试,并且效果很好。
塞巴斯蒂安·洛里昂

15

@Praveen的回答很可靠。

我无法在工作中响应它,所以我为此创建了一个jquery悬停功能。

的CSS

.svg path {
   transition:0.3s all !important;
}

JS / jQuery

// code from above wrapped into a function
replaceSVG();

// hover function
// hover over an element, and find the SVG that you want to change
$('.element').hover(function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#CCC');
}, function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#3A3A3A');
});

1
如果SVG首先是内联的,这不是唯一可行的方法吗?
Daniel Thompson

是的,但是,如果您要处理许多SVG文件或定期更新它们,则很难管理。
Matt Wujek

15

为什么不使用一个或多个svg图像创建webfont,将webfont导入css,然后仅使用css color属性更改字形的颜色?不需要JavaScript


5
如果您的svg包含多个不同颜色的元素,则此解决方案会变得非常棘手(插入了多个元素)。
kakaja

1
@kakaja这仅适用于其中具有1种颜色的矢量图像的解决方案。看到bpulecio的回答更多细节
外国佬

1
因为图标不是文本。字体用于文本。SVG用于图标。
LazarLjubenović18年

2
@LazarLjubenović-技术上来说,文本是由符号字符组成的,图标也是符号,因此这就是为什么许多人使用图标字体都不会出现问题的原因。就像创建“另一种”文字语言一样。普通话也使用“图标”而不是字母,在人类中使用图标作为“文本”并不少见
vsync

1
尽管这听起来是一个有趣的解决方案,但我确实建议将答案详细说明为“如何做”而不是“为什么不做”
YakovL

15

该答案基于答案https://stackoverflow.com/a/24933495/3890888,但此处使用的脚本是纯JavaScript版本。

您需要使SVG成为嵌入式SVG。您可以通过svg在图像中添加一个类来使用此脚本:

/*
 * Replace all SVG images with inline SVG
 */
document.querySelectorAll('img.svg').forEach(function(img){
    var imgID = img.id;
    var imgClass = img.className;
    var imgURL = img.src;

    fetch(imgURL).then(function(response) {
        return response.text();
    }).then(function(text){

        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(text, "text/xml");

        // Get the SVG tag, ignore the rest
        var svg = xmlDoc.getElementsByTagName('svg')[0];

        // Add replaced image's ID to the new SVG
        if(typeof imgID !== 'undefined') {
            svg.setAttribute('id', imgID);
        }
        // Add replaced image's classes to the new SVG
        if(typeof imgClass !== 'undefined') {
            svg.setAttribute('class', imgClass+' replaced-svg');
        }

        // Remove any invalid XML tags as per http://validator.w3.org
        svg.removeAttribute('xmlns:a');

        // Check if the viewport is set, if the viewport is not set the SVG wont't scale.
        if(!svg.getAttribute('viewBox') && svg.getAttribute('height') && svg.getAttribute('width')) {
            svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
        }

        // Replace image with new SVG
        img.parentNode.replaceChild(svg, img);

    });

});

然后,如果您这样做:

.logo-img path {
  fill: #000;
}

或许:

.logo-img path {
  background-color: #000;
}

JSFiddle:http : //jsfiddle.net/erxu0dzz/1/


1
很棒..作品。另外,如果我们的页面有多个svg,则需要将获取块放入IIFE。
Sandeep Sharma

1
大!与ES6兼容。如果您不关心IE 9,甚至可以使用:parser.parseFromString(text, "image/svg+xml");
ChristoKiwi '17

在iOS 9.3.5的UIWebView中不起作用。我认为这可能是由于fetch在10.1(Safari.mozilla.org/en-US/docs/Web/API/Fetch_API)中将其添加到Safari中所致。上面的jQuery版本确实有效。
Maria-Ines Carrera

7

使用滤镜转换为任何颜色。

我最近找到了这种解决方案,希望有人可以使用它。由于该解决方案使用滤镜,因此可以用于任何类型的图像。不只是svg。

如果您只想更改单色图像,则可以在某些滤镜的帮助下完成此操作。当然,它也适用于多色图像,但是您不能指定特定的颜色。只有整个图像。

滤镜来自“ 如何仅使用CSS滤镜将黑色转换为任何给定颜色”中建议的脚本。 如果要将白色更改为任何颜色,可以调整每个滤镜的反转值。

.startAsBlack{
  display: inline-block;
  width: 50px;
  height: 50px;
  background: black;
}

.black-green{
  filter: invert(43%) sepia(96%) saturate(1237%) hue-rotate(88deg) brightness(128%) contrast(119%);
}

.black-red{
  filter: invert(37%) sepia(93%) saturate(7471%) hue-rotate(356deg) brightness(91%) contrast(135%);
}

.black-blue{
  filter: invert(12%) sepia(83%) saturate(5841%) hue-rotate(244deg) brightness(87%) contrast(153%);
}

.black-purple{
  filter: invert(18%) sepia(98%) saturate(2657%) hue-rotate(289deg) brightness(121%) contrast(140%);
}
Black to any color: <br/>
<div class="startAsBlack black-green"></div>
<div class="startAsBlack black-red"></div>
<div class="startAsBlack black-blue"></div>
<div class="startAsBlack black-purple"></div>


4

为了扩展@gringo答案,可以使用其他答案中描述的Javascript方法,但是需要用户下载不必要的图像文件,并且IMO会使代码膨胀。

我认为更好的方法是将所有1色矢量图形迁移到webfont文件。我过去曾使用过Fort Awesome,它将您的SVG格式自定义图标/图像以及您可能使用的任何第三方图标(Font Awesome,Bootstrap图标等)组合到单个webfont文件中的效果非常好用户必须下载。您也可以对其进行自定义,因此仅包含您正在使用的第三方图标。这样可以减少页面必须发出的请求数量,并且可以减轻页面的整体重量,尤其是如果您已经包含任何第三方图标库的话。

如果您喜欢面向开发者的选项,可以使用Google“ npm svg webfont”,并使用最适合您的环境的节点模块之一。

一旦完成了这两个选项中的任何一个,就可以通过CSS轻松更改颜色,并且很可能在此过程中加快了网站速度。


您应该尝试SVG精灵。以我的经验,网络字​​体在浏览器版本之间存在随机问题。试试这个:fontastic.me-但是使用SVG sprite版本-看看您的想法。:)
sheriffderek

4

如果您只是在实色和黑白之间切换图像,则可以将一个选择器设置为:

{filter:none;}

另一个为:

{filter:grayscale(100%);}


2

您遇到的主要问题是您正在从<img>标记中导入svg,这将隐藏SVG结构。

您需要将<svg>标记与结合使用<use>以获得理想的效果。要使其正常工作,您需要id在SVG文件中<path id='myName'...>提供要使用的路径,然后才能从<use xlink:href="#myName"/>标记中检索它们。尝试下面的片段。

请注意,#如果要从外部源加载SVG (而不是将其嵌入HTML),则可以在片段之前放置任何URL 。同样,通常您不指定CSS的填充。最好考虑fill:"currentColor"在SVG本身中使用。然后,将使用相应元素的CSS颜色值。


2

由于SVG基本上是代码,因此只需要内容。我使用PHP获取内容,但是您可以使用任何内容。

<?php
$content    = file_get_contents($pathToSVG);
?>

然后,我将内容按原样打印在div容器中

<div class="fill-class"><?php echo $content;?></div>

最终在CSS上为容器的SVG子项设置规则

.fill-class > svg { 
    fill: orange;
}

我得到了带有材料图标SVG的结果:

Mozilla Firefox 59.0.2(64位)Linux

在此处输入图片说明

Google Chrome66.0.3359.181(正式版)(64位)Linux

在此处输入图片说明

Opera 53.0.2907.37 Linux

在此处输入图片说明


我不能投票,但请永远不要这样做。
桑德

5
原因 备择方案?
本杰明

我之所以不这样做,是因为这阻止了浏览器缓存SVG。替代方法是使用此处其他一些答案中提到的SVG注射器。SVG文件仍将由浏览器缓存,并且仍然可以使用CSS设置注入的SVG的样式。但是我不反对你。
儿子TRAN-阮

我了解,但是无论如何,没有提到缓存。最好的答案是可以每次通过标头过期操作或在文件名链接后强制进行哈希操作都可以重新加载(或不能重新加载)的JavaScript代码。感谢您不要拒绝投票,但我仍然相信我的答案可以解决使用CSS fill属性更改SVG的问题。
本杰明

2

这可能对PHP结合使用的人有帮助.svg希望与CSS图像。

您无法使用CSS覆盖img标签内的属性。但是,当将svg源代码嵌入HTML时,您肯定可以。我想使用包含以下内容的require_once函数来解决此问题:.svg.php文件。这就像导入图像一样,但是您仍然可以使用CSS覆盖样式!

首先包含svg文件:

<?php require_once( '/assets/images/my-icon.svg.php' ); ?>

其中包括此图标,例如:

<svg xmlns="http://www.w3.org/2000/svg" width="20.666" height="59.084" viewBox="0 0 20.666 59.084"><g transform="translate(-639.749 -3139)"><path d="M648.536,3173.876c0-2.875-1.725-3.8-3.471-3.8-1.683,0-3.49.9-3.49,3.8,0,3,1.786,3.8,3.49,3.8C646.811,3177.676,648.536,3176.769,648.536,3173.876Zm-3.471,2.341c-.883,0-1.437-.513-1.437-2.341,0-1.971.615-2.381,1.437-2.381.862,0,1.438.349,1.438,2.381,0,1.907-.616,2.339-1.438,2.339Z" fill="#142312"/><path d="M653.471,3170.076a1.565,1.565,0,0,0-1.416.9l-6.558,13.888h1.2a1.565,1.565,0,0,0,1.416-.9l6.559-13.887Z" fill="#142312"/><path d="M655.107,3177.263c-1.684,0-3.471.9-3.471,3.8,0,3,1.766,3.8,3.471,3.8,1.745,0,3.49-.9,3.49-3.8C658.6,3178.186,656.851,3177.263,655.107,3177.263Zm0,6.139c-.884,0-1.438-.514-1.438-2.34,0-1.972.617-2.381,1.438-2.381.862,0,1.437.349,1.437,2.381,0,1.909-.616,2.34-1.437,2.34Z" fill="#142312"/><path d="M656.263,3159.023l-1.49-14.063a1.35,1.35,0,0,0,.329-.293,1.319,1.319,0,0,0,.268-1.123l-.753-3.49a1.328,1.328,0,0,0-1.306-1.054h-6.448a1.336,1.336,0,0,0-1.311,1.068l-.71,3.493a1.344,1.344,0,0,0,.276,1.112,1.532,1.532,0,0,0,.283.262l-1.489,14.087c-1.7,1.727-4.153,4.871-4.153,8.638v28.924a1.339,1.339,0,0,0,1.168,1.49,1.357,1.357,0,0,0,.17.01h17.981a1.366,1.366,0,0,0,1.337-1.366v-29.059C660.414,3163.893,657.963,3160.749,656.263,3159.023Zm-8.307-17.349h4.274l.176.815H647.79Zm9.785,43.634v10.1H642.434v-17.253a4.728,4.728,0,0,1-2.028-4.284,4.661,4.661,0,0,1,2.028-4.215v-2c0-3.162,2.581-5.986,3.687-7.059a1.356,1.356,0,0,0,.4-.819l1.542-14.614H652.1l1.545,14.618a1.362,1.362,0,0,0,.4.819c1.109,1.072,3.688,3.9,3.688,7.059v9.153a5.457,5.457,0,0,1,0,8.5Z" fill="#142312"/></g></svg>

现在,我们可以使用CSS轻松更改填充颜色:

svg path {
  fill: blue;
}

我首先尝试用解决这个问题,file_get_contents()但是上面的解决方案要快得多。


0

知道这是一个老问题,但是最近我们遇到了同样的问题,我们从服务器端解决了这个问题。这是特定于php的答案,但我肯定其他环境也有类似的东西。而不是使用img标签,而是从一开始就将svg呈现为svg。

public static function print_svg($file){
    $iconfile = new \DOMDocument();
    $iconfile->load($file);
    $tag = $iconfile->saveHTML($iconfile->getElementsByTagName('svg')[0]);
    return $tag;
}

现在,当您渲染文件时,您将获得完整的内嵌svg



-2

如果您可以访问JQuery,则可以通过以下方法扩展到Praveen的答案,以编程方式更改SVG中不同嵌套元素的颜色:

$('svg').find('path, text').css('fill', '#ffffff');

在find中,您可以提及需要更改颜色的不同元素。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.