11

Update: Yes, I know there are similar questions on SO, but the solutions don't work either.

I want to change SVG's color, I mean paths's color, not a color "inside" but the path itself.

I first tried with css, it did not work at all. Then with js, and it almost work:

This works, that is, an image is loaded. It's black by default.

<object id = 'test' data="images/icons/040__file_delete.svg" type="image/svg+xml"></object>

I want to change it to green.

    <script>
        $(function(){
            document.getElementById("test").addEventListener("load", function() {
                var doc = this.getSVGDocument();
                console.log(doc);//works fine
                var p = doc.querySelector("path"); //works
                p.setAttribute("stroke", "green");
            });    
        })
    </script>

The above does "work" but adds a "border" to the path. I also tried with "color", "fillcolor", "fill" - nothing works.

Update II: The SVG's source:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" id="图层_1" x="0px" y="0px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#231815;}
</style>
<g>
    <g>
        <g>
            <g>
                <g>
                    <path class="st0" d="M13,17.5H5c-1.4,0-2.5-1.1-2.5-2.5V3c0-1.4,1.1-2.5,2.5-2.5h3.6c0.4,0,0.8,0.2,1.1,0.4l5.4,5.4       c0.3,0.3,0.4,0.7,0.4,1.1V15C15.5,16.4,14.4,17.5,13,17.5z M5,1.5C4.2,1.5,3.5,2.2,3.5,3v12c0,0.8,0.7,1.5,1.5,1.5h8       c0.8,0,1.5-0.7,1.5-1.5V7.4c0-0.1-0.1-0.3-0.1-0.4L8.9,1.6C8.8,1.6,8.7,1.5,8.6,1.5H5z" fill="green"/>
                </g>
                <g>
                    <path class="st0" d="M15,7.5h-4C9.6,7.5,8.5,6.4,8.5,5V1c0-0.3,0.2-0.5,0.5-0.5S9.5,0.7,9.5,1v4c0,0.8,0.7,1.5,1.5,1.5h4       c0.3,0,0.5,0.2,0.5,0.5S15.3,7.5,15,7.5z"/>
                </g>
            </g>
            <g>
                <g>
                    <path class="st0" d="M10.5,13.9c-0.1,0-0.3,0-0.4-0.1l-3-3C7,10.5,7,10.2,7.1,10s0.5-0.2,0.7,0l3,3c0.2,0.2,0.2,0.5,0,0.7       C10.8,13.8,10.6,13.9,10.5,13.9z"/>
                </g>
                <g>
                    <path class="st0" d="M7.5,13.9c-0.1,0-0.3,0-0.4-0.1C7,13.5,7,13.2,7.1,13l3-3c0.2-0.2,0.5-0.2,0.7,0s0.2,0.5,0,0.7l-3,3       C7.8,13.8,7.6,13.9,7.5,13.9z"/>
                </g>
            </g>
        </g>
    </g>
</g>
</svg>
konrad_firm
  • 859
  • 1
  • 11
  • 28
  • 1
    `stroke` is a 'border' for a path. Either you want a fill or a stroke, and you have mentioned both, so I don't see what you want to accomplish. Can you put this into a `SO snippet` so we can see the problem? (Also I think that with `object` tags, you need to add a `style` element to the svg, I wasn't aware jQuery could read this shadow DOM) – somethinghere Mar 07 '16 at 13:23
  • @somethinghere - well, I don't want a stroke (outline) at all. I want the path itself to become green. Btw. I added content of done SVG. – konrad_firm Mar 07 '16 at 13:31
  • 1
    The stroke _is_ the colored version of your path. – somethinghere Mar 07 '16 at 13:37
  • 1
    @somethinghere no it is not, the paths describe the actual outlines of the image, so the property to set is `fill` not `stroke`. @konrad_firm As to why the color change is not working is that the element attribute `fill` does not actually override the css style, this can be done using `setAttribute('style', 'fill: green')`. Another issue you will run into is that `getSVGDocument` is not available in all browsers, so you could consider using inline SVG (but there is probably a reason you don't do this). – Rogier Spieker Mar 07 '16 at 14:02
  • 1
    @RogierSpieker I didn't say that he is setting the wrong property, but the path, when stroked, is exactly the stroke. I didn't say it's the _filled_ version of the path. I do have to say, including it as a regular `svg` element instead of an object is really the way to go, but older browsers (mostly IE) don't play nice with it. But yeah, if it's in the document, then it is easy to adjust it using _just_ css. – somethinghere Mar 07 '16 at 14:03
  • @RogierSpieker - setAttribute('style', 'fill: green') worked, thanks! That is, it only works on first path, but I know why and I think I'll handle this. If you add it as an answer I'll be glad to accept it. – konrad_firm Mar 07 '16 at 14:09
  • 1
    @somethinghere sorry, I read it as if `stroke` would produce what is visible now, but it would 'outline the outline' (as the paths describe the outlines as filled shaped). Consider me corrected ;-) – Rogier Spieker Mar 07 '16 at 14:09
  • @somethinghere I tried to play with stroke, I tried to set it to 0 or 1, in first case changing color didn't work, in later it did add an outline. I tried to put it on jsfiddle ( https://jsfiddle.net/ak5e83nq/ ) but it doesn't work o_O i.e. it doesn't display an image. – konrad_firm Mar 07 '16 at 14:12

4 Answers4

31

The fill and/or stroke attribute on the path(s) do not override the CSS styling (here's why).

What you need to do is override the CSS styling itself, this can be done by setting the style property, e.g.

<path style="fill:green" ...>

Or in javascript

element.setAttribute('style', 'fill: green');

In your response to my comment you mentioned you'd address the 'single path' issue, in order to provide an example for that too here's why and how to fix it.

The querySelector method only provides the first element (if any) that matches, you want to use the querySelectorAll method, which will provide a NodeList containing all matching elements.

var paths = doc.querySelectorAll("path"),
    i;

for (i = 0; i < paths.length: ++i) {
    paths[i].setAttribute('style', 'fill:green');
}

As I mentioned in my comment, the getSVGDocument() method may not exist on all browsers you need to support (I know nothing about your requirements, this is just a heads up), you may be interested in the .contentDocument property as described here

Community
  • 1
  • 1
Rogier Spieker
  • 4,087
  • 2
  • 22
  • 25
1

What happens here is that the object is not a simple path, but actually the whole "stroke" has been transformed into a big object. This may happen when you export objects with fancy (or not so fancy) brush settings from various drawing applications. You can also get the same result with the Outline feature in Adobe Illustrator, IIRC.

To avoid this, edit the original object in its original illustration software and try the following:

  1. Use a simple stroke, and no brush. This may work.
  2. Use no stroke in the original editor and apply it with JS or CSS in the SVG.
Gabriel R.
  • 1,186
  • 1
  • 15
  • 29
  • 1
    See this question for an explanation of the outline feature http://graphicdesign.stackexchange.com/q/45865/13414 – Gabriel R. Mar 07 '16 at 13:28
  • 1
    I added the content of the SVG. I don't see anything complicated there. And no, I don't want "stroke", I want to colorize the path itself. It's black right now, I want to change this. Let's say this path brings "O" shape - I want it like it is now, only that green. @gabriel-r – konrad_firm Mar 07 '16 at 13:34
1

Base on accepted answer, I created sample to click button and change color path.

Important thing:

I need host HTML file to webserver (IIS) to run it. If not it a.contentDocument always return null.

I share for whom concerned.

        var svgDoc;
        function changeColor() {
            svgDoc = a.contentDocument;
            // get the inner element by id
            var paths = svgDoc.querySelectorAll("path");
            // add behaviour
            for (i = 0; i < paths.length; i++) {
                paths[i].setAttribute('style', 'fill:pink');
            }
        }

        var a = document.getElementById("alphasvg");

        // It's important to add an load event listener to the object,
        // as it will load the svg doc asynchronously
        a.addEventListener("load", function () {

            // get the inner DOM of alpha.svg
            svgDoc = a.contentDocument;
            // get the inner element by id
            var paths = svgDoc.querySelectorAll("path");
            // add behaviour
            for (i = 0; i < paths.length; i++) {
                paths[i].setAttribute('style', 'fill:green');
            }

        }, false);
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    
    <object data="test.svg" type="image/svg+xml" id="alphasvg"></object>

    <button onclick="changeColor()">Change Color</button>

    <script>
      
    </script>
</body>

</html>
Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62
0

If i understand you want to color the stroke of the path is pretty simple: add stroke property to your SVG path then apply your color(rgb or hex or hsl)

<math fill="none" stroke: rgb(0,0,0) d="M50 30 L50 -10 C50 -10 90 -10 90 30 Z" />

Proau
  • 53
  • 3