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

Jor*_*n H 84 html css svg external stylesheet

我有几个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>
Run Code Online (Sandbox Code Playgroud)

这是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>
Run Code Online (Sandbox Code Playgroud)

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

.socIcon g {fill:red;}
Run Code Online (Sandbox Code Playgroud)

但它对图形没有影响.我也尝试过.socIcon g path {}和.socIcon path {}.

有些东西不对,也许我的实现不允许外部CSS修改,或者我错过了一步?我真的很感谢你的帮助!我只需要能够通过我的外部样式表修改SVG图形的颜色,但我不能失去工具提示和链接能力.(虽然我可能没有工具提示,但我可以住.)谢谢!

RGB*_*RGB 79

如果SVG文件包含在HTML中,则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>
Run Code Online (Sandbox Code Playgroud)

如果要将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>
Run Code Online (Sandbox Code Playgroud)

您可以使用服务器端的工具根据活动样式更新样式标记.在红宝石中,你可以通过Nokogiri实现这一目标.SVG只是XML.因此,可能有许多XML库可以实现这一点.

如果你无法做到这一点,你将不得不像使用PNG一样使用它们; 为每个样式创建一个集合,并将其样式保存为内联.

  • 这是否意味着没有方法可以从缓存SVG和应用各种样式中受益?内联似乎没有很好地缓存,而其他方法需要创建许多版本的映像,从而消除缓存它们的任何好处. (16认同)
  • 就我而言,我想覆盖 SVG 中的元素样式。我的 CSS 不起作用,因为元素样式具有更高的优先级。最简单的解决方案是为 SVG 的 CSS 样式添加 !important。然后一切都很好。如果你想避免 !important,你需要将元素样式移到 CSS 中。 (2认同)
  • @clayRay 一旦 SVG2 完成草稿,您就可以这样做 https://www.w3.org/TR/SVG2/styling.html#LinkElement (2认同)
  • @raddrick 太棒了!所以只需要等待 SVG2 就可以了。那么我们应该在 2050 年代的某个时候出发。我相信为我们带来《永远的毁灭公爵》的团队是最优秀的。 (2认同)

小智 43

您可以通过一个(重要的)警告来执行您想要的操作:符号中的路径无法通过外部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>
Run Code Online (Sandbox Code Playgroud)

在外部SVG文件中,您需要以下内容:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>
Run Code Online (Sandbox Code Playgroud)

SWAP在类svg的标签(在HTML)fill-redfill-blue和当当......你有蓝色,而不是红色.

通过将外部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>
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案..我认为警告应该是:浏览器支持!很好的参考(比caniuse更详细):https://css-tricks.com/svg-fragment-identifiers-work/ (2认同)
  • 这是一个解决方案!实际上没有必要将整个 svg 内容包装在一个 `symbol` 元素中,即你可以只给 svg 元素一个 `id`,所以:` &lt;svg id=example" xmlns="http://www. w3.org/2000/svg" viewBox="0 0 256 256"&gt; &lt;path class="background" d="M120..." /&gt; &lt;path class="icon" style="fill: white;" d ="M20..." /&gt; &lt;/svg&gt; ` (2认同)

小智 24

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

<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>
Run Code Online (Sandbox Code Playgroud)

您需要在打开标签后放置它:

<svg>
  <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>
  <g>
    <path d=.../>
  </g>
</svg>
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,通过 &lt;img&gt; 标签加载的 svg 将*不会*加载外部内容(例如样式表)。 (4认同)
  • 哇,这是可行的,但只有 1 票赞成......这个解决方案适合所有情况吗?这么简单,为什么这不是我们选择的答案呢? (3认同)
  • @Frans 你所说的一切都适用于 HTML,所以这不是 SVG 特定的。事实上,这是一个非常普遍的链接问题——标记文档之间的链接确实既有好处也有缺点。 (2认同)

Pet*_*ete 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>
Run Code Online (Sandbox Code Playgroud)

如果你愿意的话,你可以在PHP中动态生成JavaScript - 事实上这在JavaScript中是可能的,这开启了无数的可能性.


Sim*_*ite 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


Leo*_*Leo 5

应该可以通过首先内联外部 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);
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 重要的是要注意,只有当您将图像托管在与 html 相同的域中,或者在图像服务器上具有专门配置的跨域策略时,这才有效。如果没有有效的允许访问标头,$.get 将使用 ajax 并且无法从外部服务器加载图像 (4认同)