如何使用外部 CSS 设置 SVG 样式?
Posted
技术标签:
【中文标题】如何使用外部 CSS 设置 SVG 样式?【英文标题】:How to style SVG with external CSS? 【发布时间】:2013-08-28 08:24:47 【问题描述】:我有几个 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 图形的颜色,但我不能失去工具提示和链接功能。 (不过,我也许可以在没有工具提示的情况下生活。)谢谢!
【问题讨论】:
见***.com/questions/12604095/… 试试svg fill:red;
或者给你的路径一个类名。例如。 <path class="socIcon" d="M28.44 ..... />
这应该可以解决问题。
【参考方案1】:
如果 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>
如果您想将 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"
viewBox="0 0 50 50">
<defs>
<style type="text/css"><![CDATA[
.socIcon g
fill:red;
]]></style>
</defs>
<g>
<path d="M28.44......./>
</g>
</svg>
您可以使用服务器端的工具来根据活动样式更新样式标签。在 ruby 中,您可以使用 Nokogiri 来实现这一点。 SVG 只是 XML。所以可能有很多可用的 XML 库可以实现这一点。
如果您无法做到这一点,您将不得不像使用 PNG 一样使用它们;为每种样式创建一个集合,并内联保存它们的样式。
【讨论】:
这是否意味着没有任何方法可以从缓存 SVG 和应用各种样式中受益?内联似乎不能很好地缓存,而其他方法需要创建许多版本的图像,从而消除了缓存它们的任何好处。 另一种方法是将 SVG 编码为背景图像数据 uri,每个版本具有不同的颜色,并依靠 gzip 来减少由于重复导致的文件大小。 就我而言,我想覆盖 SVG 中的元素样式。我的 CSS 不起作用,因为元素样式具有更高的优先级。最简单的解决方案是在 SVG 的 CSS 样式中添加一个 !important。然后一切都很好。如果你想避免 !important,你需要将元素样式移动到 CSS 中。 很遗憾您无法从 URL 加载 svg 中的样式表 @clayRay 一旦 SVG2 完成草稿w3.org/TR/SVG2/styling.html#LinkElement,您就可以这样做【参考方案2】:你可以做你想做的事,但有一个(重要的)警告:你的符号中的路径不能通过外部 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>
【讨论】:
好答案..我认为警告应该是:浏览器支持,不过!很好的参考(比 caniuse 更详细):css-tricks.com/svg-fragment-identifiers-work 这是一个解决方案!实际上没有必要将整个 svg 内容包装在一个symbol
元素中,即你可以给 svg 元素一个 id
,所以: ` 【参考方案3】:
您可以在 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 票赞成……这个解决方案适用于所有情况吗?这么简单,为什么这不是选择的答案? 重点在于集中您的样式定义。假设您有 10 个要设置样式的 SVG。现在您需要将 CSS 的引用复制到所有需要影响的 SVG 中。如果您的 CSS 的文件名/位置发生变化,您需要在 10 个 SVG 中更新它。与物理 CSS 文件的引用相比,CSS 类更具象征意义。 请注意,通过 标签加载的 svg 将不会加载外部内容(例如样式表)。 @Frans 您所说的所有内容都以相同的方式应用于 HTML,因此这不是特定于 SVG 的。事实上,这是一个非常普遍的链接问题——标记文档之间的链接确实有利有弊。 正如Moose Morals所说,使用这种方法,我们不能使用<img>
标签并在SVG内部加载外部CSS;因此,我建议使用<object>
,使用data
属性而不是src
。【参考方案4】:
可以通过在 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 中这是可能的这一事实开启了无数的可能性。
【讨论】:
嘿,我真的很喜欢你的解决方案,它正在工作,但如果你愿意帮助操作系统课程,我需要在我的情况下采用它,我在您可以采取的一种方法是使用 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 代码的样式。
请注意,这不适用于填充黑色、白色或灰色的图形。你必须有一个实际的颜色来旋转该颜色的色调。
【讨论】:
我来到这里希望能找到这样的东西。哇,辣!【参考方案6】:应该可以通过首先内联外部 svg 图像来实现。下面的代码来自 Jess Frazelle 的replace all SVG images with inline 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);
);
);
【讨论】:
重要的是要注意,只有当您将图像托管在与 html 相同的域中,或者在图像服务器上有专门配置的跨域策略时,这才有效。如果没有有效的允许访问标头,$.get 将使用 ajax 并且无法从外部服务器加载图像 这是传奇【参考方案7】:如果您使用 <object>
标记嵌入您的 svg,使用外部 css 样式表获得动态样式的非常快速的解决方案。
此示例将在单击父元素时将类添加到根 <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;
【讨论】:
似乎不起作用,你能添加一个有效的例子吗?【参考方案8】:-
外部样式
<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>
-
对于内部样式
<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>
标签内完美运行
【讨论】:
【参考方案9】:在<image>
标签中使用时,出于隐私原因,SVG 必须包含在单个文件中。这个bugzilla bug 详细说明了为什么会这样。不幸的是,您不能使用其他标签,例如 <iframe>
,因为它不能用作链接,因此您必须将 CSS 嵌入文件本身的 <style>
标签中。
另一种方法是在主 html 文件中包含 SVG 数据,即
<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 文件设置样式。
【讨论】:
我无法将样式放入文件中。实际上,我将根据用户为我的网站选择的配色方案来更改这些图像的颜色。我当前的实现是将样式表添加到覆盖默认样式的主页。我想将颜色更改放在该文件中以影响嵌入的 SVG 图形。但这行不通,因为我必须从 SVG 文件中链接到样式表(除非有一种方法也可以使用 JavaScript 将该链接添加到所有 SVG 文件)。当然有一种方法可以允许外部 SVG 文件、外部 CSS、链接和工具提示。 由于浏览器的安全模型,不可能做你想做的事。当用作图像时,您不能使用 javascript 来操作 SVG。将 SVG 用作图像时,可以将其视为动画 png 或 gif 文件,全部在一个文件中,并且没有脚本访问权限。【参考方案10】:什么对我有用:带有@import 规则的样式标签
<defs>
<style type="text/css">
@import url("svg-common.css");
</style>
</defs>
【讨论】:
【参考方案11】:@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 );
);
);
);
【讨论】:
【参考方案12】:就我而言,我在外部类中应用了display:block
。
需要在合适的地方进行试验。
inline 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
类不起作用
【讨论】:
【参考方案13】:我知道这是一篇旧帖子,但只是为了解决这个问题......你只是在错误的地方使用你的课程: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;
【讨论】:
试过了,它不起作用,就像许多其他答案已经说过的那样。您不能将样式应用于 SVG 中的类。 @Frans 您是否将 svg 作为文件包含在内,或者您是否有像上面示例中那样的 svg 源?因为我记得这取决于你如何使用 svg。通过 img 包含将不起作用。 没错,只有在 HTML 中内联 SVG 时它才有效。但这不是您的示例所做的。它使用外部(即非内联)SVG。似乎无法在 HTML 中使用 CSS 设置外部 SVG 样式。 您确定我的示例正确吗?我的意思是,包含来自外部的 css 文件?<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
好的,现在我明白了,你有一个<?xml-stylesheet ... ?>
声明inside你的SVG。我想那会奏效。它类似于在 SVG 内推荐 <link rel="stylesheet" ... >
的其他答案。它也有同样的问题(您需要更新每个 SVG 以指向样式表,并且样式表名称或位置的任何更改都意味着必须再次更改所有 SVG)。【参考方案14】:
“我实际上将根据用户为我的网站选择的配色方案来更改这些图像的颜色。” - Jordan 10 hours ago
我建议您为此使用 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 文件。
【讨论】:
请注意,此代码不会检查用户输入 - 任何内容都可以作为颜色提供,并且您的 SVG 可能会以一些非常有趣的方式呈现...不确定它是否会影响您,但您应该这样做总是验证用户输入的习惯。像这样的东西会有所帮助:if (!preg_match('/^[#][0-9a-f]6$/i', $_GET['color'])) die('Oops!');
(把它放在开始 PHP 块的某个地方)。【参考方案15】:
如果在网络浏览器中查看 svg,则此方法将起作用,但是一旦将此代码上传到服务器并且 svg 图标的类被编码为好像它是背景图像,颜色就会丢失并返回默认颜色。似乎无法从外部样式表更改颜色,即使颜色的 svg 类和 svg 的显示和位置的顶层类都映射到同一个目录。
【讨论】:
以上是关于如何使用外部 CSS 设置 SVG 样式?的主要内容,如果未能解决你的问题,请参考以下文章
使用 `fill="url(#a)"` 时如何使用 Tailwind CSS 设置 SVG <linearGradient> 样式?