122

I am trying to alter colors in an SVG with JavaScript. Is this possible? Can I load it as an object and then somehow have access to the color and image data?

2
  • of course peter! you mean vote your answer up? Commented Mar 28, 2012 at 7:35
  • you can also upvote but the best is to check my answer as the accepted answer (the geen v mark), thanks Commented Mar 29, 2012 at 10:08

12 Answers 12

104

Sure, here is an example (standard HTML boilerplate omitted):

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" style="width: 3.5in; height: 1in">
  <circle id="circle1" r="30" cx="34" cy="34" 
            style="fill: red; stroke: blue; stroke-width: 2"/>
  </svg>
<button onclick="circle1.style.fill='yellow';">Click to change to yellow</button>

Sign up to request clarification or add additional context in comments.

9 Comments

The OP asked to reference the <svg> element as an <object>; this answer does not do that.
that depends how you define an object, in my case the SVG is not embedded by an <object> tag but it is an object neverless, otherwise it wouldn't have properties i can change, if you have a working example of doing the same thing with an object tag, please post it as an answer. With the info from Erik here this should be possible. I like answers i can try out without much fiddling.
@WebWanderer - No it's not. The code run from the onclick is most definitely JavaScript code changing the fill color. Last I knew HTML didn't have dot notation or end lines with semi-colons.
@WebWanderer - I'm not sure what you mean by "you supplied", I didn't "supply" anything. But that bit of javascript is all that's needed to do it, which is why it's all that's there. It very much works, as evidenced by this jsfiddle: jsfiddle.net/3ug5f1ru
This answer is a simple example for inline SVG only. Never saw the trick of bypassing document.getElementById and just using 'id' as the object (circle1), this may not run everywhere. The term "object" in the question is ambiguous. A DOM object reference of some sort, indeed, but an <svg> or <object>? "Load it as an object" can reasonably mean to load an external SVG file into an <object>, in which case this example falls short. If using object tag, document.getElementById( 'obj-id' ).contentDocument.getElementById( 'circle1' ).style.fill = 'yellow' would work. See answers below.
|
74

This is for loading an SVG via <object>:

<object class="svgClass" type="image/svg+xml" data="image.svg"></object>

The JavaScript code is like this:

// change to red
document.querySelector(".svgClass").getSVGDocument().getElementById("svgInternalID").setAttribute("fill", "red")

To change svgInternalID you have to open the SVG file which is plain text (e.g., image.svg) and edit it:

<path id="svgInternalID"

3 Comments

Andrew S, as far as I know this is Javascript Web API - developer.mozilla.org/en-US/docs/Web/API/Document/querySelector - for more about SVG Scripting - developer.mozilla.org/en-US/docs/Web/SVG
getSVGDocument() is deprecated, it's recommended to use the contentDocument attribute instead, see w3.org/TR/SVG11/…
possible to use 'img' tag instead of 'object' tag? coz svg image doesn't scale to object tag width/height while it scales in 'img' tag
27

Given some SVG:

<div id="main">
  <svg id="octocat" xmlns="http://www.w3.org/2000/svg" width="400px" height="400px" viewBox="-60 0 420 330" style="fill:#fff;stroke: #000; stroke-opacity: 0.1">
    <path id="puddle" d="m296.94 295.43c0 20.533-47.56 37.176-106.22 37.176-58.67 0-106.23-16.643-106.23-37.176s47.558-37.18 106.23-37.18c58.66 0 106.22 16.65 106.22 37.18z"/>
    <path class="shadow-legs" d="m161.85 331.22v-26.5c0-3.422-.619-6.284-1.653-8.701 6.853 5.322 7.316 18.695 7.316 18.695v17.004c6.166.481 12.534.773 19.053.861l-.172-16.92c-.944-23.13-20.769-25.961-20.769-25.961-7.245-1.645-7.137 1.991-6.409 4.34-7.108-12.122-26.158-10.556-26.158-10.556-6.611 2.357-.475 6.607-.475 6.607 10.387 3.775 11.33 15.105 11.33 15.105v23.622c5.72.98 11.71 1.79 17.94 2.4z"/>
    <path class="shadow-legs" d="m245.4 283.48s-19.053-1.566-26.16 10.559c.728-2.35.839-5.989-6.408-4.343 0 0-19.824 2.832-20.768 25.961l-.174 16.946c6.509-.025 12.876-.254 19.054-.671v-17.219s.465-13.373 7.316-18.695c-1.034 2.417-1.653 5.278-1.653 8.701v26.775c6.214-.544 12.211-1.279 17.937-2.188v-24.113s.944-11.33 11.33-15.105c0-.01 6.13-4.26-.48-6.62z"/>
    <path id="cat" d="m378.18 141.32l.28-1.389c-31.162-6.231-63.141-6.294-82.487-5.49 3.178-11.451 4.134-24.627 4.134-39.32 0-21.073-7.917-37.931-20.77-50.759 2.246-7.25 5.246-23.351-2.996-43.963 0 0-14.541-4.617-47.431 17.396-12.884-3.22-26.596-4.81-40.328-4.81-15.109 0-30.376 1.924-44.615 5.83-33.94-23.154-48.923-18.411-48.923-18.411-9.78 24.457-3.733 42.566-1.896 47.063-11.495 12.406-18.513 28.243-18.513 47.659 0 14.658 1.669 27.808 5.745 39.237-19.511-.71-50.323-.437-80.373 5.572l.276 1.389c30.231-6.046 61.237-6.256 80.629-5.522.898 2.366 1.899 4.661 3.021 6.879-19.177.618-51.922 3.062-83.303 11.915l.387 1.36c31.629-8.918 64.658-11.301 83.649-11.882 11.458 21.358 34.048 35.152 74.236 39.484-5.704 3.833-11.523 10.349-13.881 21.374-7.773 3.718-32.379 12.793-47.142-12.599 0 0-8.264-15.109-24.082-16.292 0 0-15.344-.235-1.059 9.562 0 0 10.267 4.838 17.351 23.019 0 0 9.241 31.01 53.835 21.061v32.032s-.943 11.33-11.33 15.105c0 0-6.137 4.249.475 6.606 0 0 28.792 2.361 28.792-21.238v-34.929s-1.142-13.852 5.663-18.667v57.371s-.47 13.688-7.551 18.881c0 0-4.723 8.494 5.663 6.137 0 0 19.824-2.832 20.769-25.961l.449-58.06h4.765l.453 58.06c.943 23.129 20.768 25.961 20.768 25.961 10.383 2.357 5.663-6.137 5.663-6.137-7.08-5.193-7.551-18.881-7.551-18.881v-56.876c6.801 5.296 5.663 18.171 5.663 18.171v34.929c0 23.6 28.793 21.238 28.793 21.238 6.606-2.357.474-6.606.474-6.606-10.386-3.775-11.33-15.105-11.33-15.105v-45.786c0-17.854-7.518-27.309-14.87-32.3 42.859-4.25 63.426-18.089 72.903-39.591 18.773.516 52.557 2.803 84.873 11.919l.384-1.36c-32.131-9.063-65.692-11.408-84.655-11.96.898-2.172 1.682-4.431 2.378-6.755 19.25-.80 51.38-.79 82.66 5.46z"/>
    <path id="face" d="m258.19 94.132c9.231 8.363 14.631 18.462 14.631 29.343 0 50.804-37.872 52.181-84.585 52.181-46.721 0-84.589-7.035-84.589-52.181 0-10.809 5.324-20.845 14.441-29.174 15.208-13.881 40.946-6.531 70.147-6.531 29.07-.004 54.72-7.429 69.95 6.357z"/>
    <path id="eyes" d="m160.1 126.06 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z m94.43 0 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z"/>
    <path id="pupils" d="m154.46 126.38 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z m94.42 0 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z"/>
    <circle id="nose" cx="188.5" cy="148.56" r="4.401"/>
    <path id="mouth" d="m178.23 159.69c-.26-.738.128-1.545.861-1.805.737-.26 1.546.128 1.805.861 1.134 3.198 4.167 5.346 7.551 5.346s6.417-2.147 7.551-5.346c.26-.738 1.067-1.121 1.805-.861s1.121 1.067.862 1.805c-1.529 4.324-5.639 7.229-10.218 7.229s-8.68-2.89-10.21-7.22z"/>
    <path id="octo" d="m80.641 179.82 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m8.5 4.72 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.193 6.14 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m4.72 7.08 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.188 6.61 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m7.09 5.66 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.91 3.78 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.87 0 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m10.01 -1.64 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z"/>
    <path id="drop" d="m69.369 186.12l-3.066 10.683s-.8 3.861 2.84 4.546c3.8-.074 3.486-3.627 3.223-4.781z"/>
  </svg>
</div>

Using jQuery, for instance, you could do:

var _currentFill = "#f00"; // red
$svg = $("#octocat");
$("#face", $svg).attr('style', "fill:"+_currentFill); })

I provided a coloring book demo as an answer to another stackoverflow question: http://bl.ocks.org/4545199. Tested on Safari, Chrome, and Firefox.

Comments

14

For the background color - the fill property can be accessed like so:

svgElement.style.fill = '#fff';

To set the border color, do the same for the stroke property.

See it in action:

const svgElement = document.getElementById('svg')
const checkboxElement = document.getElementById('check')

checkboxElement.addEventListener('change', e => {
  svgElement.style.fill = e.target.checked ? 'PeachPuff' : 'PapayaWhip'
})
<input type="checkbox" id="check" />
<svg id="svg" fill="AliceBlue">
  <circle r="50" cx="70" cy="70" />
</svg>

Please refer to the W3C reference on SVG for more capabilities, as it's a broad issue.

6 Comments

@peter you are correct, one should access the object properties. i updated my answer accordingly, thanks.
also, the gradient doesn't work like that, normally you first have to define (eg grad1) one and then you can access it via fill="url(#grad1)"
@peter again, correct - this was pasted from a Raphael API code of mine. this is the value sent to the attr() method. deleted that, thanks.
Tanks for the immidiate response!
@AndroidDev, can you prove it with a demo?
|
7

Here's a full example that shows how to modify the fill color of an svg referenced via <embed>, <object> and <iframe>.

Also see How to apply a style to an embedded SVG?

1 Comment

I think you should elaborate a little bit the answer, answering using link a think is discouraged
5

Your SVG must be inline in your document in order to be styled with CSS. This can be done by writing the SVG markup directly into your HTML code, or by using SVG injection, which replaces the img element with the content from and SVG file with Javascript.

There is an open source library called SVGInject that does this for you. All you have to do is to add the attribute onload="SVGInject(this)" to you <img> tag.

A simple example using SVGInject looks like this:

<html>
  <head>
    <script src="svg-inject.min.js"></script>
  </head>
  <body>
    <img src="image.svg" onload="SVGInject(this)" />
  </body>
</html>

After the image is loaded the onload="SVGInject(this) will trigger the injection and the <img> element will be replaced by the contents of the SVG file provided in the src attribute.

Comments

3

I know this is a pretty old question. But I stumbled over it searching for the same topic. Out of this and some other answers I finally built a function for precisely this topic:

  • It loads a SVG completely in JavaScript ...
  • removes the size-tags to make it scale with its parent DIV
  • even adjusts the viewbox to make it square and
  • changes the fillColor in different ways.

Maybe this is of help for some of you:

/* inspired by https://codepen.io/osublake/pen/OMRdKq */

function loadSvgIntoDiv(theDIV, pathToSvg, prefix = 'myPrefix-', fillColor = null, fillColorID = null)
{
    if ( theDIV == null || typeof theDIV.appendChild != 'function' ) return null;
  
    fetch(pathToSvg).then( (res) => {

        // check the status
        
        if (!res.ok)
        {
            switch (res.status)
            {
                case 404: 
                    throw new Error('"' + pathToSvg + '" not found (error 404).');
                
                default:
                    throw new Error('Failed to fetch "' + pathToSvg + '": ' + res.status + ' (' + res.statusText + ')'); 
            }
        }

        let contentType = res.headers.get('content-type');

        if ( typeof contentType == 'string' && contentType.indexOf('image/svg') !== -1 ) 
        {
            // hand over SVG-content to next .then
            return res.text();

        } else {

            throw new Error('Unexpected content type (' + iconPath + ', ' + contentType + ')');
        }
    })
    .then( (iconData) => {

        // clean up SVG
    
        // remove width and height from <svg ...>-tag to allow scaling
        iconData = iconData.replace(/\<svg([^>]*)\>/ig, (match) => {
            return match.replace(/width\=[\'\"]([^\"^\']*)[\"\']/ig, '').replace(/height\=[\'\"]([^\"^\']*)[\"\']/ig, '');
        });
        
        // adjust viewbox to be a square image
        iconData = iconData.replace(/\<svg([^>]*)\>/ig, (match) => {
            return match.replace(/viewbox\=[\'\"][^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^\"^\']*[\"\']/ig, (match, x, y, w, h) => {
                x = Number(x);
                y = Number(y);
                w = Number(w);
                h = Number(h);
                if ( w < h ) { x=x-(h-w)/2; w=h; }
                if ( h < w ) { y=y-(w-h)/2; h=w; }
                return 'viewbox="' + x + ' ' + y + ' ' + w + ' ' + h + '"';
            });
        });
        
        let origIcon = iconData;

        // add fill-style to a given id
        if ( fillColorID != null && fillColor != null )
        {
            let search = '/id\=[\"\']' + fillColorID + '[\"\']/ig';
            iconData = iconData.replace(search, 'id="' + fillColorID + '" style="fill: ' + fillColor + '" ');
        }

        // edit all fill-statements within path-tags 
        if ( fillColor != null ) fillColor='fill="' + fillColor + '"';
        if ( fillColor == null || fillColorID != null ) fillColor='';
        iconData = iconData.replace(/\<path([^>]*)\>/ig, (match) => {
            return match.replace(/fill\=[\'\"]([^\"^\']*)[\"\']/ig, fillColor);
        });
        iconData = iconData.replace(/\<g\ ([^>]*)\>/ig, (match) => {
            return match.replace(/fill\=[\'\"]([^\"^\']*)[\"\']/ig, fillColor);
        });
        
        // no fill was added, as nothing was changed
        if ( iconData == origIcon)
        {
            iconData = iconData.replace(/\<g\ ([^>]*)\>/ig, (match, p) => {
                return '<g ' + replaceFill + p + '>';
            });
            iconData = iconData.replace(/\<path([^>]*)\>/ig, (match, p) => {
                return '<path ' + replaceFill + p + '>';
            }); 
        }

        // add prefix in front of every ID to prevent duplicates
        iconData = iconData.replace(/id\=[\"\']([^\"^\']*)[\"\']/ig, 'id="' + prefix + '$1"');

        // finally add the SVG to the div
        theDIV.innerHTML = iconData;
    })
    .catch( (error) => {

        // handle error messages
    });
}

see also: https://gist.github.com/aroesler-privat/2c304d42644c72142195842b10fff781

Comments

0

The Objects contentDocument exposes the SVG's DOM for manipulation. Here the kangaroos first change to yellow in the external CSS then Javascript sets them to gold.

Comments

0

Changing the color does not work directly in Typescript as far as I've tried but this works.

your_element.style.filter = `brightness(100%) hue-rotate(${Math.random() * 360}deg)`;

Comments

0

You can manipulate an SVG color with the "fill" style. However, to do so, you have to use an SVG tag directly in your html document. You can't reference it in an "img" tag using the "src" attribute. Here's an example of using the SVG in your html.

circle { cursor: pointer; transition: all 0.33s; }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Manipulation</title>
</head>
<body>
    <!-- SVG embedded directly in HTML -->
    <svg class="info-icon" width="100" height="100" viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
    </svg>

    <script>
        var icon = document.querySelector(".info-icon");
        icon.addEventListener("click", changeColor);

        function changeColor() {
            icon.querySelector('circle').style.fill = "#222"; // Change the fill color of the circle element
        }
    </script>
</body>
</html>

Sometimes the path of the SVG can be lengthy, so be careful! If you don't want to do that, then you can reference the SVG in an "img" tag "src" attribute, and change the colour of the SVG by using the "filter" style. Simple solution to that is using a hex to filter converter.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Manipulation with IMG</title>
    <style>
        .circle {
            width: 100px;
            height: 100px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <img class="circle" src="https://www.svgrepo.com/show/529031/info-circle.svg">

    <script>
        var icon = document.querySelector(".circle");
        icon.addEventListener("click", changeColor);

        function changeColor() {
            icon.style.filter = "invert(41%) sepia(44%) saturate(4130%) hue-rotate(77deg) brightness(95%) contrast(98%)";
        }
    </script>
</body>
</html>

Comments

-1

Built off the above but with dynamic creation and a vector image, not drawing.

function svgztruck() {
    tok = "{d path value}"
    return tok;
}

function buildsvg( eid ) {
    console.log("building");
    var zvg = "svg" + eid;
    var vvg = eval( zvg );
    var raw = vvg();

    var svg = document.getElementById( eid );
    svg.setAttributeNS(null,"d", raw );
    svg.setAttributeNS(null,"fill","green");
    svg.setAttributeNS(null,"onlick", eid + ".style.fill=#FF0000");
    return;
}

You could call with:

<img src="" onerror="buildscript">

Now you can add colors by sub element and manipulate all elements of the dom directly. It is important to implement your viewbox and height width first on the svg html, not done in the example above.

There is no need to make your code 10 pages when it could be one... but who am I to argue. Better use PHP while your at it.

The inner element that svg builds on is a simple <svg lamencoding id=parenteid><path id=eid><svg> with nothing else.

1 Comment

the example call is for people who are not creative... cough cough
-2

If it is just about the color and there is no specific need for JavaScript, you could also convert them to a font. This link gives you an opportunity to create a font based on the SVG. However, it is not possible to use img attributes afterwards - like "alt". This also limits the accessibility of your website for blind people and so on.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.