如何使用外部 CSS 设计 SVG?

我有几个 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 path {}.socIcon path {}

有些地方不对劲,也许我的实现不允许外部 CSS 修改,或者我错过了一个步骤?我真的很感激你的帮助!我只需要能够通过我的外部样式表修改 SVG 图形的颜色,但是我不能失去工具提示和链接能力(虽然我可能没有工具提示也能生活)。

175674 次浏览

<image>标记中使用时,出于隐私原因,SVG 必须包含在单个文件中。这个 虫子有更多关于为什么会这样的细节。不幸的是,您不能使用不同的标记,比如 <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 文件对其进行样式化。

“实际上,我将根据用户为我的网站选择的配色方案来改变这些图片的颜色。”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 文件。

Css 文件只有在 SVG 文件内联地包含在 HTML 中时才会对 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。

你可以使用一个 style 标签:

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 一样; 为每个样式创建一个集合,并在内联中保存它们的样式。

应该可以通过首先内联外部 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);
});
});

您可以做您想做的事情,但有一个(重要的)警告: 您的符号内的路径不能通过外部 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-red交换到 fill-blue,然后,ta-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 过滤器来更改浏览器中 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 代码进行样式化。

请注意,这不适用于填充黑色、白色或灰色的图形。你必须有一个实际的颜色在那里旋转该颜色的色调。

通过在 JavaScript 中动态创建 style 元素并将其附加到 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 中是可能的,这就打开了无数的可能性。

一个使用外部 css 样式表的动态样式的快速解决方案,以防您使用 <object>标记来嵌入 svg。

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

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;
}

适合我的: 带@import 规则的 style 标签

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

我知道这是一个老职位,但只是为了解决这个问题... 你只是使用你的类在错误的地方: D

首先,你可以利用

svg { fill: red; }

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

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

<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;
}

如果在 web 浏览器中查看 svg,但是一旦这段代码被上传到服务器,并且 svg 图标的类被编码为背景图像,那么这个方法就会工作,颜色会丢失并返回到默认颜色。似乎不能从外部样式表更改颜色,尽管用于颜色的 svg 类和用于显示和位置的 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>
@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>标签中完美工作

@ 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 );


} );


} );
}


}


}


} );

您可以在 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 文件。

在我的例子中,我在外部课堂上应用了 display:block

需要在适合的地方进行试验。

在内联 svg添加类和样式甚至不删除上述空白。

参见: 应用 display:block的地方。

<div class="col-3 col-sm-3 col-md-2  front-tpcard"><a class="noDecoration" href="#">
<img class="img-thumbnail img-fluid"><svg id="Layer_1"></svg>
<p class="cardtxt">Text</p>
</a>
</div>

申请的类别

   .front-tpcard .img-thumbnail{
display: block; /*To hide the blank whitespace in svg*/
}

这招对我很管用。 内部 svg类没有工作

正如这里的答案和 其他相关的 问题中所描述的,样式表只适用于当前的 DOM。因此,您需要将 svg 作为文档 DOM 的一部分,方法是将其内联到 html 中,或者使用 javascript 将其包含在 DOM 中。

这就是我最后做的 那里:

<object type="image/svg+xml" data="illustration.svg"
onload="this.parentNode.replaceChild(this.contentDocument.documentElement, this);">
</object>

虽然这个解决方案对我来说真的很好,但是 只能用在你控制的文件上,因为 从不可信源内联加载 svg让源代码能够在 HTML 中包含至少任意的脚本、 css 和其他元素,从而打破了沙箱。

我还没有研究缓存在这种情况下的工作效果,但是它应该和 img标记一样好,因为 javascript 函数是在加载元素之后运行的。请随意编辑。

如果禁用了 javascript,则 svg 不会包含在 DOM 中,样式也不会应用,因此请确保默认样式是可用的。带备份的 CSS 自定义属性(变量)非常适合该用例。

虽然还没有完全测试,但是我已经找到了一种像内联一样处理外部 svg 文件的好方法。没有 Javascript,没有服务器代码——只有一个文档 root-id:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="svgroot">...

在这之后,我们可以使用 SVG2-Tag,它似乎是由 Chrome/Edge-Blink、 Firefox-Gecko、 Safari-Webkit 支持的:

<html>
<head>
<style>
.primary-text {
color: green;
}
.icon {
height: 100px;
width: 100px;
fill: currentColor;
}
</style>
</head>
<body>
<h3>svg Fill currentColor</h3>
<svg class="primary-text icon">
<use href="example.svg#svgroot"></use>
</svg>


</body>
</html>

更进一步,您可以创建一个 resource-dictionary/sprite 文件:

<svg xmlns="http://www.w3.org/2000/svg">
<svg viewBox="0 0 512 512" id="apple">...
<svg viewBox="0 0 512 512" id="peach">...
</svg>

说实话,这看起来太好了,不像是真的... ... : D

//编辑:
这似乎是一种备受推崇的做法:

Https://icons.getbootstrap.com/#usage