Im using object and use in order to have a single file for all my svg icons. But what Im seeing is that icons.svg file gets redownloaded every time a new icon is used in application. It's not strictly for every icon but it seems to happen very often. I couldn't diagnose it in my searches.
Is this normal behavior? Should it keep downloading the file? Am I just supposed to cache it?
How I include svg file to index.html:
<object type="image/svg+xml" data="/static/icons.svg" style="display: none;"></object>
How I use icons in various places:
<use href="/static/icons.svg#foo"></use>
<use href="/static/icons.svg#bar"></use>
Example icons.svg:
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="foo" viewBox="0 0 100 100">
<circle cx="69.37" cy="37.27" r="16.97"/>
</symbol>
<symbol id="bar" viewBox="0 0 100 100">
<circle cx="69.37" cy="37.27" r="16.97"/>
</symbol>
</svg>
I have an SVG image with an illustration of a cloud.
The cloud is going to be used in several weather icons. I have another SVG file that embeds the cloud illustration and adds another graphical element, a circle.
Now, this main SVG file shows up fine when I open it directly in the browser:
However, when I use the file as a background-image, the cloud is not rendered:
Here's a JSFiddle.
What the heck?
It shouldn't be a relative path issue because the image shows up fine when I call the main SVG in the browser (and I tried using an absolute path to no avail)
It's not a clipping issue - if you change the background-size property in the JSFiddle, you'll see the entire image area is rendered, just without the cloud.
The cloud was generated by Adobe Illustrator and not optimized yet, but seems to look ok.
This is the main SVG's markup:
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="-0" r="30" style="fill:red" />
<image x="12" y="12" width="20" height="40" xlink:href="elements/cloud.svg" />
</svg>
What am I doing wrong?
I've tested this in Safari 9.1.2 and latest Chrome on OS X, with the same result.
All SVGs that are inserted as images (through the img tag or as a background-image) cannot reference external files. So if you have an external CSS stylesheet, a custom font, or as in your case an external image, it won't work.
The solution would be to embed the image data within the xlink:href attribute:
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="-0" r="30" style="fill:red" />
<image x="12" y="12" width="20" height="40" xlink:href="data:image/svg+xml,%0A%3Csvg%20id%3D%22Ebene_1%22%20data-name%3D%22Ebene%201%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20viewBox%3D%220%200%20284%20179%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3Anone%3B%7D.cls-2%7Bclip-path%3Aurl(%23clip-path)%3B%7D.cls-3%7Bfill%3A%23508f9e%3B%7D%3C%2Fstyle%3E%3CclipPath%20id%3D%22clip-path%22%20transform%3D%22translate(-278.44%20-208.09)%22%3E%3Crect%20class%3D%22cls-1%22%20x%3D%22279.44%22%20y%3D%22207.09%22%20width%3D%22284%22%20height%3D%22179%22%2F%3E%3C%2FclipPath%3E%3C%2Fdefs%3E%3Ctitle%3Ecloud%3C%2Ftitle%3E%3Cg%20class%3D%22cls-2%22%3E%3Cg%20id%3D%22TK6tin%22%3E%3Cpath%20class%3D%22cls-3%22%20d%3D%22M562.44%2C302.09c-4.19%2C9-7.71%2C18.44-13.39%2C26.63-9.1%2C13.12-21.26%2C22.65-35.52%2C30.06C497.65%2C367%2C481%2C372.3%2C463.34%2C373.68c-17%2C1.33-32.1-3.68-43.58-16.9-3-3.43-4.87-2.72-7.56-.06-6%2C5.92-11.9%2C11.83-19.1%2C16.52-9.22%2C6-19.37%2C9.45-29.58%2C13a4.17%2C4.17%2C0%2C0%2C0-1.09.89h-19c-7.91-2.63-15.56-5.83-21.8-11.53a10%2C10%2C0%2C0%2C0-6.55-2.63c-15.38-1.29-32.37-10.18-35.09-28.87-0.38-2.61.39-5.62-1.56-8v-5c2.09-3.79%2C1.2-8.2%2C2.85-12.26%2C2.87-7.07%2C8.91-9.62%2C15-11.45%2C5.41-1.62%2C9.87-3%2C11.87-9%2C3.9-11.71%2C12.39-17.5%2C24.66-17.08%2C5.43%2C0.18%2C7.92-1.18%2C10.39-6.77%2C4.51-10.24%2C12-18.52%2C21.06-25.77A171.48%2C171.48%2C0%2C0%2C1%2C398.75%2C227c20.39-9.63%2C41.2-17.45%2C64.13-17.83%2C1%2C0%2C2%2C.11%2C2.55-1.06h7c2.35%2C2.26%2C5.3.64%2C7.93%2C1.21%2C13%2C2.81%2C25.88%2C6.08%2C37.28%2C13.42%2C8.3%2C5.35%2C17.12%2C10.07%2C23.36%2C18a94%2C94%2C0%2C0%2C1%2C10.57%2C17.12c4.56%2C9.4%2C9.31%2C18.73%2C10.86%2C29.24v15ZM318.12%2C365.24c1.49%2C0.13%2C1.71%2C1.24%2C2.29%2C2a37.42%2C37.42%2C0%2C0%2C0%2C25.1%2C14.71c15%2C2%2C28.63-2.48%2C41.61-9.82C397.41%2C366.3%2C405%2C357.4%2C413.92%2C350c2.08-1.74%2C3.65-2.89%2C5.66-.08%2C12.35%2C17.29%2C30.17%2C21.51%2C49.68%2C19a127.56%2C127.56%2C0%2C0%2C0%2C54.87-21c16.7-11.17%2C26.73-27.07%2C33.68-45.37%2C0.68-1.8.5-3.59%2C0.63-5.41%2C1.16-16.58-6.55-30.39-13.88-44.3a39.91%2C39.91%2C0%2C0%2C0-7.73-10.86c-13.58-12.69-28.91-22-47.27-26.37-15.43-3.68-30.69-3.42-46.1-.72-15.69%2C2.75-30.25%2C8.85-44.45%2C15.69-23.79%2C11.46-45.28%2C25.58-54.66%2C52.22a3.16%2C3.16%2C0%2C0%2C1-3.27%2C2.38c-3.81.17-7.6%2C0.73-11.42%2C1-9.24.54-15.85%2C4.7-17.71%2C13.68-1.27%2C6.13-4.13%2C9-9.56%2C10.64-1.3.39-2.6%2C0.42-3.85%2C0.75-5.69%2C1.52-11.51%2C3.66-13.65%2C9.54-4.64%2C12.77-2.74%2C26.7%2C6.27%2C37.43%2C6%2C7.19%2C14.75%2C9.64%2C23.74%2C10.93%2C0.84%2C0.12%2C1.74%2C1.26%2C2.8.06C317.92%2C368%2C316.87%2C366.61%2C318.12%2C365.24Z%22%20transform%3D%22translate(-278.44%20-208.09)%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" />
</svg>
Please follow the explanation in this link:
https://css-tricks.com/using-svg/
You need to enter the full svg code. you can get it from photoshop or online tools like this:
.background-img {
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><circle cx='15' cy='15' r='10' /></svg>") no-repeat;
height: 30px;
width: 30px;
}
I am using this example from Chris Coyer
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" mlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
<defs>
<g id="icon-image">
<path class="path1" d="M0 4v26h32v-26h-32zM30 28h-28v-22h28v22zM22 11c0-1.657 1.343-3 3-3s3 1.343 3 3c0 1.657-1.343 3-3 3-1.657 0-3-1.343-3-3zM28 26h-24l6-16 8 10 4-3z"></path>
</g>
</defs>
</svg>
<h1>
<svg viewBox="0 0 32 32">
<use xlink:href="#icon-phone"></use>
</svg>
Call me
However, I would like the path definitions to NOT be in the html as they will be used throughout the app.
Is this possible? (Note: I have read the answer that suggests javascript to manually inject the svg into the html. I don't want to do that either.)
I know there are many ways of embedding/linking SVG paths and files. And I have tried them all. In particular, I need to be able to style it to the currentColor. As covered in detail in this blog post, this cannot be done with external SVG files which are then used in an img tag.
So the closest thing I have found is this example above. However, I still don't want the path embedded in the html. If I could somehow get it in an external file of some type so it is reusable, that would be great.
Another option would be to convert SVG to a font
Searching the internet for "convert SVG to font" will give you a lot of sites/tools doing that, like:
https://icomoon.io/app/#/select
https://glyphter.com/
http://fontastic.me/
Also "HTML entities" have some reusable icons etc.
https://dev.w3.org/html5/html-author/charref
There's only one remaining option here. You don't want to embed the svg manually, you don't want to inject it with javascript and you don't want to use it in an img tag since you want to modify the properties with css. The only remaining solution would be to use your server-side language to inject it.
If you're using php, you can simply echo the content of your svg file where you want:
<?php echo file_get_contents(file_path); ?>
Another option I found is SVG Sprites, explained in detail by Chris Coyier
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<style>
.icon {
width: 125px;
height: 125px;
background: #eee;
fill: currentColor;
}
body {
padding: 20px;
}
</style>
</head>
<body>
<div style="color: red">
<svg class="icon"><use xlink:href="menu.svg#beaker"/></svg>
</div>
<div style="color: brown">
<svg class="icon"><use xlink:href="menu.svg#fish" /></svg>
</div>
</body>
</html>
And then this in a separate file called menu.svg:
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<symbol id="fish" viewBox="0 26 100 48">
<path d="M98.5,47.5C96.5,45.5,81,35,62,35c-2.1,0-4.2,0.1-6.2,0.3L39,26c0,4.5,1.3,9,2.4,12.1C31.7,40.7,23.3,44,16,44L0,34
c0,8,4,16,4,16s-4,8-4,16l16-10c7.3,0,15.7,3.3,25.4,5.9C40.3,65,39,69.5,39,74l16.8-9.3c2,0.2,4.1,0.3,6.2,0.3
c19,0,34.5-10.5,36.5-12.5S100.5,49.5,98.5,47.5z M85.5,50c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5
C88,48.9,86.9,50,85.5,50z" />
</symbol>
So I'm trying to make a simple textpath .svg that would be a vertical line with some text. The problem I am getting is that the <defs> tags seem to throw everything off. I think it has something to do with my xlink:href but I can't seem to pin down what exactly.
<svg version="1.1"
baseProfile="full"
width="20" height="600"
xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="testPath" d="M 10 10 L 10 600 z"
stroke="black" stroke-width="3" />
</defs>
<text>
<textpath xlink:href="#testPath">
teeeest
</textpath>
</text>
</svg>
Any help would be appreciated.
Your sample will work fine inlined in a browser, because the browser knows about the xlink namespace.
If your SVG is an external file, then more strict XML parsing is performed and all namespaces used have to be defined.
All you need to do is add a definition for the xlink namespace to your outermost <svg> element.
<svg version="1.1"
baseProfile="full"
width="20" height="600"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
SVG is a case sensitive language so textpath actually needs to be written as textPath.
If you embed the SVG in html then you don't need namespaces as html doesn't support them (unlike xhtml). If you have your SVG standalone you'll also need xmlns:xlink="http://www.w3.org/1999/xlink" on the root <svg> element.
Chrome seems not to display <use> elements in inline svg. Here is an example (code below or view it at http://www.bobwyttenbach.com/chromeuse.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chrome use-tag bug?</title>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="200px" height="200px" viewBox="0 0 200 200">
<defs>
<g id="test1">
<circle cx="100" cy="100" r="50" fill="red"/>
</g>
</defs>
<g>
<rect x="0.5" y="0.5" width="199" height="199" stroke="black" fill="none"/>
<use xlink:href="#test1" x="0" y="0"/>
</g>
</svg>
<p>Above is inline svg with a use tag; below is the same svg linked through an object tag. Below is correct.</p>
<object data="chromeuse.svg" width="200" height="200"></object>
</body>
</html>
The red circle does not appear in the inline svg but does appear when the same svg is linked through an object tag. Safari, Firefox, Opera, and Internet Explorer 9 all display the inline svg correctly.
Am I doing something wrong? Is this a known Chrome bug (I haven't found it listed)? Any workarounds?
Don't know if this question is still relevant, but I've met such a case recently and I pretty sure that somebody else will meet the case (especially those who tries to make use of SVG sprites for the first time).
In my case I've joined 16 SVG icons in one sprite manually into sprite.svg, and in this file I've omitted important meta information:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
I had no first line at all, and all I had on the second line was an opening <svg> tag with no meta attributes (xmlns and xmlns:xlink). As soon as I brought back all this omitted meta information, my graphics from sprite.svg started to display properly.
Hope it helps someone.
Ok so I deleted my last post as I incorrectly tried to figure out why the use element was working for me and not for you. What I can say is that I am using a modified version of this source, https://code.google.com/p/svg-edit/ , so in short, my answer is to walk through and see how they do it. I believe its demonstrated when you insert an image from their library.
I spent a long time debugging inline svg use elements not showing up. The chrome bug discussed by BobW seems fixed at this time. To eliminate the same issue caused by something else entirely, try commenting out the <base href="somethingsomethingsomething" /> tag from your HTML.
Of course, this will likely break every relative link on your site, but the <use> elements now show up. One step forward, half a step back :)
Related info here:
Using base tag on a page that contains SVG marker elements fails to render marker