使用 CSS 操作外部 svg 文件样式属性

Posted

技术标签:

【中文标题】使用 CSS 操作外部 svg 文件样式属性【英文标题】:Manipulating external svg file style properties with CSS 【发布时间】:2014-04-10 17:41:34 【问题描述】:

我正在尝试通过 CSS 操作外部 .svg 文件。

HTML

<body>
    <div class="mysvg">
    <img src="decho.svg"  ></img>
    </div>
</body>

CSS

div.mysvg img 
    opacity: .3;
    transition: opacity 1s linear 0s;

    div.mysvg img:hover 
    opacity: 1;

此代码适用于不透明度,但不适用于 fill 或其他 svg 特定属性,如 stroke。我知道我不能用 img 标签做到这一点,但我一直在寻找几个小时,但我找不到使用 svgobject 的正确方法。

所以基本上,我的问题是,我如何获得与我链接的代码相同的结果,但要能够操纵填充、描边等属性,它必须是一个外部文件 ,而不仅仅是粘贴在 html 中的内联 svg 代码。

如果有人能告诉我正确的方法,我将不胜感激。谢谢。


编辑:

我设法通过在 .svg 文件本身中添加一个 css 来做到这一点。它必须紧跟在svg 开始标记之后。

<svg ...>
<style type="text/css" media="screen">  
    <![CDATA[  
    g   
        fill: yellow;  
        stroke: black;  
        stroke-width: 1;
        transition: fill 1s linear 0s;
    
    g:hover 
        fill: blue;
    
    ]]>  
</style> 
<g>
    <path ...>
</g>
</svg>

还需要在html中插入object,否则不起作用。

<object data="decho.svg" type="image/svg+xml">

希望这对将来寻找像我这样的答案的人有所帮助。这对我有帮助 http://www.hongkiat.com/blog/scalable-vector-graphic-css-styling/。

【问题讨论】:

您必须使用 javascript 获取对象文档,然后操作其 DOM,您只能使用 CSS。 感谢您的回答。我一直在阅读我可以将 CSS 直接添加到 svg 文件中,您认为这是解决我问题的好方法吗? 你有办法使用 css 来操纵 svg 的大小吗?我不确定这是否可能,因为我还没有在网上找到这样做的方法。我正在嵌入在主页中的 html 文件中使用 svg 代码。 @j4v1 如果您检查我的答案中的链接,有两种可能的方法可以使用 css 操作 svg 的内部。一种是将所有 svg 转换为字体,然后使用 font-size 和 :hover psuedo 操作它们。另一种方法是将svg作为svg defs加载到页面顶部的html中,然后将它们呈现为>>,然后使用您的样式类.blah ...。 【参考方案1】:

这是我认为 svg 最大的缺陷:沙盒

Svg 文件被沙盒化: 在它们自己的文档中,这就是为什么典型的“填充:”样式不适用的原因。同样,您在 svg 中编写的 css 将不适用于您网站的其余部分。

将 css 直接添加到 svg: 这不是一个好的解决方案,因为您最终会在使用的每个 svg 中重写 css。

真正的解决方案:“图标系统”。 SVG 字体或 svg 精灵。阅读更多关于他们的信息here。

不透明度起作用的原因:不透明度适用于 svg 对象/框架本身,而不是 svg 的内容(不可访问)。

我还应该注意,无论您如何将这些 svg、内联、通过引用、在对象中作为背景加载,您都无法进入沙箱。这就是为什么必须将它们转换为字体或使用精灵来使用悬停、焦点和其他效果/过渡。

【讨论】:

这实际上是可能的,只要 SVG 不包含填充,并且您不在 CSS(阴影 DOM 边界)内使用任何父选择器。 是的,如果我们想用 CSS 控制它,它会迫使我们在 HTML 中包含 SVG - 迫使我们打破内容/语义和图形或样式的分离。我想知道为什么。好的,有 Ben 的解决方案——我可能会开始使用它。但是我想到的是通过img[src] 包含 SVG 的基本方式 这个答案不再是 100% 正确的。您可以通过&lt;symbol&gt;&lt;use&gt; 包含和设置外部文件的样式。见Ben Crook's answer。【参考方案2】:

如果 SVG 托管在同一个域上(感谢@FabienSnauwaert),并且它本身没有定义填充颜色,并且您在 CSS 中不包含父选择器,这是可能的。例如:

我有以下文件:

icon-sprite.svg(我的 SVG 外部精灵) buttons.scss test.html

icon-sprite.svg

为了清楚起见,我省略了其他 SVG。

<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;">
    <symbol viewBox="0 0 1500 828" id="icon-arrow-3pt-down">
        <title>arrow-3pt-down</title>
        <path d="M1500 0H0l738.9 827.7z"/>
    </symbol>
</svg>

test.html

<button class="button--large">
    Large button
    <svg class="svg"  >
        <use xlink:href="icon-sprite.svg#icon-arrow-3pt-down"></use>
    </svg>
</button>

buttons.scss

.svg 
    fill: red;

如果我要使用 body .svg,由于影子 DOM 边界,这将不起作用

见this CSS Tricks article for more info

【讨论】:

@Rolf 我认为 SVG 片段与我上面提到的不同,这似乎是为了将一个 SVG 的一小部分用作 CSS 背景或图像标签内。 css-tricks.com/svg-fragment-identifiers-work 解释得很好,虽然我只是略读。 很棒的解决方案,适用于所有 Firefox、Chrome 和 Safari。谨防!即使 xlink:href 已被弃用,在 Safari 中,引用仍必须使用 xlink:href 属性 - 仅使用 href 将导致图像无法加载。 (从 Safari 12.0.2 发布。) 虽然我在这里,但 SVG 不支持 alt 属性。另一种选择是:role="img" aria-label="[title + description]". ...要使其正常工作,SVG 必须与托管页面位于同一域中。 (因此,如果您的站点是 example.org 并且您在 cdn.example.org 上托管 SVG,那么您就不走运了。)Documented here:“出于安全原因,浏览器可以应用同源策略use 元素,并且可以拒绝在 href 属性中加载跨域 URL,这实际上是所有三大浏览器目前正在发生的事情。 (最终使用简单的&lt;img&gt; 来包含 SVG 并创建 SVG 文件的变体。) @FabienSnauwaert 好地方,我没想到那个案子。拒绝它是有道理的,因为 SVG 可能容易受到跨站点脚本的攻击。我已将其添加到答案中,谢谢。

以上是关于使用 CSS 操作外部 svg 文件样式属性的主要内容,如果未能解决你的问题,请参考以下文章

您如何使用 CSS 设置外部 svg 的样式

SVG:为啥外部 css 会覆盖文本的内联样式?

对外部 SVG 文件使用 CSS 悬停?

需要在操作系统中更改暗/亮模式以强制刷新外部 SVG 文件

使用带有外部定义的 SVG

如何链接外部CSS样式表