Related
Placing the SVG output directly inline with the page code I am able to simply modify fill colors with CSS like so:
polygon.mystar {
fill: blue;
}
circle.mycircle {
fill: green;
}
This works great, however I'm looking for a way to modify the "fill" attribute of an SVG when it's being served as a BACKGROUND-IMAGE.
html {
background-image: url(../img/bg.svg);
}
How can I change the colors now? Is it even possible?
For reference, here are the contents of my external SVG file:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679
118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>
You can use CSS masks, With the 'mask' property, you create a mask that is applied to an element.
.icon {
background-color: red;
-webkit-mask-image: url(icon.svg);
mask-image: url(icon.svg);
}
For more see this great article: https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images
I needed something similar and wanted to stick with CSS. Here are LESS and SCSS mixins as well as plain CSS that can help you with this. Unfortunately, it's browser support is a bit lax. See below for details on browser support.
LESS mixin:
.element-color(#color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{color}" ... /></g></svg>');
}
LESS usage:
.element-color(#fff);
SCSS mixin:
#mixin element-color($color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}
SCSS usage:
#include element-color(#fff);
CSS:
// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');
Here is more info on embedding the full SVG code into your CSS file. It also mentioned browser compatibility which is a bit too small for this to be a viable option.
One way to do this is to serve your svg from some server side mechanism.
Simply create a resource server side that outputs your svg according to GET parameters, and you serve it on a certain url.
Then you just use that url in your css.
Because as a background img, it isn't part of the DOM and you can't manipulate it.
Another possibility would be to use it regularly, embed it in a page in a normal way, but position it absolutely, make it full width & height of a page and then use z-index css property to put it behind all the other DOM elements on a page.
Yet another approach is to use mask. You then change the background color of the masked element. This has the same effect as changing the fill attribute of the svg.
HTML:
<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>
CSS:
glyph {
display: inline-block;
width: 24px;
height: 24px;
}
glyph.star {
-webkit-mask: url(star.svg) no-repeat 100% 100%;
mask: url(star.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: yellow;
}
glyph.heart {
-webkit-mask: url(heart.svg) no-repeat 100% 100%;
mask: url(heart.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: red;
}
You will find a full tutorial here: http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images (not my own). It proposes a variety of approaches (not limited to mask).
Use the sepia filter along with hue-rotate, brightness, and saturation to create any color we want.
.colorize-pink {
filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5);
}
https://css-tricks.com/solved-with-css-colorizing-svg-backgrounds/
It's possible with Sass!
The only thing you have to do is to url-encode your svg code. And this is possible with a helper function in Sass. I've made a codepen for this. Look at this:
http://codepen.io/philippkuehn/pen/zGEjxB
// choose a color
$icon-color: #F84830;
// functions to urlencode the svg string
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function url-encode($string) {
$map: (
"%": "%25",
"<": "%3C",
">": "%3E",
" ": "%20",
"!": "%21",
"*": "%2A",
"'": "%27",
'"': "%22",
"(": "%28",
")": "%29",
";": "%3B",
":": "%3A",
"#": "%40",
"&": "%26",
"=": "%3D",
"+": "%2B",
"$": "%24",
",": "%2C",
"/": "%2F",
"?": "%3F",
"#": "%23",
"[": "%5B",
"]": "%5D"
);
$new: $string;
#each $search, $replace in $map {
$new: str-replace($new, $search, $replace);
}
#return $new;
}
#function inline-svg($string) {
#return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}
// icon styles
// note the fill="' + $icon-color + '"
.icon {
display: inline-block;
width: 50px;
height: 50px;
background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}
.icon {
width: 48px;
height: 48px;
display: inline-block;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/heart.svg) no-repeat 50% 50%;
background-size: cover;
}
.icon-orange {
-webkit-filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
}
.icon-yellow {
-webkit-filter: hue-rotate(70deg) saturate(100);
filter: hue-rotate(70deg) saturate(100);
}
codeben article and demo
Now you can achieve this on the client side like this:
var green = '3CB54A';
var red = 'ED1F24';
var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";
Fiddle here!
Download your svg as text.
Modify your svg text using javascript to change the paint/stroke/fill color[s].
Then embed the modified svg string inline into your css as described here.
If you are trying to use and SVG directly on CSS with url() like this;
a:before {
content: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 451 451"><path d="M345.441,2...
You should encode the # to %23, otherwise it won't work.
<svg fill="%23FFF" ...
You can store the SVG in a variable. Then manipulate the SVG string depending on your needs (i.e., set width, height, color, etc). Then use the result to set the background, e.g.
$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';
$icon-color: #f00;
$icon-color-hover: #00f;
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function svg-fill ($svg, $color) {
#return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}
#function svg-size ($svg, $width, $height) {
$svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
$svg: str-replace($svg, '<svg', '<svg height="#{$height}"');
#return $svg;
}
.icon {
$icon-svg: svg-size($circle-icon-svg, 20, 20);
width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');
&:hover {
background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
}
}
I have made a demo too, http://sassmeister.com/gist/4cf0265c5d0143a9e734.
This code makes a few assumptions about the SVG, e.g. that <svg /> element does not have an existing fill colour and that neither width or height properties are set. Since the input is hardcoded in the SCSS document, it is quite easy to enforce these constraints.
Do not worry about the code duplication. gzip compression makes the difference negligible.
You can use the brightness filter, any value greater than 1 makes the element brighter, and any value less than 1 makes it darker. So, we can make those light SVG’s dark, and vice versa, for example, this will make the svg darker:
filter: brightness(0);
In order to change the color and not only brightness level we can use sepia filter along with hue-rotate, brightness, for example:
.colorize-blue {
filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6);
}
You can create your own SCSS function for this. Adding the following to your config.rb file.
require 'sass'
require 'cgi'
module Sass::Script::Functions
def inline_svg_image(path, fill)
real_path = File.join(Compass.configuration.images_path, path.value)
svg = data(real_path)
svg.gsub! '{color}', fill.value
encoded_svg = CGI::escape(svg).gsub('+', '%20')
data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
Sass::Script::String.new(data_url)
end
private
def data(real_path)
if File.readable?(real_path)
File.open(real_path, "rb") {|io| io.read}
else
raise Compass::Error, "File not found or cannot be read: #{real_path}"
end
end
end
Then you can use it in your CSS:
.icon {
background-image: inline-svg-image('icons/icon.svg', '#555');
}
You will need to edit your SVG files and replace any fill attributes in the markup with fill="{color}"
The icon path is always relative to your images_dir parameter in the same config.rb file.
Similar to some of the other solutions, but this is pretty clean and keeps your SCSS files tidy!
In some (very specific) situations this might be achieved by using a filter. For example, you can change a blue SVG image to purple by rotating the hue 45 degrees using filter: hue-rotate(45deg);. Browser support is minimal but it's still an interesting technique.
Demo
If you wanna swap in a simple way from white to black or some like that, try this:
filter: invert(100%);
for monochrome background you could use a svg with a mask, where the background color should be displayed
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" preserveAspectRatio="xMidYMid meet" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;" >
<defs>
<mask id="Mask">
<rect width="100%" height="100%" fill="#fff" />
<polyline stroke-width="2.5" stroke="black" stroke-linecap="square" fill="none" transform="translate(10.373882, 8.762969) rotate(-315.000000) translate(-10.373882, -8.762969) " points="7.99893906 13.9878427 12.7488243 13.9878427 12.7488243 3.53809523"></polyline>
</mask>
</defs>
<rect x="0" y="0" width="20" height="20" fill="white" mask="url(#Mask)" />
</svg>
and than use this css
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
background-image: url(your/path/to.svg);
background-color: var(--color);
Since this comes up on Google despite the age, I thought I might as well give a solution that I'm employing in the distant future of 2022 after looking at the options here.
This is really just the mask solution from before, but on a pseudo-element.
.icon {
height: 1.5rem;
width: 1.5rem;
}
.icon::before {
content: "";
display: block;
width: 100%;
height: 100%;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
mask-image: url("path/to/svg/icon.svg");
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-image: url("path/to/svg/icon.svg");
}
This works in all major browsers today, although obviously you can't have an SVG with multiple colors using this. That's the cost of business if the site doesn't let you inject them inline, or if you don't fancy doing font icons, etc.
Late to the show here, BUT, I was able to add a fill color to the SVG polygon, if you're able to directly edit the SVG code, so for example the following svg renders red, instead of default black. I have not tested outside of Chrome though:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
<polygon
fill="red"
fill-rule="evenodd" clip-rule="evenodd" points="452.5,233.85 452.5,264.55 110.15,264.2 250.05,390.3 229.3,413.35
47.5,250.7 229.3,86.7 250.05,109.75 112.5,233.5 "/>
</svg>
The only way i found for this, and to be cross browser (aka bulletproof), is to render the SVG with PHP and pass Query String to set the color.
The SVG, here called "arrow.php"
<?php
$fill = filter_input(INPUT_GET, 'fill');
$fill = strtolower($fill);
$fill = preg_replace("/[^a-z0-9]/", '', $fill);
if(empty($fill)) $fill = "000000";
header('Content-type: image/svg+xml');
echo '<?xml version="1.0" encoding="utf-8"?>';
?>
<svg xmlns="http://www.w3.org/2000/svg" width="7.4" height="12" viewBox="0 0 7.4 12">
<g>
<path d="M8.6,7.4,10,6l6,6-6,6L8.6,16.6,13.2,12Z" transform="translate(-8.6 -6)" fill="#<?php echo htmlspecialchars($fill); ?>" fill-rule="evenodd"/>
</g>
</svg>
Then you call the image like this
.cssclass{ background-image: url(arrow.php?fill=112233); }
Works only with PHP. And remember that everytime you change the color value, your browser will load a new image.
scss create function
#function url-svg($icon) {
#return url("data:image/svg+xml;utf8,#{str-replace($icon, "#", "%23")}");
}
scss use
url-svg('<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="#8A8A8F"/></svg>')
css generated
url('data:image/svg+xml;utf8,<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="%238A8A8F"/></svg>')
The str-replace function is used from bootstrap.
Here is another solution using a gradient and a monochrome icon as background and background-blend-mode to colorize the icon.
It requires the background-color to be white, else the whole background gets colored. I only tested on Chrome.
.colored-background {
background-image: linear-gradient(45deg, green, green), url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-color: #fff;
background-blend-mode: lighten, normal;
background-repeat: no-repeat;
background-position: center, center right .8em;
background-size: auto, 0.6em;
color: red;
display: inline-flex;
align-items: center;
padding: 0.5em;
padding-right: 2em;
height: 1.6em;
width: auto;
border: 1px solid gray;
}
.bg {
background-color: #ddd;
padding: 1em;
}
<div class="bg">
<div class="colored-background">green icon from black svg</div>
</div>
Related to a closed question that is linked to here, but not related directly to this question.
So in case, anyone needs actually to replace src like in the linked question, there is already an answer there. Furthermore if anyone is coming from Vue, and the src path is change on compile, I've come up with a different solution.
In my case, the parent element is a link, but it could be anything really.
<a
v-for="document in documents" :key="document.uuid"
:href="document.url"
target="_blank"
class="item flex align-items-center gap-2 hover-parent"
>
<img alt="documents" class="icon" src="../assets/PDF.svg" />
<strong>{{ document.name }}</strong>
<img class="itemImage ml-auto hide-on-parent-hover" src="../assets/download-circular-button.svg" />
<img class="itemImage ml-auto show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</a>
.hover-parent .show-on-parent-hover { display: none }
.hover-parent .hide-on-parent-hover { display: block }
.hover-parent:hover .show-on-parent-hover { display: block }
.hover-parent:hover .hide-on-parent-hover { display: none }
So the solution here is not to change src attribute, but instead to put both <img> elements in the DOM and only display the one that is needed.
If you don't have a parent element that's supposed to be hovered on, you can simply wrap both images in a div.
<div class="hover-parent" >
<img class="hide-on-parent-hover" src="../assets/download-circular-button.svg" />
<img class="show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</div>
You might also change CSS to the following, so the .hover-parent ancestor must be a direct parent:
.hover-parent > .show-on-parent-hover { display: none }
.hover-parent > .hide-on-parent-hover { display: block }
.hover-parent:hover > .show-on-parent-hover { display: block }
.hover-parent:hover > .hide-on-parent-hover { display: none }
This is my favorite method, but your browser support must be very progressive. With the mask property you create a mask that is applied to an element. Everywhere the mask is opaque, or solid, the underlying image shows through. Where it’s transparent, the underlying image is masked out, or hidden. The syntax for a CSS mask-image is similar to background-image.look at the codepenmask
A lot of IFs, but if your pre base64 encoded SVG starts:
<svg fill="#000000
Then the base64 encoded string will start:
PHN2ZyBmaWxsPSIjMDAwMDAw
if the pre-encoded string starts:
<svg fill="#bfa76e
then this encodes to:
PHN2ZyBmaWxsPSIjYmZhNzZl
Both encoded strings start the same:
PHN2ZyBmaWxsPSIj
The quirk of base64 encoding is every 3 input characters become 4 output characters. With the SVG starting like this then the 6-character hex fill color starts exactly on an encoding block 'boundary'.
Therefore you can easily do a cross-browser JS replace:
output = input.replace(/MDAwMDAw/, "YmZhNzZl");
But tnt-rox answer above is the way to go moving forward.
Placing the SVG output directly inline with the page code I am able to simply modify fill colors with CSS like so:
polygon.mystar {
fill: blue;
}
circle.mycircle {
fill: green;
}
This works great, however I'm looking for a way to modify the "fill" attribute of an SVG when it's being served as a BACKGROUND-IMAGE.
html {
background-image: url(../img/bg.svg);
}
How can I change the colors now? Is it even possible?
For reference, here are the contents of my external SVG file:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679
118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>
You can use CSS masks, With the 'mask' property, you create a mask that is applied to an element.
.icon {
background-color: red;
-webkit-mask-image: url(icon.svg);
mask-image: url(icon.svg);
}
For more see this great article: https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images
I needed something similar and wanted to stick with CSS. Here are LESS and SCSS mixins as well as plain CSS that can help you with this. Unfortunately, it's browser support is a bit lax. See below for details on browser support.
LESS mixin:
.element-color(#color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{color}" ... /></g></svg>');
}
LESS usage:
.element-color(#fff);
SCSS mixin:
#mixin element-color($color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}
SCSS usage:
#include element-color(#fff);
CSS:
// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');
Here is more info on embedding the full SVG code into your CSS file. It also mentioned browser compatibility which is a bit too small for this to be a viable option.
One way to do this is to serve your svg from some server side mechanism.
Simply create a resource server side that outputs your svg according to GET parameters, and you serve it on a certain url.
Then you just use that url in your css.
Because as a background img, it isn't part of the DOM and you can't manipulate it.
Another possibility would be to use it regularly, embed it in a page in a normal way, but position it absolutely, make it full width & height of a page and then use z-index css property to put it behind all the other DOM elements on a page.
Yet another approach is to use mask. You then change the background color of the masked element. This has the same effect as changing the fill attribute of the svg.
HTML:
<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>
CSS:
glyph {
display: inline-block;
width: 24px;
height: 24px;
}
glyph.star {
-webkit-mask: url(star.svg) no-repeat 100% 100%;
mask: url(star.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: yellow;
}
glyph.heart {
-webkit-mask: url(heart.svg) no-repeat 100% 100%;
mask: url(heart.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: red;
}
You will find a full tutorial here: http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images (not my own). It proposes a variety of approaches (not limited to mask).
Use the sepia filter along with hue-rotate, brightness, and saturation to create any color we want.
.colorize-pink {
filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5);
}
https://css-tricks.com/solved-with-css-colorizing-svg-backgrounds/
It's possible with Sass!
The only thing you have to do is to url-encode your svg code. And this is possible with a helper function in Sass. I've made a codepen for this. Look at this:
http://codepen.io/philippkuehn/pen/zGEjxB
// choose a color
$icon-color: #F84830;
// functions to urlencode the svg string
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function url-encode($string) {
$map: (
"%": "%25",
"<": "%3C",
">": "%3E",
" ": "%20",
"!": "%21",
"*": "%2A",
"'": "%27",
'"': "%22",
"(": "%28",
")": "%29",
";": "%3B",
":": "%3A",
"#": "%40",
"&": "%26",
"=": "%3D",
"+": "%2B",
"$": "%24",
",": "%2C",
"/": "%2F",
"?": "%3F",
"#": "%23",
"[": "%5B",
"]": "%5D"
);
$new: $string;
#each $search, $replace in $map {
$new: str-replace($new, $search, $replace);
}
#return $new;
}
#function inline-svg($string) {
#return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}
// icon styles
// note the fill="' + $icon-color + '"
.icon {
display: inline-block;
width: 50px;
height: 50px;
background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}
.icon {
width: 48px;
height: 48px;
display: inline-block;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/heart.svg) no-repeat 50% 50%;
background-size: cover;
}
.icon-orange {
-webkit-filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
}
.icon-yellow {
-webkit-filter: hue-rotate(70deg) saturate(100);
filter: hue-rotate(70deg) saturate(100);
}
codeben article and demo
Now you can achieve this on the client side like this:
var green = '3CB54A';
var red = 'ED1F24';
var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";
Fiddle here!
Download your svg as text.
Modify your svg text using javascript to change the paint/stroke/fill color[s].
Then embed the modified svg string inline into your css as described here.
If you are trying to use and SVG directly on CSS with url() like this;
a:before {
content: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 451 451"><path d="M345.441,2...
You should encode the # to %23, otherwise it won't work.
<svg fill="%23FFF" ...
You can store the SVG in a variable. Then manipulate the SVG string depending on your needs (i.e., set width, height, color, etc). Then use the result to set the background, e.g.
$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';
$icon-color: #f00;
$icon-color-hover: #00f;
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function svg-fill ($svg, $color) {
#return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}
#function svg-size ($svg, $width, $height) {
$svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
$svg: str-replace($svg, '<svg', '<svg height="#{$height}"');
#return $svg;
}
.icon {
$icon-svg: svg-size($circle-icon-svg, 20, 20);
width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');
&:hover {
background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
}
}
I have made a demo too, http://sassmeister.com/gist/4cf0265c5d0143a9e734.
This code makes a few assumptions about the SVG, e.g. that <svg /> element does not have an existing fill colour and that neither width or height properties are set. Since the input is hardcoded in the SCSS document, it is quite easy to enforce these constraints.
Do not worry about the code duplication. gzip compression makes the difference negligible.
You can use the brightness filter, any value greater than 1 makes the element brighter, and any value less than 1 makes it darker. So, we can make those light SVG’s dark, and vice versa, for example, this will make the svg darker:
filter: brightness(0);
In order to change the color and not only brightness level we can use sepia filter along with hue-rotate, brightness, for example:
.colorize-blue {
filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6);
}
You can create your own SCSS function for this. Adding the following to your config.rb file.
require 'sass'
require 'cgi'
module Sass::Script::Functions
def inline_svg_image(path, fill)
real_path = File.join(Compass.configuration.images_path, path.value)
svg = data(real_path)
svg.gsub! '{color}', fill.value
encoded_svg = CGI::escape(svg).gsub('+', '%20')
data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
Sass::Script::String.new(data_url)
end
private
def data(real_path)
if File.readable?(real_path)
File.open(real_path, "rb") {|io| io.read}
else
raise Compass::Error, "File not found or cannot be read: #{real_path}"
end
end
end
Then you can use it in your CSS:
.icon {
background-image: inline-svg-image('icons/icon.svg', '#555');
}
You will need to edit your SVG files and replace any fill attributes in the markup with fill="{color}"
The icon path is always relative to your images_dir parameter in the same config.rb file.
Similar to some of the other solutions, but this is pretty clean and keeps your SCSS files tidy!
In some (very specific) situations this might be achieved by using a filter. For example, you can change a blue SVG image to purple by rotating the hue 45 degrees using filter: hue-rotate(45deg);. Browser support is minimal but it's still an interesting technique.
Demo
If you wanna swap in a simple way from white to black or some like that, try this:
filter: invert(100%);
for monochrome background you could use a svg with a mask, where the background color should be displayed
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" preserveAspectRatio="xMidYMid meet" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;" >
<defs>
<mask id="Mask">
<rect width="100%" height="100%" fill="#fff" />
<polyline stroke-width="2.5" stroke="black" stroke-linecap="square" fill="none" transform="translate(10.373882, 8.762969) rotate(-315.000000) translate(-10.373882, -8.762969) " points="7.99893906 13.9878427 12.7488243 13.9878427 12.7488243 3.53809523"></polyline>
</mask>
</defs>
<rect x="0" y="0" width="20" height="20" fill="white" mask="url(#Mask)" />
</svg>
and than use this css
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
background-image: url(your/path/to.svg);
background-color: var(--color);
Since this comes up on Google despite the age, I thought I might as well give a solution that I'm employing in the distant future of 2022 after looking at the options here.
This is really just the mask solution from before, but on a pseudo-element.
.icon {
height: 1.5rem;
width: 1.5rem;
}
.icon::before {
content: "";
display: block;
width: 100%;
height: 100%;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
mask-image: url("path/to/svg/icon.svg");
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-image: url("path/to/svg/icon.svg");
}
This works in all major browsers today, although obviously you can't have an SVG with multiple colors using this. That's the cost of business if the site doesn't let you inject them inline, or if you don't fancy doing font icons, etc.
Late to the show here, BUT, I was able to add a fill color to the SVG polygon, if you're able to directly edit the SVG code, so for example the following svg renders red, instead of default black. I have not tested outside of Chrome though:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
<polygon
fill="red"
fill-rule="evenodd" clip-rule="evenodd" points="452.5,233.85 452.5,264.55 110.15,264.2 250.05,390.3 229.3,413.35
47.5,250.7 229.3,86.7 250.05,109.75 112.5,233.5 "/>
</svg>
The only way i found for this, and to be cross browser (aka bulletproof), is to render the SVG with PHP and pass Query String to set the color.
The SVG, here called "arrow.php"
<?php
$fill = filter_input(INPUT_GET, 'fill');
$fill = strtolower($fill);
$fill = preg_replace("/[^a-z0-9]/", '', $fill);
if(empty($fill)) $fill = "000000";
header('Content-type: image/svg+xml');
echo '<?xml version="1.0" encoding="utf-8"?>';
?>
<svg xmlns="http://www.w3.org/2000/svg" width="7.4" height="12" viewBox="0 0 7.4 12">
<g>
<path d="M8.6,7.4,10,6l6,6-6,6L8.6,16.6,13.2,12Z" transform="translate(-8.6 -6)" fill="#<?php echo htmlspecialchars($fill); ?>" fill-rule="evenodd"/>
</g>
</svg>
Then you call the image like this
.cssclass{ background-image: url(arrow.php?fill=112233); }
Works only with PHP. And remember that everytime you change the color value, your browser will load a new image.
scss create function
#function url-svg($icon) {
#return url("data:image/svg+xml;utf8,#{str-replace($icon, "#", "%23")}");
}
scss use
url-svg('<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="#8A8A8F"/></svg>')
css generated
url('data:image/svg+xml;utf8,<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="%238A8A8F"/></svg>')
The str-replace function is used from bootstrap.
Here is another solution using a gradient and a monochrome icon as background and background-blend-mode to colorize the icon.
It requires the background-color to be white, else the whole background gets colored. I only tested on Chrome.
.colored-background {
background-image: linear-gradient(45deg, green, green), url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-color: #fff;
background-blend-mode: lighten, normal;
background-repeat: no-repeat;
background-position: center, center right .8em;
background-size: auto, 0.6em;
color: red;
display: inline-flex;
align-items: center;
padding: 0.5em;
padding-right: 2em;
height: 1.6em;
width: auto;
border: 1px solid gray;
}
.bg {
background-color: #ddd;
padding: 1em;
}
<div class="bg">
<div class="colored-background">green icon from black svg</div>
</div>
Related to a closed question that is linked to here, but not related directly to this question.
So in case, anyone needs actually to replace src like in the linked question, there is already an answer there. Furthermore if anyone is coming from Vue, and the src path is change on compile, I've come up with a different solution.
In my case, the parent element is a link, but it could be anything really.
<a
v-for="document in documents" :key="document.uuid"
:href="document.url"
target="_blank"
class="item flex align-items-center gap-2 hover-parent"
>
<img alt="documents" class="icon" src="../assets/PDF.svg" />
<strong>{{ document.name }}</strong>
<img class="itemImage ml-auto hide-on-parent-hover" src="../assets/download-circular-button.svg" />
<img class="itemImage ml-auto show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</a>
.hover-parent .show-on-parent-hover { display: none }
.hover-parent .hide-on-parent-hover { display: block }
.hover-parent:hover .show-on-parent-hover { display: block }
.hover-parent:hover .hide-on-parent-hover { display: none }
So the solution here is not to change src attribute, but instead to put both <img> elements in the DOM and only display the one that is needed.
If you don't have a parent element that's supposed to be hovered on, you can simply wrap both images in a div.
<div class="hover-parent" >
<img class="hide-on-parent-hover" src="../assets/download-circular-button.svg" />
<img class="show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</div>
You might also change CSS to the following, so the .hover-parent ancestor must be a direct parent:
.hover-parent > .show-on-parent-hover { display: none }
.hover-parent > .hide-on-parent-hover { display: block }
.hover-parent:hover > .show-on-parent-hover { display: block }
.hover-parent:hover > .hide-on-parent-hover { display: none }
This is my favorite method, but your browser support must be very progressive. With the mask property you create a mask that is applied to an element. Everywhere the mask is opaque, or solid, the underlying image shows through. Where it’s transparent, the underlying image is masked out, or hidden. The syntax for a CSS mask-image is similar to background-image.look at the codepenmask
A lot of IFs, but if your pre base64 encoded SVG starts:
<svg fill="#000000
Then the base64 encoded string will start:
PHN2ZyBmaWxsPSIjMDAwMDAw
if the pre-encoded string starts:
<svg fill="#bfa76e
then this encodes to:
PHN2ZyBmaWxsPSIjYmZhNzZl
Both encoded strings start the same:
PHN2ZyBmaWxsPSIj
The quirk of base64 encoding is every 3 input characters become 4 output characters. With the SVG starting like this then the 6-character hex fill color starts exactly on an encoding block 'boundary'.
Therefore you can easily do a cross-browser JS replace:
output = input.replace(/MDAwMDAw/, "YmZhNzZl");
But tnt-rox answer above is the way to go moving forward.
I am trying to center that base64 background-image inside an horizontal rectangle div, and it just does not work.
I know it should be pretty trivial and I looked into many almost similar questions here, but no trick worked. The image is not centered horizontally and i do not know why.
In fact, background-position does not seem to take any effect unless I use pixels explicitly.
you can see it in this playground:
https://codesandbox.io/s/solitary-worker-vvrx4?file=/index.html
.container {
background: red;
width: 100px;
height: 16px;
background-image:url("data:image/svg+xml;base64,...");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
<div class="container"></div>
Could somebody please help?
Thank you.
Looks like the problem is with your SVG. Made a fell changes on it and generated a new base64 that worked fine. I'm not so sure why this solved, though.
What I did:
Changed transform="rotate(90 8 8)" to transform="rotate(90)"
Added specific width and height properties width="160" height="160"
Heres the result
.icon {
background: red;
width: 100px;
height: 16px;
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.icon--broken {
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIxLjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA4IDgpIiBmaWxsPSIjMzM5OWZmIj4KPGc+Cgk8Y2lyY2xlIGN4PSI3LjgiIGN5PSIxMy45IiByPSIxLjciLz4KCTxwYXRoIGQ9Ik03LjgsMTEuOGMxLjIsMCwyLjEsMC45LDIuMSwyLjFDOS45LDE1LjEsOSwxNiw3LjgsMTZzLTIuMS0wLjktMi4xLTIuMUM1LjcsMTIuNyw2LjcsMTEuOCw3LjgsMTEuOHoiLz4KPC9nPgo8Zz4KCTxjaXJjbGUgY3g9IjcuOCIgY3k9IjcuOSIgcj0iMS43Ii8+Cgk8cGF0aCBkPSJNNy44LDUuOGMxLjIsMCwyLjEsMC45LDIuMSwyLjFDOS45LDkuMSw5LDEwLDcuOCwxMFM1LjcsOS4xLDUuNyw3LjlDNS43LDYuOCw2LjcsNS44LDcuOCw1Ljh6Ii8+CjwvZz4KPGc+Cgk8Y2lyY2xlIGN4PSI3LjgiIGN5PSIyLjEiIHI9IjEuNyIvPgoJPHBhdGggZD0iTTcuOCwwQzksMCw5LjksMC45LDkuOSwyLjFjMCwxLjItMC45LDIuMS0yLjEsMi4xUzUuNywzLjMsNS43LDIuMUM1LjcsMC45LDYuNywwLDcuOCwweiIvPgo8L2c+Cjwvc3ZnPgo=");
}
.icon--fixed {
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIxLjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE2IDE2OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgdHJhbnNmb3JtPSJyb3RhdGUoOTApIiBmaWxsPSIjMzM5OWZmIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjE2MCI+CjxnPgoJPGNpcmNsZSBjeD0iNy44IiBjeT0iMTMuOSIgcj0iMS43Ii8+Cgk8cGF0aCBkPSJNNy44LDExLjhjMS4yLDAsMi4xLDAuOSwyLjEsMi4xQzkuOSwxNS4xLDksMTYsNy44LDE2cy0yLjEtMC45LTIuMS0yLjFDNS43LDEyLjcsNi43LDExLjgsNy44LDExLjh6Ii8+CjwvZz4KPGc+Cgk8Y2lyY2xlIGN4PSI3LjgiIGN5PSI3LjkiIHI9IjEuNyIvPgoJPHBhdGggZD0iTTcuOCw1LjhjMS4yLDAsMi4xLDAuOSwyLjEsMi4xQzkuOSw5LjEsOSwxMCw3LjgsMTBTNS43LDkuMSw1LjcsNy45QzUuNyw2LjgsNi43LDUuOCw3LjgsNS44eiIvPgo8L2c+CjxnPgoJPGNpcmNsZSBjeD0iNy44IiBjeT0iMi4xIiByPSIxLjciLz4KCTxwYXRoIGQ9Ik03LjgsMEM5LDAsOS45LDAuOSw5LjksMi4xYzAsMS4yLTAuOSwyLjEtMi4xLDIuMVM1LjcsMy4zLDUuNywyLjFDNS43LDAuOSw2LjcsMCw3LjgsMHoiLz4KPC9nPgo8L3N2Zz4K");
}
<div class="icon icon--broken"></div>
<div class="icon icon--fixed"></div>
The problem is not CSS but the SVG image inside the base64 string. When you open it, you find the following code:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve" transform="rotate(90 8 8)" fill="#9c9c9c">
<g>
<circle cx="7.8" cy="13.9" r="1.7"/>
<path d="M7.8,11.8c1.2,0,2.1,0.9,2.1,2.1C9.9,15.1,9,16,7.8,16s-2.1-0.9-2.1-2.1C5.7,12.7,6.7,11.8,7.8,11.8z"/>
</g>
<g>
<circle cx="7.8" cy="7.9" r="1.7"/>
<path d="M7.8,5.8c1.2,0,2.1,0.9,2.1,2.1C9.9,9.1,9,10,7.8,10S5.7,9.1,5.7,7.9C5.7,6.8,6.7,5.8,7.8,5.8z"/>
</g>
<g>
<circle cx="7.8" cy="2.1" r="1.7"/>
<path d="M7.8,0C9,0,9.9,0.9,9.9,2.1c0,1.2-0.9,2.1-2.1,2.1S5.7,3.3,5.7,2.1C5.7,0.9,6.7,0,7.8,0z"/>
</g>
</svg>
Notice the transform="rotation(90 8 8)" attribute. It rotates the image by 90 degrees around the point [8,8]. The point should be the center of the image according to viewBox="0 0 16 16" but for some reason, the dimensions get broken, and an offset of 16 pixels is allocated on the left side of the image.
The simplest fix is to change the value of the transform attribute to rotation(90). The fixed image in base64 is:
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDE2IDE2IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAxNiAxNjsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHRyYW5zZm9ybT0icm90YXRlKDkwKSIgZmlsbD0iIzljOWM5YyI+CjxnPgoJPGNpcmNsZSBjeD0iNy44IiBjeT0iMTMuOSIgcj0iMS43Ii8+Cgk8cGF0aCBkPSJNNy44LDExLjhjMS4yLDAsMi4xLDAuOSwyLjEsMi4xQzkuOSwxNS4xLDksMTYsNy44LDE2cy0yLjEtMC45LTIuMS0yLjFDNS43LDEyLjcsNi43LDExLjgsNy44LDExLjh6Ii8+CjwvZz4KPGc+Cgk8Y2lyY2xlIGN4PSI3LjgiIGN5PSI3LjkiIHI9IjEuNyIvPgoJPHBhdGggZD0iTTcuOCw1LjhjMS4yLDAsMi4xLDAuOSwyLjEsMi4xQzkuOSw5LjEsOSwxMCw3LjgsMTBTNS43LDkuMSw1LjcsNy45QzUuNyw2LjgsNi43LDUuOCw3LjgsNS44eiIvPgo8L2c+CjxnPgoJPGNpcmNsZSBjeD0iNy44IiBjeT0iMi4xIiByPSIxLjciLz4KCTxwYXRoIGQ9Ik03LjgsMEM5LDAsOS45LDAuOSw5LjksMi4xYzAsMS4yLTAuOSwyLjEtMi4xLDIuMVM1LjcsMy4zLDUuNywyLjFDNS43LDAuOSw2LjcsMCw3LjgsMHoiLz4KPC9nPgoJCjwvc3ZnPg==
You have to increase the width of the container.
You can see it in this playground: https://codesandbox.io/s/admiring-monad-lwqlk?file=/index.html
I'm having trouble with a svg pattern background that is not repeating on the x-axis in IE11 (and probably other IEs) and the Android native browser.
Apparently I should add preserveAspectRatio: "none slice" to the svg element, but what if the svg is used as background-image?
CSS
header.logoheader:after {
background-image: url('patroon5.svg');
background-size: auto 100%;
background-repeat: repeat-x;
content: "";
display: block;
height: 100px;
left: 0;
position: absolute;
top: 40px;
width: 100%;
}
(I'm using the :after selector so the transparent pattern covers the div)
In my HTML there is no svg element to add the preserveAspectRatio to. I'm thinking this is because of the :after selector.
Anyone got an solution?
You can either edit the background image svg file to include it or alternatively use an SVG fragment identifier i.e.
background-image: url('patroon5.svg#svgView(preserveAspectRatio(none))');
Had this kind of problem before on IE. To fix it you have to edit your svg file then remove the set width and height assuming you have viewBox set in there. Then add preserveAspectRatio="xMinYMid" as an attribute.
e.g.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
preserveAspectRatio="xMinYMid" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
I want to use an svg image in 100% width which has as filled background from the top left to the bottom right. I've tried several ways to make it always 100% wide (background-size, etc.) but it doesn't work.
If I'm opening the svg source code, there are several "fix" widths. Maybe this is the problem. But I don't know how I could fix it.
It would be great if I could place this swg as a background of a div. (using css)
Here is my svg Code:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!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" x="0px" y="0px"
width="1280px" height="70px" viewBox="0 0 1280 70" enable-background="new 0 0 1280 70" xml:space="preserve">
<polygon points="1280,70 0,70 0,0 "/>
</svg>
Does anybody have an idea how to fix this? I also thought about another way, with an rotated div container. But I think svg is the best way.
Here you can see an example:
jsfiddle.net/maszzfom
Remove width and height
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1280 70" enable-background="new 0 0 1280 70" xml:space="preserve" preserveAspectRatio="none">
<polygon points="1280,70 0,70 0,0 "/>
</svg>
css
svg{width:100%}
resource on responsive svg
Demo
upate: save the svg as file and use it like this
.element {
background-image: url(image.svg);
/* other styles */
}
If you want a pure css solute the give pseudo element or linear-gradient a try
If the triangle doesn't have content by itself (just decoration), it should be defined in the CSS.
Following your example with a triangle ( 100% width and static height 70px), you could achieve it as:
.triangle {
position: relative;
}
.triangle:before {
background-repeat: no-repeat;
background-size: 100% 100%;
content: '';
display: block;
position: absolute;
width: 100%;
left: 0;
bottom: -70px;
height: 70px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpolygon points='100,0 100,100 0,100' style='fill:%23000000;' /%3E%3C/svg%3E");
}
<div class="triangle"></div>
The triangle coordinates are possible to invert: points='0,0 0,100 100,100'
You could change the triangle color: "fill:%23000000;"
The CSS works with :before and :after, depending your needs!
Fiddle: http://jsfiddle.net/b8czxyzg/