ChatGPT解决这个技术问题 Extra ChatGPT

如何使用外部 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 图形的颜色,但我不能失去工具提示和链接能力(尽管我可能可以在没有工具提示的情况下生活)。

尝试 svg { fill:red; } 或为您的路径指定一个类名。例如 <path class="socIcon" d="M28.44 ..... /> 这应该可以解决问题。
您可以在 <svg> 元素中使用 <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="styles.css"/><style>@import url(styles.css);</style>

M
Mahozad

如果 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"
     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>

您可以使用服务器端的工具根据活动样式更新样式标签。在 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,您就可以这样做
W
Wenfang Du

你可以做你想做的事,但有一个(重要的)警告:你的符号中的路径不能通过外部 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,所以:` <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> `
J
Jacek Mamot

您可以使用以下方法在 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 文件,但您修改它们一次,然后所有样式更改都可以在所有 svg 文件的一个 css 文件中完成。


哇,这是可行的,但只有 1 个赞成票……这个解决方案适用于所有情况吗?这么简单,为什么这不是选择的答案?
重点是集中您的样式定义。假设您有 10 个要设置样式的 SVG。现在您需要将对 CSS 的引用复制到所有需要影响的 SVG 中。如果你的 CSS 的文件名/位置发生变化,你需要在 10 个 SVG 中更新它。一个 CSS 类感觉比对物理 CSS 文件的引用更具象征意义。
请注意,通过 标签加载的 svg 不会加载外部内容(例如,样式表)。
@Frans 您所说的所有内容都以相同的方式应用于 HTML,因此这不是特定于 SVG 的。事实上,这是一个非常普遍的链接问题——标记文档之间的链接确实有利有弊。
正如 Moose Morals 所说,使用这种方法,我们不能使用 <img> 标记并在 SVG 中加载外部 CSS;因此,我建议使用带有 data 属性而不是 src<object>
P
Pieter van den Ham

可以通过在 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 中这是可能的这一事实开启了无数的可能性。


嘿,我实际上喜欢你的解决方案,它正在工作,但如果你愿意帮助操作系统课程,我需要在我的情况下采用它,我在 中有一个样式标签,我可以手动删除它们并运行此代码以便创建一种风格,有没有办法我可以删除defs然后像你一样重新创建元素或者只是更新它,而且url有一个错误url没有定义你能帮忙吗,谢谢
S
Simon White

您可以采取的一种方法是使用 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 代码的样式。

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


我来到这里希望能找到这样的东西。哇,热血!
L
Ludovic Kuty

应该可以通过首先内联外部 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 并且无法从外部服务器加载图像
这是传奇
v
vhanahrni

如果您使用 <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>

查询:

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

似乎不起作用,您可以添加一个工作示例吗?
Y
Yuvraj Patil

对于外部样式

对于内部样式

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


<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="main.css" type="text/css"/> 也有效
R
Robert Longson

<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 文件,所有这些都在一个文件中,并且没有脚本访问权限。
F
Fordi

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

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

T
Tino Costa 'El Nino'

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

                } );

            } );
        }

    }

}

} );

S
Susobhan Das

就我而言,我在外部类中应用了 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 类不起作用


F
Frans

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

首先你可以使用

svg { fill: red; }

在您的 main.css 中使其变红。这确实有效果。您也可以使用节点选择器来获取特定路径。

第二件事是,您将类声明为 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"?>
好的,现在我明白了,您的 SVG 中有一个 <?xml-stylesheet ... ?> 声明inside。我想那会奏效。它类似于在 SVG 中推荐 <link rel="stylesheet" ... > 的其他答案。它也有同样的问题(您需要更新每个 SVG 以指向样式表,并且样式表的名称或位置的任何更改都意味着必须再次更改所有 SVG)。
M
MayeulC

如此处的答案和 other 相关的 questions 中所述,样式表仅适用于当前 DOM。因此,您需要通过将 svg 内联到 html 中或使用 javascript 将其包含在 DOM 中来使 svg 成为文档 DOM 的一部分。

这就是我最终做的there

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

虽然该解决方案对我来说非常有效,但只能在您控制的文档上使用它,因为 inline loading an svg from an untrusted source 使该源能够在您的 HTML 中至少包含任意脚本、css 和其他元素,从而破坏沙盒。

我还没有研究缓存在此方面的效果如何,但它应该与 img 标记一样好用,因为 javascript 函数是在元素加载后运行的。随意编辑这个。

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


C
Community

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


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

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