Specify an SVG as a background image and ALSO style the SVG in CSS?
Is it possible to specify an SVG as a background image and ALSO style the SVG in the same CSS file?
I'm very comfortable placing, scaling and clipping SVG images as either single files or sprites, but I haven't been able to work out if it possible to style the SVG within the same CSS file as sets it as a background image.
In pseudo CSS i'd like to d开发者_如何学运维o the following to vary the colour of simple shape based on the class of the parent element:
element1 {
background-image(icon.svg);
}
element1.black .svg-pathclass {
fill: #000000;
}
element1.white .svg-pathclass {
fill: #ffffff;
}
obviously this assumes a path in the SVG having class .svg-pathclass
is this possible?
No, this is not possible. The SVG has to be prepared in one document (which may be a data URI or an externally referenced file) and then used as a background in another file.
You can use SVG
and CSS
masks to recreate this effect, then use normal CSS
to style the inside of the SVG
, even 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 */
You can use this to create drop shadows by appending an element
to the DOM
and styling that, with a lower z-index and setting an opacity.
Hope that helps!
Edit: Links
- Modernizr Test - http://pastebin.com/w4eVbEKr
- Some more information - https://www.webkit.org/blog/181/css-masks/
It's actually possible for those who can use preprocessors in production, by "inlining" background SVG, and bit of SASS mixins
, which "slice" whole svg
gibberish, to get access to parts you want to manipulate via SASS variables
.
In your original scenario you have an element
<div class="element1"></div>
,
so you need a mixin/function
which will inline SVG for you. Let's say you want to control of the fill
, so:
@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}');
}
where $svg-content
variable is your <svg>
stuff excluding <style>
element (which you want to access from inside of the mixin
) and wrapping svg
tag,, ie:
$svg-content = "<path .... />"
This just need to be included with values passed inside:
@include inline-svg(salmon, $svg-content);
To sum whole thing up, this is an example SASS code:
$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);
}
I think possibilities here are quite big (there are also limitations here to that approach). I actually pass a SASS map
to my mixin
with css
styles defined as key
, value
pair, to inject whole bunch of css
styles to the <style>
part of svg
.
So it's technically possible, but require more compexity, but once you get this done, you'll get benefits of reusing this mixin
throughout your project(s), which is cool .
Styling the SVG via a separate CSS class didn't work for me, but inline styling did:
&::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>");
}
Note: specifying the fill
prop as a hexcode colour didn't work, even though it did if in a 'normal' SVG, that's why I converted it to RGB and styled it that way.
Reading all of these answers made me come up with this nice way of dealing with SVG in SASS (.scss), which compiles CSS, for my styling theme and also get the color
working. For my use case, I want (need) to use content: url(..svg)
since my lib supports Font and now SVG by using content: $my-icon;
in a pseudo :before
that is the only thing that works with both Font/SVG.
First is to create a SASS function to deal with urlencode
of the color (since content: url()
needs to be encoded, #
needs to become %23
). For reference, I copied this function from someone else Gist. For example this will take #fafafa
and return %23fafafa
that I can then use in fill
of the SVG. You could also go without it, just remember to change #
to %23
in the fill
property.
/* 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;
}
My lib has a few SASS variables defined for theme styling so this is what I got working with both Font and/or SVG (I added width
and display
but it might work without too).
.sort-indicator-desc:before {
content: $icon-sort-desc;
display: inline-block;
width: $icon-sort-font-size;
font-size: $icon-sort-font-size;
}
and finally the end user can still use it with a Font Family (like 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";
or with SVG (like 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>...');
So at the end, I got both the Font & SVG working with SASS variables and that is great because that means that any users of my lib (Angular-Slickgrid) can still use Font Awesome 4 icons (font) while others could also use SVGs (like Font Awesome 5) without having to install the Font Family (.eof
, .woff
, ...) which tend to be large depending on the lib. The end result is still a compiled CSS file with content
to load the SVG with an extra fill
property for the SVG color.
and voilà!!! I get the best of both :)
精彩评论