[css] How to change the color of an svg element?

I want to use this technique and change the SVG color, but so far I haven't been able to do so. I put this in the CSS, but my image is always black, no matter what.

My code:

_x000D_
_x000D_
.change-my-color {
  fill: green;
}
_x000D_
<svg>
    <image class="change-my-color" xlink:href="https://svgur.com/i/AFM.svg" width="96" height="96" src="ppngfallback.png" />
</svg>
_x000D_
_x000D_
_x000D_

This question is related to css svg

The answer is


Actually, there is a quite more flexible solution to this problem: writing a Web Component which will patch SVG as text in runtime. Also published in gist with a link to JSFiddle

filter: invert(42%) sepia(93%) saturate(1352%) hue-rotate(87deg) brightness(119%) contrast(119%);

<html>

<head>
  <title>SVG with color</title>
</head>

<body>
  <script>
    (function () {
      const createSvg = (color = '#ff9933') => `
          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="76px" height="22px" viewBox="-0.5 -0.5 76 22">
            <defs/>
              <g>
                <ellipse cx="5" cy="10" rx="5" ry="5" fill="#ff9933" stroke="none" pointer-events="all"/>
                <ellipse cx="70" cy="10" rx="5" ry="5" fill="#ff9933" stroke="none" pointer-events="all"/>
                <path d="M 9.47 12.24 L 17.24 16.12 Q 25 20 30 13 L 32.5 9.5 Q 35 6 40 9 L 42.5 10.5 Q 45 12 50 6 L 52.5 3 Q 55 0 60.73 3.23 L 66.46 6.46" fill="none" stroke="#ff9933" stroke-miterlimit="10" pointer-events="stroke"/>
              </g>
          </svg>`.split('#ff9933').join(color);

      function SvgWithColor() {
        const div = Reflect.construct(HTMLElement, [], SvgWithColor);
        const color = div.hasAttribute('color') ? div.getAttribute('color') : 'cyan';
        div.innerHTML = createSvg(color);
        return div;
      }

      SvgWithColor.prototype = Object.create(HTMLElement.prototype);
      customElements.define('svg-with-color', SvgWithColor);

      document.body.innerHTML += `<svg-with-color
        color='magenta' 
      ></svg-with-color>`;

    })();

  </script>
</body>

</html>

if you want to change the color dynamically:

  1. Open de svg in a code editor
  2. Add or rewrite the attribute of fill of every path to fill="currentColor"
  3. Now, that svg will take the color of your font color so you can do something like:
svg {
    color : "red";
}

SVG mask on a box element with a background color will result:

_x000D_
_x000D_
body{ overflow:hidden; }

.icon {
  --size: 70px;
  display: inline-block;
  width: var(--size);
  height: var(--size);
  transition: .12s;
  
  -webkit-mask-size: cover;
  mask-size: cover;
}

.icon-bike {
  background: black;
  animation: 4s frames infinite linear;
  
  -webkit-mask-image: url(https://image.flaticon.com/icons/svg/89/89139.svg);
  mask-image: url(https://image.flaticon.com/icons/svg/89/89139.svg);
}

@keyframes frames {
  0% { transform:translatex(100vw) }
  25% { background: red; }
  75% { background: lime; }
  100% { transform:translatex(-100%) }
}
_x000D_
<i class="icon icon-bike" style="--size:150px"></i>
_x000D_
_x000D_
_x000D_


Note - SVG masks are not supported in Internet Explorer browsers


shortest Bootstrap-compatible way, no JavaScript:

.cameraicon {
height: 1.6em;/* set your own icon size */
mask: url(/camera.svg); /* path to your image */
-webkit-mask: url(/camera.svg) no-repeat center;
}

and use it like:

<td class="text-center">
    <div class="bg-secondary cameraicon"/><!-- "bg-secondary" sets actual color of your icon -->
</td>

If you want to use css to change the colour, you could also use an online tool like this one: https://change-svg-color.vercel.app/


Target the path within the svg:

<svg>
   <path>....
</svg>

You can do inline, like:

<path fill="#ccc">

Or

svg{
   path{
        fill: #ccc

here the fast&furious way :)

_x000D_
_x000D_
 body{
 background-color: #deff05;
 }
 
 svg{
   width: 30%;
    height: auto;
 }
 
 svg path {
    color:red;
    fill: currentcolor;
}
_x000D_
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 514.666 514.666"><path d="M514.666,210.489L257.333,99.353L0,210.489l45.933,19.837v123.939h30V243.282l33.052,14.274v107.678l4.807,4.453  c2.011,1.862,50.328,45.625,143.542,45.625c93.213,0,141.53-43.763,143.541-45.626l4.807-4.452V257.557L514.666,210.489z   M257.333,132.031L439,210.489l-181.667,78.458L75.666,210.489L257.333,132.031z M375.681,351.432  c-13.205,9.572-53.167,33.881-118.348,33.881c-65.23,0-105.203-24.345-118.348-33.875v-80.925l118.348,51.112l118.348-51.111  V351.432z"></path></svg>
_x000D_
_x000D_
_x000D_


2020 answer

CSS Filter works on all current browsers

To change any SVGs color

  1. Add the SVG image using an <img> tag.
<img src="dotted-arrow.svg" class="filter-green"/>
  1. To filter to a specific color, use the following Codepen(Click Here to open codepen) to convert a hex color code to a CSS filter:

For example, output for #00EE00 is

filter: invert(42%) sepia(93%) saturate(1352%) hue-rotate(87deg) brightness(119%) contrast(119%);
  1. Add the CSS filter into this class.
    .filter-green{
        filter: invert(48%) sepia(79%) saturate(2476%) hue-rotate(86deg) brightness(118%) contrast(119%);
    }

A good approach is to use a mixin to control stroke colour and fill colour. My svgs are used as icons.

@mixin icon($color, $hoverColor) {
    svg {
        fill: $color;

        circle, line, path {
            fill: $color
        }

        &:hover {
            fill: $hoverColor;

            circle, line, path {
                fill: $hoverColor;
            }
        }
    }
}

You can then do the following in your scss:

.container {
    @include icon(white, blue);
}

  1. Method 1

The easy and effect way

open your .svg file with any text editor

<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" 
   xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 477.526 477.526" style="enable-background:new 0 0 477.526 477.526; 
   fill: rgb(109, 248, 248);" xml:space="preserve"> 
<svg />

give an style attribute and fill that with color

  1. Another way

fill with color in your shape here i have rect shape fill="white

<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
      <g>
          <title>background</title>
          <rect fill="#fff" id="canvas_background" height="602" width="802" y="-1" 
           x="-1"/>
           <g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" 
           id="canvasGrid">
              <rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" 
              width="100%"/>
           </g>
       </g>
</svg>

If you want to do this to an inline svg that is, for example, a background image in your css:

_x000D_
_x000D_
background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='rgba(31,159,215,1)' viewBox='...'/%3E%3C/svg%3E");
_x000D_
_x000D_
_x000D_

of course, replace the ... with your inline image code


To change the color of any SVG you can directly change the svg code by opening the svg file in any text editor. The code may look like the below code

<?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 16.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="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
    <g>
        <path d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
            C181.113,454.921,171.371,464.663,161.629,474.404z"/>
    /*Some more code goes on*/
    </g>
    </svg>

You can observe that there are some XML tags like path, circle, polygon etc. There you can add your own color with help of style attribute. Look at the below example

<path style="fill:#AB7C94;" d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
                C181.113,454.921,171.371,464.663,161.629,474.404z"/>

Add the style attribute to all the tags so that you can get your SVG of your required color


For Example, in your HTML:

<body>
  <svg viewBox="" width="" height="">
    <path id="struct1" fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
  </svg>
</body>

Use jQuery:

$("#struct1").css("fill","<desired colour>");

You can try with filter hack:

.colorize-pink {
  filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5);
}

.colorize-navy {
  filter: brightness(0.2) sepia(1) hue-rotate(180deg) saturate(5);
}

.colorize-blue {
  filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6);
}

Open your image using a browser, right-click on the image click on view page source and you will see the svg tag of the image. Cope and paste into your html, then change the fill to the colour of your choice


the easiest way would be to create a font out of the SVG using a service like https://icomoon.io/app/#/select or such. upload your SVG, click "generate font", include font files and css into your side and just use and style it like any other text. I always use it like this because it makes styling much easier.

EDIT: As mentioned in the article commented by @CodeMouse92 icon fonts mess up screen readers (and are possibly bad for SEO). So rather stick to the SVGs.


Added a test page - to color SVG via Filter settings:

E.G filter: invert(0.5) sepia(1) saturate(5) hue-rotate(175deg)

Upload & Color your SVG - Jsfiddle

Took the idea from: https://blog.union.io/code/2017/08/10/img-svg-fill/


Simply add fill:"desiredColor" in the svg tag of the image: example:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#bbb9c6">
<path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

To change color of SVG element I have found out a way while inspecting Google search box search icon below:

_x000D_
_x000D_
.search_icon {
  color: red;
  fill: currentColor;
  display: inline-block;
  width: 100px;
  height: 100px;
}
_x000D_
<span class="search_icon">
    <svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></svg>
</span>
_x000D_
_x000D_
_x000D_

I have used span element with "display:inline-block", height, width and setting a particular style "color: red; fill: currentColor;" to that span tag which is inherited by the child svg element.


Only SVG with path information. you can't do that to the image.. as the path you can change stroke and fill information and you are done. like Illustrator

so: via CSS you can overwrite path fill value

path { fill: orange; }

but if you want more flexible way as you want to change it with a text when having some hovering effect going on.. use

path { fill: currentcolor; }

_x000D_
_x000D_
body {_x000D_
  background: #ddd;_x000D_
  text-align: center;_x000D_
  padding-top: 2em;_x000D_
}_x000D_
_x000D_
.parent {_x000D_
  width: 320px;_x000D_
  height: 50px;_x000D_
  display: block;_x000D_
  transition: all 0.3s;_x000D_
  cursor: pointer;_x000D_
  padding: 12px;_x000D_
  box-sizing: border-box;_x000D_
}_x000D_
_x000D_
/***  desired colors for children  ***/_x000D_
.parent{_x000D_
  color: #000;_x000D_
  background: #def;_x000D_
}_x000D_
.parent:hover{_x000D_
  color: #fff;_x000D_
  background: #85c1fc;_x000D_
}_x000D_
_x000D_
.parent span{_x000D_
  font-size: 18px;_x000D_
  margin-right: 8px;_x000D_
  font-weight: bold;_x000D_
  font-family: 'Helvetica';_x000D_
  line-height: 26px;_x000D_
  vertical-align: top;_x000D_
}_x000D_
.parent svg{_x000D_
  max-height: 26px;_x000D_
  width: auto;_x000D_
  display: inline;_x000D_
}_x000D_
_x000D_
/****  magic trick  *****/_x000D_
.parent svg path{_x000D_
  fill: currentcolor;_x000D_
}
_x000D_
<div class='parent'>_x000D_
  <span>TEXT WITH SVG</span>_x000D_
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 32 32">_x000D_
<path d="M30.148 5.588c-2.934-3.42-7.288-5.588-12.148-5.588-8.837 0-16 7.163-16 16s7.163 16 16 16c4.86 0 9.213-2.167 12.148-5.588l-10.148-10.412 10.148-10.412zM22 3.769c1.232 0 2.231 0.999 2.231 2.231s-0.999 2.231-2.231 2.231-2.231-0.999-2.231-2.231c0-1.232 0.999-2.231 2.231-2.231z"></path>_x000D_
</svg>_x000D_
</div>
_x000D_
_x000D_
_x000D_


To simply change the color of the svg :

Go to the svg file and under styles, mention the color in fill.

<style>.cls-1{fill:#FFFFFF;}</style>

Use an svg <mask> element. This works in IE too!

Bonus: color is inherited from font-color, so easy to use alongside text.

_x000D_
_x000D_
<svg style="color: green; width: 96px; height: 96px" viewBox="0 0 100 100" preserveAspectRatio="none">
  <defs>
    <mask id="fillMask" x="0" y="0" width="100" height="100">
      <image xlink:href="https://svgur.com/i/AFM.svg" x="0" y="0" width="100" height="100" src="ppngfallback.png" />
    </mask>
  </defs>
  <rect x="0" y="0" width="100" height="100" style="stroke: none; fill: currentColor" mask="url(&quot;#fillMask&quot;)" />
</svg>
_x000D_
_x000D_
_x000D_

https://jsfiddle.net/jamiegl/5jaL0s1t/19/


You can change SVG coloring with css if you use some tricks. I wrote a small script for that.

  • go through a list of elements which do have an svg image
  • load the svg file as xml
  • fetch only svg part
  • change color of path
  • replace src with the modified svg as inline image
$('img.svg-changeable').each(function () {
  var $e = $(this);
  var imgURL = $e.prop('src');

  $.get(imgURL, function (data) {
    // Get the SVG tag, ignore the rest
    var $svg = $(data).find('svg');

    // change the color
    $svg.find('path').attr('fill', '#000');

    $e.prop('src', "data:image/svg+xml;base64," + window.btoa($svg.prop('outerHTML')));
  });

});

the code above might not be working correctly, I've implemented this for elements with an svg background image which works nearly similar to this. But anyway you have to modify this script to fit your case. hope it helped.