如何在CSS中指定SVG背景图并进行样式设置?

27

能否在CSS文件中同时指定SVG为背景图像并对SVG进行样式设置?

我很习惯将SVG图像作为单个文件或精灵进行放置、缩放和裁剪,但我无法确定是否可以在同一CSS文件中对设置为背景图像的SVG进行样式设置。

在伪CSS中,我想根据父元素的类来改变简单形状的颜色,如下所示:

element1 {
 background-image(icon.svg);
}

element1.black .svg-pathclass {
 fill: #000000;
}

element1.white .svg-pathclass {
 fill: #ffffff;
}

显然,这假定SVG路径具有类.svg-pathclass。

这可行吗?

5个回答

19

不,这是不可能的。SVG必须在一个文档中准备好(可以是数据URI或外部引用文件),然后作为背景在另一个文件中使用。


@joneb 我认为这不会很好,我认为它会导致循环引用问题。 :) - Phrogz
13
是的,你说得对。在这种情况下使用 "neat" 是与 "我希望它能在不考虑更广泛的影响的情况下为我当前的目的发挥作用" 相关的。 :D - JSDBroughton
@JSDBroughton #为什么他们不只是... - Nicholas Shanks

6

如果能在生产中使用预处理器,通过“内联”背景SVG和一些SASS mixins,将整个SVG乱码“切片”,以便通过SASS变量访问要操作的部分,这是可能的。

在您的原始方案中,您有一个元素
<div class="element1"></div>

所以您需要一个mixin/function来为您内联SVG。假设您想控制填充,那么:

@mixin inline-svg($color, $svg-content) {
  $start: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><style>path { fill:#{$color}; }</style>';
  $end:   '</svg>';

  background-image: url('data:image/svg+xml;utf8, #{$start}#{$svg-content}#{$end}');
}

其中$svg-content变量是您的<svg>内容,不包括<style>元素(您希望从mixin内部访问的元素),并且包装svg标签,即:$svg-content = "<path .... />"

只需传递所需的值即可包含此内容:
@include inline-svg(salmon, $svg-content);

总之,这是一个示例SASS代码:

$svg-content = "<path .... />"

@mixin inline-svg($color, $svg-content) {
    $start: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><style>path { fill:#{$color}; }</style>';
    $end:   '</svg>';

    background-image: url('data:image/svg+xml;utf8, #{$start}#{$svg-content}#{$end}');
}  

.element1 {
    @include inline-svg(rgba(0,0,0,0.6), $svg-content);
}

我认为这里的可能性相当大(但这种方法也有局限性)。我实际上将一个SASS映射传递给我的mixin,其中定义了css样式作为键值对,以将整个一堆css样式注入到svg的style部分中。
所以从技术上讲是可能的,但需要更多的复杂性,但一旦完成,您将获得在整个项目中重用此mixin的好处,这很酷。

最初的使用案例是允许UX事件自动对子SVG元素进行外观更改,例如使用data-mode属性。请求使用单个SVG以最小化占用空间来促进交互。但是这是一个很好的工作示例。 - JSDBroughton

6
您可以使用SVGCSS掩模来重现此效果,然后使用普通的CSS来样式化SVG内部,甚至包括background-image
-webkit-mask:   url(filename.svg) 50% 50% / 100px 50px no-repeat;
    -o-mask:    url(filename.svg) 50% 50% / 100px 50px no-repeat;
    -ms-mask:   url(filename.svg) 50% 50% / 100px 50px no-repeat;

background-color: red;
background-image: url(animated.gif);

/* Filename, Position / Size, Repeat */
/* Modernizr.cssmask is the test needed to pass - snippet below */

你可以使用该方法创建下拉阴影:将一个元素附加到DOM并设置较低的z-index和不透明度进行样式设置。
希望这有所帮助!
编辑:链接
- Modernizr测试 - http://pastebin.com/w4eVbEKr - 更多信息 - https://www.webkit.org/blog/181/css-masks/

2
除非-o和-ms不存在:/ - okliv
1
这很好,但可能不适用于所有浏览器,并且取决于图像的复杂性:http://caniuse.com/#feat=css-masks。 - Crystal Miller

2
通过单独的CSS类样式表来设置SVG的样式对我无效,但是内联样式可以:
&::after {
      content: url("data:image/svg+xml;charset=UTF-8, <svg viewBox='0 0 14 24' xmlns='http://www.w3.org/2000/svg' width='12px' height='18px'><path fill='rgb(13, 132, 254)' d='M2.1.1L0 2.2l8.3 8.3L9.8 12l-1.5 1.5L0 21.8l2.1 2.1L14 12z' /></svg>");
    }

注意:将fill属性指定为十六进制颜色代码无效,即使在“普通”的SVG中也是如此,这就是为什么我将其转换为RGB并以这种方式进行样式设计的原因。

1
你需要对fill颜色进行urlencode编码,因为它是一个链接。这通常意味着将#转换为%23,因此颜色#fafafa将变成fill="%23fafafa"fill="%23red" - ghiscoding

0

阅读所有这些答案让我想到了一个不错的方法来处理SASS (.scss)中的SVG,它可以编译CSS,用于我的样式主题,并且可以使color正常工作。对于我的用例,我想(需要)使用content: url(..svg),因为我的库支持字体和现在使用content: $my-icon;在伪元素:before中支持SVG和字体。

首先创建一个SASS函数来处理颜色的urlencode(因为content:url()需要编码,#需要变成%23)。我从别人那里复制了这个函数Gist。例如,这将取出#fafafa并返回%23fafafa,然后我可以在SVG的fill中使用它。你也可以不用它,只需记得在fill属性中将#更改为%23
/* sass-utilities.scss */
@function encodecolor($string) {
    @if type-of($string) == 'color' {
        $hex: str-slice(ie-hex-str($string), 4);
        $string:unquote("#{$hex}");
    }
    $string: '%23' + $string;
    @return $string;
}

我的库中定义了一些SASS变量用于主题样式,所以我可以使用字体和/或SVG(我添加了widthdisplay,但也可能不需要)。

.sort-indicator-desc:before {
    content: $icon-sort-desc;
    display: inline-block;
    width: $icon-sort-font-size;    
    font-size: $icon-sort-font-size;
}

最后,最终用户仍然可以使用类似 Font Awesome 4 的字体系列来使用它。
/* with a Font */
$icon-font-family:     "FontAwesome"; //  Font Awesome 4 
$icon-sort-color:      #0070d2;
$icon-sort-font-size:  13px;
$icon-sort-asc:        "\f0d8";       // unicode value of the icon
$icon-sort-desc:       "\f0d7";
// this compiles to => `content: "\f0d8";

或者使用SVG(例如Font Awesome 5)

@import './sass-utilities'; // sass helper

/* with SVG */
$icon-sort-color:     #0070d2;
$icon-sort-font-size: 13px;
$icon-sort-asc:       url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" fill="#{encodecolor($icon-sort-color)}" viewBox="0 0 24 24" id="arrowdown"><path d="M19.1 9.7c.4-.4.4-.9 0-1.3l-6.9-6.7c-.4-.4-.9-.4-1.3 0L4 8.4c-.4.4-.4.9 0 1.3l1.3 1.2c.3.4.9.4 1.3 0l2.1-2.1c.4-.4 1-.1 1 .4v12.5c0 .5.5.9 1 .9h1.8c.5 0 .9-.5.9-.9V9.2c0-.5.7-.8 1-.4l2.2 2.1c.4.4.9.4 1.3 0l1.2-1.2z"></path></svg>');
$icon-sort-desc:      url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" fill="#{encodecolor($icon-sort-color)}" viewBox="0 0 24 24" id="arrowdown"><path d="M4.4 14.3c-.3.4-.3.9 0 1.3l7 6.7c.3.4.9.4 1.2 0l7-6.7c.4-.4.4-.9 0-1.3l-1.3-1.2c-.3-.4-.9-.4-1.3 0l-2.1 2.1c-.4.4-1.1.1-1.1-.4V2.3c0-.5-.4-.9-.9-.9h-1.8c-.5 0-.9.5-.9.9v12.5c0 .5-.7.8-1.1.4L7 13.1c-.4-.4-1-.4-1.3 0l-1.3 1.2z"></path></svg>');
// this compiles to => `content: url('data:image/svg+xml,<svg>...');

最终,我成功地使用SASS变量同时实现了字体和SVG,这非常棒,因为这意味着我的库(Angular-Slickgrid)的任何用户都可以使用 Font Awesome 4 图标(字体),而其他人也可以使用 SVG(例如Font Awesome 5),而无需安装字体族(.eof, .woff等),这取决于库的大小。最终结果仍然是一个已编译的CSS文件,带有content以加载带有额外 fill 属性用于SVG颜色的SVG。

瞧!我得到了最好的两者 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接