Change SVG fill color in :before or :after CSS
Using the content
property generates (non-exposed) markup functionally equvialent to an svg in an <img> element.
You cannot apply style to elements inside the svg document because:
- styles are not allowed to cascade across documents
- when using <img> (or
content
, or any css image property that references svg) the svg document is not exposed by the browsers due to security concerns
Similar questions, but for background-image
here and here.
So, to do what you want you must get around the two points above somehow. There are various options for doing that, e.g using inline svg, using filters (applied to the <img>) or generating different svg files (or data URIs), as in your question.
How to change the color of an svg element?
You can't change the color of an image that way. If you load SVG as an image, you can't change how it is displayed using CSS or Javascript in the browser.
If you want to change your SVG image, you have to load it using <object>
, <iframe>
or using <svg>
inline.
If you want to use the techniques in the page, you need the Modernizr library, where you can check for SVG support and conditionally display or not a fallback image. You can then inline your SVG and apply the styles you need.
See :
#time-3-icon { fill: green;}
.my-svg-alternate { display: none;}.no-svg .my-svg-alternate { display: block; width: 100px; height: 100px; background-image: url(image.png);}
<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path id="time-3-icon" d="M256,50C142.229,50,50,142.229,50,256c0,113.77,92.229,206,206,206c113.77,0,206-92.23,206-206 C462,142.229,369.77,50,256,50z M256,417c-88.977,0-161-72.008-161-161c0-88.979,72.008-161,161-161c88.977,0,161,72.007,161,161 C417,344.977,344.992,417,256,417z M382.816,265.785c1.711,0.297,2.961,1.781,2.961,3.518v0.093c0,1.72-1.223,3.188-2.914,3.505 c-37.093,6.938-124.97,21.35-134.613,21.35c-13.808,0-25-11.192-25-25c0-9.832,14.79-104.675,21.618-143.081 c0.274-1.542,1.615-2.669,3.181-2.669h0.008c1.709,0,3.164,1.243,3.431,2.932l18.933,119.904L382.816,265.785z"/></svg>
<image class="my-svg-alternate" width="96" height="96" src="ppngfallback.png" />
Change color/fill of a SVG path when used in the content of a ::before pseudo-element
You could use a mask.
div::before {
display: inline-block;
width: 18px;
height: 18px;
content: '';
background: var(--c);
-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'><path d='M350.85 129c25.97 4.67 47.27 18.67 63.92 42 14.65 20.67 24.64 46.67 29.96 78 4.67 28.67 4.32 57.33-1 86-7.99 47.33-23.97 87-47.94 119-28.64 38.67-64.59 58-107.87 58-10.66 0-22.3-3.33-34.96-10-8.66-5.33-18.31-8-28.97-8s-20.3 2.67-28.97 8c-12.66 6.67-24.3 10-34.96 10-43.28 0-79.23-19.33-107.87-58-23.97-32-39.95-71.67-47.94-119-5.32-28.67-5.67-57.33-1-86 5.32-31.33 15.31-57.33 29.96-78 16.65-23.33 37.95-37.33 63.92-42 15.98-2.67 37.95-.33 65.92 7 23.97 6.67 44.28 14.67 60.93 24 16.65-9.33 36.96-17.33 60.93-24 27.98-7.33 49.96-9.67 65.94-7zm-54.94-41c-9.32 8.67-21.65 15-36.96 19-10.66 3.33-22.3 5-34.96 5l-14.98-1c-1.33-9.33-1.33-20 0-32 2.67-24 10.32-42.33 22.97-55 9.32-8.67 21.65-15 36.96-19 10.66-3.33 22.3-5 34.96-5l14.98 1 1 15c0 12.67-1.67 24.33-4.99 35-3.99 15.33-10.31 27.67-18.98 37z'/></svg>") center no-repeat;
}
<div style="--c:red;"></div>
<div style="--c:orange;"></div>
<div style="--c:yellow;"></div>
<div style="--c:green;"></div>
<div style="--c:blue;"></div>
<div style="--c:indigo;"></div>
<div style="--c:violet;"></div>
I want to change the color of svg while it is in outer file and imported with img tag
You're correct that you can't change an SVG's fill
attribute via CSS if you use it in the src
of an img
tag – you need to have the contents of the SVG in your document.
You could try using CSS filter
to change the appearance of the image though, in particular the brightness
or invert
options:
<img src="myimage.svg" class="invert">
<style>
.grayscale { filter: grayscale(100%); }
.contrast { filter: contrast(160%); }
.brightness { filter: brightness(0.25); }
.invert { filter: invert(100%); }
</style>
CSS - SVG in a pseudo element with Color changing capabilities
This is easy if you flip the logic - instead of adding color on the hover - think of it as removing color when you are not hovering.
With CSS filters - you can convert your svg to greyscale - meaning that a color image / SVG is rendered as a black and white image. Then on hover - stop the filter / conversion and your svg will have its actual color.
Note that this only works with one color change - you cannot have different paths go different colors etc - but by reversing the color logic you get a black and white svg that turns colorful on hover.
The following div has a border - just to show the dimensions (and I would probably do the svg as the background image of the div rather than the ::before - but I left it as requested. The SVG is iniitally shown as black and on hover over the div - the svg turns red.... magic :)
div {
height: 160px;
width: 300px;
border: solid 1px blue;
position: relative
}
div::before {
content: url('data:image/svg+xml;utf8,<svg version="1.1" id="" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink" style="" xml:space="preserve"><path d="M150 0 L75 200 L225 200 Z" fill="red"></path></svg>');
display: block;
-webkit-filter: grayscale(100);
filter: grayscale(100);
}
div:hover:before{
-webkit-filter: grayscale(0);
filter: grayscale(0);
}
<div></div>
Svg color not changing from css color?
Most likely there is something wrong in your css.
Maybe a specificty issue (e.g previously declared svg color styles).
It should work like this:
body{
font-size: 3vw;
}
.green{
color: green
}
.red{
color: red
}
.fill-gray svg{
fill: #ccc;
}
.svg-inline{
display:inline-block;
font-size:1em;
height:1em;
width:1em;
}
<p class="green">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="ionicon svg-inline" viewBox="0 0 512 512">
<title>Logo Instagram</title>
<g id="icon-instagram">
<path id="path1" d="M349.33 69.33a93.62 93.62 0 0193.34 93.34v186.66a93.62 93.62 0 01-93.34 93.34H162.67a93.62 93.62 0 01-93.34-93.34V162.67a93.62 93.62 0 0193.34-93.34h186.66m0-37.33H162.67C90.8 32 32 90.8 32 162.67v186.66C32 421.2 90.8 480 162.67 480h186.66C421.2 480 480 421.2 480 349.33V162.67C480 90.8 421.2 32 349.33 32z"/>
<path id="path2" d="M377.33 162.67a28 28 0 1128-28 27.94 27.94 0 01-28 28zM256 181.33A74.67 74.67 0 11181.33 256 74.75 74.75 0 01256 181.33m0-37.33a112 112 0 10112 112 112 112 0 00-112-112z"/>
</g>
</svg>
green icon
</p>
<p class="red">
<svg class="svg-inline" fill="currentColor" viewBox="0 0 512 512">
<use href="#icon-instagram" />
</svg> Inline Icon (fill inherited by parent's color)
</p>
<p class="red fill-gray">
<svg class="svg-inline" fill="currentColor" viewBox="0 0 512 512">
<use href="#icon-instagram" />
</svg> Inline Icon (fill color overridden by fill property)
</p>
<p class="red">
<svg class="svg-inline" viewBox="0 0 512 512">
<use href="#icon-instagram" />
</svg> Inline Icon (fill color can't be inherited, since fill="currentColor" is missing )
</p>
How to change color of SVG image using CSS (jQuery SVG image replacement)?
Firstly, use an IMG tag in your HTML to embed an SVG graphic. I used Adobe Illustrator to make the graphic.
<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>
This is just like how you'd embed a normal image. Note that you need to set the IMG to have a class of svg. The 'social-link' class is just for examples sake. The ID is not required, but is useful.
Then use this jQuery code (in a separate file or inline in the HEAD).
/**
* Replace all SVG images with inline SVG
*/
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(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);
}, 'xml');
});
What the above code does is look for all IMG's with the class 'svg' and replace it with the inline SVG from the linked file. The massive advantage is that it allows you to use CSS to change the color of the SVG now, like so:
svg:hover path {
fill: red;
}
The jQuery code I wrote also ports across the original images ID and classes. So this CSS works too:
#facebook-logo:hover path {
fill: red;
}
Or:
.social-link:hover path {
fill: red;
}
You can see an example of it working here:
http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html
We have a more complicated version that includes caching here:
https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90
Related Topics
How to Change an Element Type Using Jquery
Why How to Access Typescript Private Members When I Shouldn't Be Able To
Differencebetween $(Window).Load and $(Document).Ready
Es6 Object Destructuring Default Parameters
JavaScript Date Object Comparison
How to Get the Title of HTML Page with JavaScript
How to Make a Radio Button Unchecked by Clicking It
:Touch CSS Pseudo-Class or Something Similar
How to Add "Href" Attribute to a Link Dynamically Using JavaScript
Is There an Alternative Method to Use Onbeforeunload in Mobile Safari
Fcm - Programmatically Send Push Notification to User Segments
How Does Linux Emulator in JavaScript by Fabrice Bellard Work
Confusion About Node.Js Internal Asynchronous I/O Mechanism
Draw a Circle Around Nodes Groups
How to Change Reactjs Styles Dynamically