You can include SVG files into your HTML file via embed
object
and svg
tags.
embed
or object
tag requires linking the image with a URL. (This is what I prefer, because I don't like all that SVG code in my HTML code, so I’d like to keep it that way.)svg
tag (AFAIK) requires having the SVG code inline in your HTML code.How do I include SVG icons, images, and other files into my HTML file, without having to put the entire SVG code in, and still be able to apply styles to them? Applying them through JS is fine too.
When I include them via object
or embed
, I can't seem to access them through jQuery, even with $("#my-svg-div").find("svg")
(which, by the way, almost every answer on SO says I should). I just get undefined
.
Thank you!
SVG images can be written directly into the HTML document using the <svg> </svg> tag. To do this, open the SVG image in VS code or your preferred IDE, copy the code, and paste it inside the <body> element in your HTML document. If you did everything correctly, your webpage should look exactly like the demo below.
The SVG <style> element allows style sheets to be embedded directly within SVG content.
There are many Scalable Vector Graphics (SVG), but only certain attributes can be applied as CSS to SVG. Presentation attributes are used to style SVG elements and can be used as CSS properties. Some of these attributes are SVG-only while others are already shared in CSS, such as font-size or opacity .
It's taken a while, but SVG is now widely supported across all major browsers and devices. SVG files are super-small, searchable, modifiable – via code – and scalable. They look great at all sizes and can be used just like images or inline right in your HTML (creating a site but don't want to code?
You can include SVG files into your HTML file via embed object and svg tags. Using an embed or object tag requires linking the image with a URL. (This is what I prefer, because I don't like all that SVG code in my HTML code, so I’d like to keep it that way.) Using the svg tag (AFAIK) requires having the SVG code inline in your HTML code.
- Stack Overflow How to apply a style to an embedded SVG? When an SVG is directly included in a document using the <svg> tag, you can apply CSS styles to the SVG via the document's stylesheet. However, I am trying to apply a style to an SVG which is embedded (using the <object> tag).
How to use inline SVG images. SVG images can be written directly into the HTML document using the <svg> </svg> tag. To do this, open the SVG image in VS code or your preferred IDE, copy the code, and paste it inside the <body> element in your HTML document. <body> // Paste the SVG code here. </body>.
How to use SVG as a CSS background-image This is similar to adding SVG to an HTML document using the <img> tag. But this time we do it with CSS instead of HTML as you can see in the code snippet below. When you use an SVG as a CSS background image, it has similar limitations to using <img>. Still, it allows a bit more customization.
You can programmatically inline an SVG image. Such an image can be treated essentially identically to an actual inline <svg>
element, including being able to have styles applied to it.
If your SVG image is referenced in an <object>
or <iframe>
element (e
), you can inline it as follows:
e.parentElement.replaceChild(e.contentDocument.documentElement.cloneNode(true), e);
If your SVG image is referenced in an <embed>
element, replace .contentDocument
in the above code with .getSVGDocument()
.
If your SVG image is referenced in an <img>
element, a completely different strategy, involving AJAX and described below, can be used to inline the image.
If your external SVG image files are same-origin (e.g. the images are loaded from the same place as the HTML code), then one approach that allows styling of these images is to programmatically inline them as follows:
This inlining strategy gives you the best of two worlds:
You get the benefits of separate image files, including:
Yet you can still do anything to the eventually-inlined SVG images that you could do to <svg>
elements that were truly originally inline, including:
<object>
or <iframe>
elements:You can inline externally referenced SVG code as follows:
// using vanilla JavaScript (as shown above):
e.parentElement.replaceChild(e.contentDocument.documentElement.cloneNode(true), e);
// using jQuery:
$e.replaceWith($($e[0].contentDocument.documentElement).clone());
...where e
or $e
are the vanilla or jQuery variables (respectively) in which you have selected an external-SVG-referencing <object>
or <iframe>
element.
<embed>
elements:If, instead, you are using an external-SVG-referencing <embed>
element, then you can inline the SVG content by replacing .contentDocument
in the above code with .getSVGDocument()
(note the additional parentheses). Note that .contentDocument
does not work with <embed>
elements while .getSVGDocument()
actually works with all three element types. However .getSVGDocument()
is deprecated and so should only be used if you really need <embed>
elements.
<img>
elements:Neither of the above strategies works for <img>
elements. To inline these, you can retrieve the src
attribute of the <img>
element, make an AJAX request for that file, create a new <svg>
element using the retrieved SVG code and replace the original <img>
element with the new <svg>
element. If you want this strategy to work for all four element types, then just be aware that the URL of the referenced SVG image is held in the src
attribute of <iframe>
, <embed>
and <img>
elements but in the data
attribute of an <object>
element. This strategy can be implemented as follows:
// using vanilla JavaScript:
var xhr = new XMLHttpRequest();
xhr.open("GET", e.getAttribute(e.nodeName === "OBJECT" ? "data" : "src");
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
e.outerHTML = xhr.responseText;
}
};
// using jQuery:
$.get($e.attr($e.prop("nodeName") === "OBJECT" ? "data" : "src"), function(data) {
$e.replaceWith(data.documentElement);
});
The following example demonstrates where the above strategy does and does not allow external CSS stylings to be applied to originally-external SVG images. (I didn't create a code snippet or jsfiddle because of the need to reference local external files.)
The following two screenshots show the CSS styling (red triangles) or lack thereof (black triangles) before and after inlining. It shows the results for SVG images originally embedded in the HTML (<svg>
) or referenced in the indicated elements (<object>
, <iframe>
, <embed>
, and <img>
). The three rows show the results of inlining using the three indicated strategies.
Before clicking the button, no inlining has yet been attempted, and the screen looks like this. Only embedded SVG elements (the 1st column) are styled:
After clicking the button, inlining is attempted, and the screen now looks like this. CSS styling has been successfully applied to some of the elements:
The code required for this example follows:
image.svg
(externally referenced file, i.e. not embedded in the HTML):
<svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px">
<polygon points="25,5 45,45 5,45 25,5"/>
</svg>
index.html
(obviously, remove the jQuery script line if not using jQuery):
<!DOCTYPE html>
<head>
<link href="styles.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="main.js"></script>
</head>
<body>
<button>Click to attempt to inline svg images.</button>
<table>
<tr>
<th></th>
<th>svg </th>
<th>object</th>
<th>iframe</th>
<th>embed </th>
<th>img </th>
</tr>
<tr>
<td>contentDocument</td>
<td><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"><polygon points="25,5 45,45 5,45 25,5"/></svg></td>
<td><object data="image.svg" type="image/svg+xml"></object></td>
<td><iframe src="image.svg" width="50" height="50" style="border: none;"></iframe></td>
<td><embed src="image.svg" type="image/svg+xml" /></td>
<td><img src="image.svg" /></td>
</tr>
<tr>
<td>getSVGDocument()<br />(deprecated)</td>
<td><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"><polygon points="25,5 45,45 5,45 25,5"/></svg></td>
<td><object data="image.svg" type="image/svg+xml"></object></td>
<td><iframe src="image.svg" width="50" height="50" style="border: none;"></iframe></td>
<td><embed src="image.svg" type="image/svg+xml" /></td>
<td><img src="image.svg" /></td>
</tr>
<tr>
<td>XMLHttpRequest</td>
<td><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"><polygon points="25,5 45,45 5,45 25,5"/></svg></td>
<td><object data="image.svg" type="image/svg+xml"></object></td>
<td><iframe src="image.svg" width="50" height="50" style="border: none;"></iframe></td>
<td><embed src="image.svg" type="image/svg+xml" /></td>
<td><img src="image.svg" /></td>
</tr>
</table>
</body>
</html>
styles.css
(only the polygon
line is important for demonstrating the inlining):
polygon {fill: red;}
table {border-collapse: collapse;}
td, th {border: solid black 1px; padding: 0.4em;}
main.js
(jQuery version):
$(document).ready(function() {
$("button").click(function() {
["object", "iframe", "embed", "img"].forEach(function(elmtType) {
var $e, $threeElmts = $(elmtType);
$e = $($threeElmts[0]);
if ($e[0].contentDocument) $e.replaceWith($($e[0].contentDocument.documentElement).clone());
$e = $($threeElmts[1]);
if ($e[0].getSVGDocument) $e.replaceWith($($e[0].getSVGDocument().documentElement).clone());
$e = $($threeElmts[2]);
$.get($e.attr($e.prop("nodeName") === "OBJECT" ? "data" : "src"), function(data) {
$e.replaceWith(data.documentElement);
});
});
});
});
main.js
(vanilla JavaScript version):
document.addEventListener("DOMContentLoaded", function() {
document.querySelector("button").addEventListener("click", function() {
["object", "iframe", "embed", "img"].forEach(function(elmtType) {
var e, threeElmts = document.querySelectorAll(elmtType);
e = threeElmts[0];
if (e.contentDocument) e.parentElement.replaceChild(e.contentDocument.documentElement.cloneNode(true), e);
e = threeElmts[1];
if (e.getSVGDocument) e.parentElement.replaceChild(e.getSVGDocument().documentElement.cloneNode(true), e);
e = threeElmts[2];
var xhr = new XMLHttpRequest();
xhr.open("GET", e.getAttribute(e.nodeName === "OBJECT" ? "data" : "src"));
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) e.outerHTML = xhr.responseText;
};
});
});
});
id
and class
(or any other) attributes, event listeners, iframe
functionality, etc.object
, iframe
, embed
, and img
elements. It does not address external SVG images referenced in CSS background-image
properties or in the drawImage
function of a <canvas>
context. I suspect those won't work this way, but I haven't checked.index.html
, Chrome and Opera have security settings that will make this impossible. To get those browsers to work in such a local configuration, you instead need to run a local server as instructed in this other SO question. There should be no such problem if you are using the inlining strategy in a normal server-hosted web site.This is the most comprehensive walkthrough of (1) the different ways of using SVGs in your HTML and (2) what styling the individual pieces (ie: paths) of the SVG via CSS/JS you can do.
https://css-tricks.com/using-svg/
In an image tag (ie: <img src="picture.svg" />
or as a background image in CSS = no styling
Inline - style away, but it'll clutter your HTML. PHP helps here, or you could use a gulp build task or something to keep the SVGs from cluttering your working code, while still being inline in the end.
As an object you can now add CSS within the .svg file:
<svg ...>
<style>
/* SVG specific fancy CSS styling here */
</style>
...
</svg>
or
<?xml-stylesheet type="text/css" href="svg.css" ?>
Data URIs - can be great for background images. No styling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With