SVG: access defs item in HTML when SVG inside Object? - object

Suppose I have an SVG which has the following defs:
<svg width="179" height="170" viewBox="0 0 179 170" xmlns="http://www.w3.org/2000/svg">
<title>Star 1</title>
<defs>
<g id="shape">
<rect x="50" y="50" width="50" height="50" />
</g>
</defs>
<g fill="none" fill-rule="evenodd">
<path stroke="#979797" fill="#D8D8D8" d="M89.5 140.25l-54.958 28.893 10.496-61.196L.576 64.607l61.445-8.93L89.5 0l27.48 55.678 61.444 8.93-44.462 43.34 10.496 61.195z" />
</g>
</svg>
I am including that SVG inside an HTML document using the object tag. For example:
<object type="image/svg+xml" data="star.svg" class="svgObjectWrapper">
Your browser doesn't support SVG
</object>
Is there any way, in the HTML document, to reference/use those defs from the SVG (which is in turn inside the object). For example, this doesn't seem to work. Should this be possible?
<use xlink:href="#shape" x="50" y="50" />
My guess is no, but I wanted to be sure.

It's possible on UAs that support it (Firefox does for instance) and you don't even need an object tag if all you want is to reference a document via <use>.
Per the SVG specification you can just put in the URL of the file you want to use the data from i.e.
<use xlink:href="star.svg#shape" x="50" y="50" />
star.svg has to be on the same domain as your html file.

Since <object> loads the svg in a separate document you can't use local references (such as <use xlink:href="#shape"/>) in the top document to reach resources inside the other document. It is possible to reference external resources with <use> though, e.g <use xlink:href="star.svg#shape"/>. Note that this still does not mean that it's the same document as that in the <object>, e.g if you change elements inside the <object> element it will have no effect on <use xlink:href="star.svg#shape"/>.

Related

SVG <defs> not included from external target of <use> [duplicate]

I'm trying to hack together a sprite sheet from a set of icons. I know almost nothing about SVG. I can get the simple icons to work, but an icon with a clip path isn't displaying properly. From what I can tell it seems like it's not using the clip path.
The sprite works in jsfilddle and it works if I just load the svg on it's own and include a < use > statement in the SVG. But if I have a separate < use > it doesn't work.
All my testing has been done in Chrome (50.0.2661.94)
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<clipPath id="folder-clip-0">
<path d="..." />
</clipPath>
<symbol id="folder" viewBox="0 0 32 32">
<g class="container" data-width="32" data-height="27" transform="translate(0 2)">
<path d="..." class="..." />
<path class="..." d="..." />
<path clip-path="url(#folder-clip-0)" d="..." class="..." />
</g>
</symbol>
</defs>
</svg>
I'm using it like so:
<svg>
<use
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="/img/path/sprite.svg#folder">
</use>
</svg>
When I use the separate statement it looks like this:
But it should look like this:
The color difference is not relevant, it's just the background when the image was taken.
Edit:
I just discovered that if I dump the whole sprite sheet into the page HTML and reference it locally instead of an external file it works. So I don't know what's wrong with my external reference.
e.g.
<svg>
<use xlinkHref={"/img/path/not/work/sprite.svg#folder"}></use>
</svg>
vs.
<svg>
<symbol id="folder"></symbol>
</svg>
<svg>
<use xlinkHref={"#folder"}></use>
</svg>
This works for me as a fallback, but I'd rather have an external SVG file instead of embedding it in my HTML.
Edit 2:
If the SVG sprite sheet is embeded in the HTML directly using the external link shows the icon correctly.
This seems to be a browser support issue. Using the external reference works as expected in Firefox. Chrome doesn't handle clip paths and some other functions in external references. There's an outstanding bug report filed. Safari also doesn't support it.
Related StackOverflow ticket: Why can't I reference an SVG linear gradient defined in an external file (paint server)?
Open bugs:
https://code.google.com/p/chromium/issues/detail?id=109212
https://bugs.webkit.org/show_bug.cgi?id=105904

SVG use linked from an external source not showing svg data

I have an html page with two svg use elements:
The first references inline svg.
The second references an external svg file (same code).
I am trying to figure out why the second example does not show the svg paths even though the SVG code that is inline is exactly the same as the SVG code in the linked file.
https://s3.amazonaws.com/jagger/svg/index.html
<svg class="svg-inline">
<use xlink:href="#test" />
</svg>
<svg class="svg-external">
<use xlink:href="sprite.svg#test" />
</svg>
<svg width="0" height="0">
<symbol id="test" viewBox="0 0 600 600">
<title>Test Icon</title>
<rect id="svg_2" height="214.39594" width="481.62782" y="10" x="10" stroke-width="5" stroke="#000000" fill="none"/>
<line fill="none" stroke="#000000" stroke-width="5" x1="10" y1="10" x2="400" y2="400" id="svg_1"/>
</symbol>
</svg>
using of external sprite is working in the latest version of all modern browsers
still problem in actual IE and older browsers versions
see MDN <use> browser_compatibility table
for IE (and older browsers) just use polyfill svg4everybody

Clip path not displaying properly in SVG sprite when using "use"

I'm trying to hack together a sprite sheet from a set of icons. I know almost nothing about SVG. I can get the simple icons to work, but an icon with a clip path isn't displaying properly. From what I can tell it seems like it's not using the clip path.
The sprite works in jsfilddle and it works if I just load the svg on it's own and include a < use > statement in the SVG. But if I have a separate < use > it doesn't work.
All my testing has been done in Chrome (50.0.2661.94)
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<clipPath id="folder-clip-0">
<path d="..." />
</clipPath>
<symbol id="folder" viewBox="0 0 32 32">
<g class="container" data-width="32" data-height="27" transform="translate(0 2)">
<path d="..." class="..." />
<path class="..." d="..." />
<path clip-path="url(#folder-clip-0)" d="..." class="..." />
</g>
</symbol>
</defs>
</svg>
I'm using it like so:
<svg>
<use
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="/img/path/sprite.svg#folder">
</use>
</svg>
When I use the separate statement it looks like this:
But it should look like this:
The color difference is not relevant, it's just the background when the image was taken.
Edit:
I just discovered that if I dump the whole sprite sheet into the page HTML and reference it locally instead of an external file it works. So I don't know what's wrong with my external reference.
e.g.
<svg>
<use xlinkHref={"/img/path/not/work/sprite.svg#folder"}></use>
</svg>
vs.
<svg>
<symbol id="folder"></symbol>
</svg>
<svg>
<use xlinkHref={"#folder"}></use>
</svg>
This works for me as a fallback, but I'd rather have an external SVG file instead of embedding it in my HTML.
Edit 2:
If the SVG sprite sheet is embeded in the HTML directly using the external link shows the icon correctly.
This seems to be a browser support issue. Using the external reference works as expected in Firefox. Chrome doesn't handle clip paths and some other functions in external references. There's an outstanding bug report filed. Safari also doesn't support it.
Related StackOverflow ticket: Why can't I reference an SVG linear gradient defined in an external file (paint server)?
Open bugs:
https://code.google.com/p/chromium/issues/detail?id=109212
https://bugs.webkit.org/show_bug.cgi?id=105904

Can you combine multiple svgs with different viewBoxes and customize each in Polymer?

I have multiple svgs that I'd like to use in my application and was hoping to put them in a single custom-svg element to reference individually by id, however, the viewBoxes are different. One svg is defined as
<iron-iconset-svg name="club-icon" size="512">
<svg>
<defs>
<g id="club-icon">
<path d="bunch of numbers"></path>
</g>
</defs>
</svg>
</iron-iconset-svg>
The other svg is defined as
<iron-iconset-svg name="club-icon" size="300">
<svg>
<defs>
<g id="book-icon">
<path d="bunch of numbers"></path>
</g>
</defs>
</svg>
</iron-iconset-svg>
Is there a way for each custom icon to define its own viewBox, or must every svg defined within a single iconset share the same properties. For now I have multiple custom element html files, but each custom element is an http request (which I'm trying to minimize).
It can be done using symbols.
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="beaker" viewBox="214.7 0 182.6 792">
<!-- <path>s and whatever other shapes in here -->
</symbol>
<symbol id="shape-icon-2" viewBox="0 26 100 48">
<!-- <path>s and whatever other shapes in here -->
</symbol>
</svg>
See this article on CSS tricks for a further explanation.
https://css-tricks.com/svg-symbol-good-choice-icons/
you might try a transform scale on you g element?
<g id="book-icon" transform="scale(1.71)">
1.71 = 512/300
or if you are using gulp/grunt, you could resize the SVGs to be the same using svg-scaler or the like

Enforce relative links to defs in SVG

I'm trying to draw multiple SVGs on a single page and the ids in the defs section of each SVG are clashing. I'd like each one to refer only the mask in their own defs. Currently they all use the mask that has a matching id on the first svg on the page. No svg knows about the others so they would have to rely on a random number generator to pick ids that (hopefully) are different.
Is that possible or do they need unique ids if the SVGs are loaded into the same webpage. They are created on the fly by d3.
<svg>
<defs>
<mask id="temperatureMask">
<rect width="100%" height="100%" fill="#ffffff">
</mask>
</defs>
<rect mask="#temperaureMask">…etc
</svg>
<svg>
<defs>
<mask id="temperatureMask">
<rect width="100%" height="50%" fill="#dddddd">
</mask>
</defs>
<rect mask="#temperaureMask">…etc
</svg>
The ids on a page must be unique. That includes any inline SVGs. You will need to alter your d3 script like you suggest to add a unique number etc to the ids.

Resources