如何使用外部CSS设置SVG样式?


102

我有几个SVG图形,我想通过我的外部样式表修改颜色,而不是直接在每个SVG文件中。我不是将图形插入行中,而是将它们存储在我的图像文件夹中并指向它们。

我以这种方式实现了它们,以使工具提示能够正常工作,并且我还将每个工具提示都包装在<a>标签中以允许链接。

<a href='http://youtube.com/...' target='_blank'><img class='socIcon' src='images/socYouTube.svg' title='View my videos on YouTube' alt='YouTube' /></a>

这是SVG图形的代码:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!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" viewBox="0 0 56.69 56.69">
<g>
    <path d="M28.44......./>
</g>
</svg>

我将以下内容放入我的外部CSS文件(main.css)中:

.socIcon g {fill:red;}

但是,它对图形没有影响。我还尝试了.socIcon g路径{}和.socIcon路径{}。

某些情况不正确,也许我的实现不允许外部CSS修改,或者我错过了一步?非常感谢您的帮助!我只需要能够通过我的外部样式表修改SVG图形的颜色,但是我不会失去工具提示和链接功能。(尽管我可能没有工具提示也可以生活。)谢谢!



尝试svg { fill:red; }或给您的路径一个类名。例如,<path class="socIcon" d="M28.44 ..... />这应该可以解决问题。
Dwza

Answers:


92

仅当HTML内联包含SVG文件时,您的main.css文件才会对SVG的内容产生影响:

https://developer.mozilla.org/en/docs/SVG_In_HTML_Introduction

<html>
  <body>
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
      <path d="M28.44......./>
    </g>
  </svg>
</html>

如果要将SVG保留在文件中,则需要在SVG文件中定义CSS。

您可以使用样式标签来实现:

http://www.w3.org/TR/SVG/styling.html#StyleElementExample

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="50px" height="50px" viewBox="0 0 50 50">
  <defs>
    <style type="text/css"><![CDATA[
      .socIcon g {
        fill:red;
      }
    ]]></style>
  </defs>
  <g>
    <path d="M28.44......./>
  </g>
</svg>

您可以使用服务器端的工具来更新样式标签,具体取决于活动的样式。在红宝石中,您可以使用Nokogiri实现此目的。SVG只是XML。因此,可能有许多XML库可以实现此目的。

如果您无法执行此操作,则只需使用它们就好像它们是PNG一样。为每种样式创建一个集合,然后内联保存它们的样式。


17
这是否意味着没有任何方法可以受益于缓存SVG和应用各种样式?内联似乎无法很好地缓存,而其他方法则需要创建该图像的多个版本,从而消除了对其进行缓存的任何好处。
msg45f 2015年

另一种方法是将SVG编码为背景图像数据uri,每个版本上使用不同的颜色,并由于复制而依赖gzip减小文件大小。
罗斯金

1
就我而言,我想覆盖SVG中的元素样式。我的CSS无法正常工作,因为元素样式具有更高的优先级。最简单的解决方案是在SVG的CSS样式中添加!important。然后一切都很好。如果要避免!important,则需要将元素样式移入CSS。
David Gausmann

可惜您不能从URL加载svg内的样式表
clayRay

1
@clayRay,一旦SVG2完成草案w3.org/TR/SVG2/styling.html#LinkElement
RGB

51

您可以做一个(重要的)警告,做自己想做的事情:符号中的路径不能通过外部CSS独立设置样式-您只能使用此方法设置整个符号的属性。因此,如果您的符号中有两条路径并希望它们具有不同的填充颜色,那么这将行不通,但是如果您希望所有路径都相同,则这应该行得通。

在您的html文件中,您需要这样的内容:

<style>
  .fill-red { fill: red; }
  .fill-blue { fill: blue; }
</style>

<a href="//www.example.com/">
  <svg class="fill-red">
    <use xlink:href="images/icons.svg#example"></use>
  </svg>
</a>

在外部SVG文件中,您需要这样的内容:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>

svg标签上的类(在您的html中)从交换fill-redfill-blueta-da ...您拥有蓝色而不是红色。

通过将外部CSS与特定路径上的某些嵌入式CSS进行混合和匹配,您可以部分地避免能够与外部CSS分别定位路径的局限性,因为嵌入式CSS将优先。如果您要在彩色背景上执行白色图标之类的操作,而您想通过外部CSS更改背景颜色,但是图标本身始终是白色,则此方法会起作用。因此,使用与以前相同的HTML以及类似svg的代码,您将获得红色背景和白色前景路径:

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="example" viewBox="0 0 256 256">
    <path class="background" d="M120..." />
    <path class="icon" style="fill: white;" d="M20..." />
  </symbol>
</svg>

好答案..我认为警告应该确实是:浏览器支持,但是!很好的参考资料(比犬类更详细):css-tricks.com/svg-fragment-identifiers-work
ptim

这是一个解决方案!实际上,没有必要将整个svg内容包装在一个symbol元素中,即,您可以给idsvg元素一个,所以:`<svg id = example“ xmlns =” w3.org/2000/svg “ viewBox =” 0 0 256 256“> <path class =” background“ d =” M120 ...“ /> <path class =” icon“ style =” fill:white;“ d =” M20 ...“ /> </ svg >`
SimoneMSR

12

您可以使用以下方法在SVG文件中包括指向外部CSS文件的链接:

<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>

您需要在打开标签后将其放入:

<svg>
  <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>
  <g>
    <path d=.../>
  </g>
</svg>

这不是完美的解决方案,因为您必须修改svg文件,但是您必须修改它们一次,然后所有样式更改都可以在一个css文件中针对所有svg文件进行。


1
哇,这是可行的,但只有1个赞成票...此解决方案在所有情况下都适用吗?如此简单,为什么不选择答案呢?
布鲁诺·文森特

重点在于集中样式定义。假设您要设置10个SVG。现在,您需要将对CSS的引用复制到所有需要受影响的SVG中。并且,如果CSS的文件名/位置发生了变化,则需要在10个SVG中进行更新。CSS类比对物理CSS文件的引用更具象征意义。
弗朗斯

请注意,通过<img>标签加载的svg 不会加载外部内容(例如,样式表)。
驼鹿道德

7

通过在JavaScript中动态创建样式元素并将其附加到SVG元素,可以对SVG进行样式设置。哈克,但它可以工作。

<object id="dynamic-svg" type="image/svg+xml" data="your-svg.svg">
    Your browser does not support SVG
</object>
<script>
    var svgHolder = document.querySelector('object#dynamic-svg');
    svgHolder.onload = function () {
        var svgDocument = svgHolder.contentDocument;
        var style = svgDocument.createElementNS("http://www.w3.org/2000/svg", "style");

        // Now (ab)use the @import directive to load make the browser load our css
        style.textContent = '@import url("/css/your-dynamic-css.css");';

        var svgElem = svgDocument.querySelector('svg');
        svgElem.insertBefore(style, svgElem.firstChild);
    };
</script>

您可以根据需要在PHP中动态生成JavaScript-JavaScript可以实现这一事实带来了无数种可能性。


嘿,我实际上很喜欢您的解决方案,它可以正常工作,但是如果您愿意帮助os当然,我需要在自己的情况下采用它,我在<defs>里面有一个样式标签,可以手动删除它们并运行此代码,以便创建一种样式,有没有一种方法可以删除defs,然后像您一样重新创建元素,或者只是更新它,并且url出现了未定义的错误url您能不能帮忙,谢谢
Kamel Mili

6

您可以采用的一种方法就是仅使用CSS过滤器来更改SVG图形在浏览器中的外观。

例如,如果您的SVG图形在SVG代码中使用红色的填充色,则可以通过180度的色相旋转设置将其变为紫色:

#theIdOfTheImgTagWithTheSVGInIt {
    filter: hue-rotate(180deg);
    -webkit-filter: hue-rotate(180deg);
    -moz-filter: hue-rotate(180deg);
    -o-filter: hue-rotate(180deg);
    -ms-filter: hue-rotate(180deg);
}

试用其他色相-旋转设置以查找所需的颜色。

需要明确的是,以上CSS包含在应用于HTML文档的CSS中。您正在样式化HTML代码中的img标签,而不是样式化SVG代码。

请注意,这不适用于填充黑色,白色或灰色的图形。您必须在其中具有实际颜色才能旋转该颜色的色相。


4

如果您使用<object>标记嵌入svg,可以使用外部CSS样式表快速生成动态样式。

此示例将<svg>在单击父元素时将一个类添加到根标签。

file.svg:

<?xml-stylesheet type="text/css" href="../svg.css"?>
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="">
  <g>
   <path/>
  </g>
 </svg>

html:

<a class="parent">
  <object data="file.svg"></object>
</a>

jQuery的:

$(function() {
  $(document).on('click', '.parent', function(){
    $(this).find('object').contents().find('svg').attr("class","selected");
  }
});

点击父元素时:

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="" class="selected">

那么你可以管理你的CSS

svg.css:

path {
 fill:none;
 stroke:#000;
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}

.selected path {
 fill:none;
 stroke:rgb(64, 136, 209);
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}

似乎无效,您可以添加一个有效的示例吗?
Jeanluca Scaljeri,2017年

4

应该可以通过首先内嵌外部svg图像来做到。以下代码来自由Jess Frazelle 用内联SVG替换所有SVG图像

$('img.svg').each(function(){
  var $img = $(this);
  var imgID = $img.attr('id');
  var imgClass = $img.attr('class');
  var imgURL = $img.attr('src');
  $.get(imgURL, function(data) {
    // Get the SVG tag, ignore the rest
    var $svg = $(data).find('svg');
    // Add replaced image's ID to the new SVG
    if (typeof imgID !== 'undefined') {
      $svg = $svg.attr('id', imgID);
    }
    // Add replaced image's classes to the new SVG
    if (typeof imgClass !== 'undefined') {
      $svg = $svg.attr('class', imgClass+' replaced-svg');
    }
    // Remove any invalid XML tags as per http:validator.w3.org
    $svg = $svg.removeAttr('xmlns:a');
    // Replace image with new SVG
    $img.replaceWith($svg);
  });
});

3
请注意,仅当您将图像托管在与html相同的域中,或在图像服务器上具有经过特殊配置的跨域策略时,这才有效。如果没有有效的允许访问标头
$。get

这是传奇
Tino Costa'El Nino''19

2

<image>标签中使用时,出于隐私原因,SVG必须包含在单个文件中。该bugzilla错误详细说明了为什么会这样。不幸的是,您不能使用其他标签(例如,<iframe>因为不能用作链接),因此您必须将CSS嵌入<style>文件本身的标签中。

另一种方法是将SVG数据保存在主html文件中,即

<a href='http://youtube.com/...' target='_blank'>
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path d="M28.44......./>
    </g>
  </svg>
</a>

您可以使用HTML <link>标记通过外部CSS文件设置样式。


2
我无法将样式放入文件中。实际上,我将根据用户为我的网站选择的配色方案来更改这些图像的颜色。我当前的实现是在主页上添加一个样式表,该样式表将覆盖默认样式。我想将颜色更改放入该文件中,以影响嵌入式SVG图形。但这是行不通的,因为我必须从SVG文件中链接到样式表(除非也有一种使用JavaScript将链接添加到所有SVG文件的方法)。当然,有一种方法可以允许外部SVG文件,外部CSS,链接和工具提示。
约旦H

1
由于浏览器的安全模型,无法做您想做的事情。当用作图像时,不能使用javascript来操纵SVG。当将SVG用作图像时,就像动画的png或gif文件一样,它们都在一个文件中并且没有脚本访问权限。
罗伯特·朗森

1

“实际上,我将根据用户为我的网站选择的配色方案来更改这些图像的颜色。” - 约旦 10小时前

我建议您为此使用PHP。没有图标字体,确实没有更好的方法可以完成此操作,如果您拒绝使用它们,可以尝试以下方法:

<?php

    header('Content-Type: image/svg+xml');
    echo '<?xml version="1.0" encoding="utf-8"?>';
    $color = $_GET['color'];

?>
<!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" viewBox="0 0 56.69 56.69">
    <g>
        <path fill="<?php echo $color; ?>" d="M28.44..."/>
    </g>
</svg>

然后,您可以将此文件用作filename.php?color=#ffffff所需颜色的svg文件。


6
请注意,此代码不会检查用户输入-任何内容都可以作为颜色提供,并且您的SVG可能会以一些非常有趣的方式呈现...不确定是否会影响您,但您应该养成始终验证用户输入的习惯。这样的事情会有所帮助:(if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');将其放在开始的PHP块中的某个位置)。
johndodo 2013年

1

什么对我有用:具有@import规则的样式标签

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>

1

我知道它是一个老帖子,但只是为了解决这个问题...您只是在错误的地方使用了您的课程:D

首先,您可以使用

svg { fill: red; }

在你的main.css红色。这确实有效果。您也可以适当地使用节点选择器来获取特定路径。

第二件事是,您将类声明为-Tag img

<img class='socIcon'....

实际上,您应该在SVG中将其解码。如果您有不同的路径,则可以定义更多的路径。

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!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" viewBox="0 0 56.69 56.69">
<g>
    <path class="myClassForMyPath" d="M28.44......./>
</g>
</svg>

现在您可以按自己的main.css喜好更改颜色

.myClassForMyPath {
    fill: yellow;
}

试过这个,它不起作用,就像许多其他答案已经说过的那样。您不能将样式应用于SVG内部的类。
弗朗斯

@Frans您是否将svg包含为文件,或者是否像上面的示例一样具有svg源?因为我牢记这取决于您使用svg的方式。包括img都行不通。
德扎

确实,仅当您在HTML中内联SVG时,它才有效。但这不是您的示例所做的。它使用外部(即非串联)SVG。似乎没有办法在HTML中使用CSS设置外部SVG的样式。
弗朗斯

确定您尝试的示例正确吗?我的意思是,包括来自外部的CSS文件?<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
Dwza

好的,现在我知道,您 SVG中有一个<?xml-stylesheet ... ?>声明。我想那行得通。它与建议在SVG内部的其他答案类似。它也有同样的问题(您需要更新每个SVG以指向样式表,并且样式表名称或位置的任何更改都意味着必须再次更改所有SVG)。<link rel="stylesheet" ... >
弗朗斯

1
  1. 对于外部样式

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	@import url(main.css);
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

  1. 对于内部样式

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	    .socIcon g {fill:red;}
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

注意:如果您在<img>标记中包含SVG,则外部样式将不起作用。它将在<div>标签内完美运行


0

@leo这是angularJS版本,再次感谢

G.directive ( 'imgInlineSvg', function () {

return {
    restrict : 'C',
    scope : true,
    link : function ( scope, elem, attrs ) {

        if ( attrs.src ) {

            $ ( attrs ).each ( function () {
                var imgID    = attrs.class;
                var imgClass = attrs.class;
                var imgURL   = attrs.src;

                $.get ( imgURL, function ( data ) {

                    var $svg = $ ( data ).find ( 'svg' );
                    if ( typeof imgID !== 'undefined' ) {
                        $svg = $svg.attr ( 'id', imgID );
                    }

                    if ( typeof imgClass !== 'undefined' ) {
                        $svg = $svg.attr ( 'class', imgClass + ' replaced-svg' );
                    }

                    $svg = $svg.removeAttr ( 'xmlns:a' );

                    elem.replaceWith ( $svg );

                } );

            } );
        }

    }

}

} );

-1

如果在Web浏览器中查看了svg,但此代码将被上传到服务器,并且该svg图标的类被编码为好像是背景图像,则该颜色将丢失并恢复为默认颜色。似乎颜色无法从外部样式表更改,即使颜色的svg类和svg的显示和位置的顶层类都已映射到同一目录。

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.