1425Days

1425 days since this post was last revised. Specific details are likely out of date.

One of the incredible things about SVGs is the fact that they are dynamic; they can be altered when on the page. If you use an SVG directly in the markup you can access it directly. You can see this approach used on http://nice-letterform.com.

However, it’s also possible to place SVGs into markup with an <object> tag. Here’s an example:

<object id="svgObject" data="img/svgfile.svg" type="image/svg+xml" height="50" width="50">
Your browser doesn't support SVG
</object>

In this case, an image called ‘svgfile.svg’ is in an ‘img’ folder and this <object> will pull it in and place the SVG contents into the DOM. This then provides full access to the SVG DOM (which crucially differs from an HTML DOM). If the browser doesn’t have support, the enclosed text message will be shown.

Anecdotally I have found that although markup is ugly when an SVG is written inline, performance is better, especially in Chrome this way. For example, there is also an odd effect in Chrome (as of time of writing) whereby an SVG inserted via an object that has been changed via JS returns to its initial unaltered state when hidden and re-shown via display: none;)

So now it’s in the DOM, we want to amend that SVG with JavaScript. Shouldn’t be a problem. As already noted, if you look in the Dev Tools the SVG DOM is clearly there.

Lovely. Except as a JavaScript amateur, I tend to lean on jQuery (and I’m not too great with that either). Here’s the most important thing you can know in relation to this subject: YOU CAN’T SELECT PARTS OF THE SVG INSIDE AN OBJECT DIRECTLY WITH JQUERY. Phew. Hope you got that. The abridged reason: jQuery only understands the HTML DOM and not the SVG DOM.

However, don’t sweat that. You just want to select your SVG internals. Am I right? We can do it easily with good ol’ JavaScript. To aid understanding, imagine this is the contents of our SVG:

<svg height="40px" width="40px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800">
	<rect id="svgItem" width="800" height="800" fill="red"></rect>
	<circle cx="400" cy="400" r="400" fill="blue"></circle>
</svg>

As you can see, the rectangle is red by default. Let’s change that with JavaScript:

window.onload=function() {
	// Get the Object by ID
	var a = document.getElementById("svgObject");
	// Get the SVG document inside the Object tag
	var svgDoc = a.contentDocument;
	// Get one of the SVG items by ID;
	var svgItem = svgDoc.getElementById("svgItem");
	// Set the colour to something else
	svgItem.setAttribute("fill", "lime");
};

You’ll notice in the above code that the fun stuff has been enclosed in a window.onload function. This simply ensures that the SVG and the main DOM is loaded before we start trying to manipulate it.

Here’s a great reference URL that helped me understand all this: – make sure you inspect the source to see what’s going on.

I’m also aware that there is a plugin for jQuery called jQuery.svg that gives jQuery the super powers to select SVGs internals in this way but I didn’t want another dependency.

The key here is the contentDocument that grabs the inner (SVG) document. So don’t be put off, even if the thought of non-jQuery JS makes you tremble. It’s nice and simple with native JavaScript.

Ben Frain Developer, Author: 'Enduring CSS', 'Responsive Web Design with HTML5 & CSS3'.