Change Svg Fill Color in :Before or :After CSS

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:

  1. styles are not allowed to cascade across documents
  2. 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



Leave a reply



Submit