I want to embed a group from an SVG file, that can be identified with an id. My naive approaches were:
1. embed
<embed src="cards/svg-cards.svg#joker_red"
id="embsvg"
width="300" height="220" type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/"
viewBox="0 0 100 100"
/>
2. image
<image id="i" x="10" y="20" width="80" height="80"
xlink:href="cards/svg-cards.svg#joker_red" />
3. object
<object data="cards/svg-cards.svg#red_joker"></object>
and I tried some more silly variants including the USE element and javascript.
The svg document was taken from here: Sourceforge
I found it out myself.
The important piece was, to give all visible elements a class attribute, say class="card" and specify 'svg .card { display: none }' as a style. That will make everything disappear. Then only the item that is selected via # behind the svg file name is actually displayed.
It doesn't really matter if the part to be displayed is a group or svg element.
Robert's posted code did it this way, but it was not obvious to me how important the class was.
Related
We have a server generated SVG which cannot be modified and which needs to be displayed nested inside of another, larger, SVG.
It is necessary to modify the "preserveAspectRatio" attribute of the contained (inner) SVG to
preserveAspectRatio="none"
for it to display correctly.
The current approach is to define the nested SVG inside of a DEFS tag as follows:
<defs>
<svg id="serverSetID"
viewBox="0 0 200 200"
>
svg content here
</svg>
</defs>
and then reference it as follows:
<use
xlink:href="#serverSetID#svgView(preserveAspectRatio(none))"
x="0"
y="0"
width="200"
height="200"
/>
Note: the nested SVG has a server generated ID attribute that is unique for that page.
If I leave out the "#svgView(preserveAspectRatio(none))" then it displays although not the way I want it to.
But if I include "#svgView(preserveAspectRatio(none))" then it does not display at all.
I have looked into other strategies such as directly including the code of the inner SVG within the body of the outer SVG without using the DEFS tag. But the problem with that strategy is that there does not appear to be a way to manipulate the "preserveAspectRatio" attribute since, as far as I can tell by experimentation and research, that attribute is not exposed to CSS in an SVG.
We are anxious NOT to use JavaScript for this because the page already has a LOT of very complex JS and we are trying to pare it down where possible.
Does anybody have any suggestions please?
PS. If I overlooked something (highly likely) or if "preserveAspectRatio" is indeed manipulable by CSS I will be humbly grateful for somebody to point out my error.
This question already has an answer here:
How many levels of recursion does SVG support?
(1 answer)
Closed 2 years ago.
I have created the following SVG file:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="150" height="150">
<rect
x="5"
y="5"
width="140"
height="140"
style="fill:white;stroke:black;stroke-width:1"
id="rect2"
/>
<image
y="50"
x="80"
id="image76"
xlink:href='https://image.flaticon.com/icons/svg/46/46441.svg'
preserveAspectRatio="none"
height="60"
width="60"
/>
<image
y="50"
x="10"
id="image76"
xlink:href='https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Android_robot.png/646px-Android_robot.png'
preserveAspectRatio="none"
height="60"
width="60"
/>
</svg>
I've managed to display it using the object tag like the following and it works fine:
<object type="image/svg+xml" data="image.svg"></object>
The result is like this:
However, when I try to use the img tag I have the following result:
<img src="image.svg"/>
When I try to display this svg file with the img tag, the images that are inside it disappear. I know it happens because I'm using addresses like https://image.flaticon.com/icons/svg/46/46441.svg and https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Android_robot.png/646px-Android_robot.png for my images instead of writing a base64 image inside this svg. But because it's possible with the object tag I'm curious to know if it's also possible with the img tag. Is it possible to make the img tag open svg files like this one? Or is it a limitation of the img tag?
No documents loaded in <img> can not request any external resource, can not execute scripts, can not receive any user event.
For your bitmap image, you'd have to embedded it as a data: URI in the svg itself.
If I have the following SVG image for example:
<svg role="img" viewbox="0 0 100 50" height="100px">
<title>Site Logo</title>
<rect x="0" y="00" width="100" height="10" fill="red"></rect>
<rect x="0" y="10" width="100" height="10" fill="salmon"></rect>
<rect x="0" y="20" width="100" height="10" fill="pink"></rect>
<rect x="0" y="30" width="100" height="10" fill="aqua"></rect>
<rect x="0" y="40" width="100" height="10" fill="blue"></rect>
</svg>
I should be hitting a11y svg guidelines by setting role=img and including a <title> element
However, when I run the Accessibility Audit in Firefox, it adds a warning for every element/graphic inside the SVG (path, rect, circ) with the following warning:
Content with images must be labeled. Learn more
But surely I don't need to mark up every individual path within the svg?
What should I do to improve a11y or indicate to FF what the correct alt text is?
Here's a demo page in fiddle that will reproduce this issue
I found that including a <title>Image title</title> tag within the <svg role="img"></svg> tags led FireFox to stop showing the error. Note the inclusion of the role attribute on the svg tag (as noted in an earlier comment), along with any other attributes you may need for the opening tag.
According to MDN Web Docs:
The element provides an accessible, short-text description of
any SVG container element or graphics element.
So, like an alt tag for an <img> element. It sounds like a <desc> tag could be used for additional descriptive information.
I am pretty sure this is a bug, or design flaw in FF's accessibility tool. I have reported it here.
Remember that automated accessibility audits can not catch every issue, and often report false positives. Try installing (e.g.) the WAVE accessibility add-on, which is another automatic accessibility auditor. It makes no such complaint.
w3 says
An img represents a single graphic within a document, whether or not
it is formed by a collection of drawing objects.
So you are right that role="img" on the SVG root should do The Right Thing. The accessibility API will not try to expose the children, but Firefox's current beta version of the accessibility tool obviously does.
I tried your code (wrapped in a bare bones HTML doc) with a screen reader (NVDA) and it didn't try to announce the rects, which is what I would expect. It did announce the accessible name. Actually it announces it twice (which is a known NVDA bug at time of writing).
I also tried putting a <g role="presentation"> element around the contents of the svg, but the accessibility tool still flagged warnings on all the children. This shouldn't be necessary.
So, I think you're good.
Elements with img role have the children presentational property set to true. So rect elements can't have an alternative name.
It's likely due to a bug in this Firefox plugin.
Note that (curiously?) the Accessible Name and Description guidelines state that the name can be:
generated from [...] a host language labeling mechanism, such as the alt or title attribute in HTML, or the desc element in SVG.
So according to this statement you should use the desc element. I'm not sure if it's an error in the documentation as the title element seems to be a more suitable choice.
This might come in late, but it helps all the time.
Since the svg does not have text, including aria-label="descriptive text here" and alt="svg description here" should help with the text label checks.
However, if the svg is just for presentational purpose, using empty alt helps out as well. This is to make screen readers recognise the svg, but will not describe the image (instead they'd just say "image", or similar).
I have multiple SVG pictures embedded into single HTML page.
Every SVG has own defs section that I am referencing to in my use elements.
It looks like I can't define element with the same id inside multiple defs and reference to it.
Second SVG use will pick the definition form the first SVG defs section, and ignore the local redefinition.
Does anybody know how I can reference to the LOCAL defs section?
The same story in Chrome and Firefox.
See the example below:
<html><head></head><body>
<svg height="50" width="50">
<defs>
<rect id="mybox" height="40" width="40" style="fill:#00F;"></rect>
</defs>
<use xlink:href="#mybox"/>
</svg>
<svg height="50" width="50">
<defs>
<rect id="mybox" height="20" width="20" style="fill:#F00;"></rect>
</defs>
<use xlink:href="#mybox"/>
</svg>
</body></html>
An SVG file with multiple identical IDs is invalid per http://www.w3.org/TR/SVG/struct.html#IDAttribute
Your options are either make all the IDs unique or move the SVG into separate files and reference them via <object> or <iframe> tags.
I created a tool to randomize definition id's to avoid this issue with inline svg's referencing the same #id, hopefully it will be useful for someone else. http://hugozap.com/randomize_svg_def_ids.html
One way to solve this is using svgo
svgo --enable=prefixIds *.svg
svgo can be installed via npm and is available as a library as well
I'm using object to embed some SVGs that I would like to href to other pages.
First option is to change the xml inside
See Inkscape FAQ-s 1.8.1
http://wiki.inkscape.org/wiki/index.php/Frequently_asked_questions
But I want to use javascript to dynamically change the url if they have js enabled. AND i want to reuse the same SVG doc anyway but with different links. So I need another option.
Second option, wrap the embedded object in a 'a href' tag, but that doesn't seem to work, it makes the div part that ISN'T covered by SVG a clickable link but not the svg.
{Further complicated because inside the object I have a .png (made clickable by using usemap) which if the browser falls back to I get TWO clickable areas. The PNG and DIV remainder....}
Third Option, a USEMAP for the svg itself! No that doesn't seem to work either.
Are there any other options? Javascript answers welcome, for reference purposes, but ideally not.
EDIT to add HTML code
<object class="svg" type="image/svg+xml" data="svgimage.svg" >
<img src="pngbackupforIEpre9androidpre3.png" type="image/png" usemap="#mapping"/>
</object>
</a>
<map name="mapping">
<area shape="rect" coords="0,0,100,100" href="svgfreezone.php" />
</map>
EDIT to add SVG XML code
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 0 617.875 320.75" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(-66.78125,-339.125)">
<rect style="stroke:#000000;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:3.5999999;fill:#ff0000;" height="317" width="614" y="341" x="68.6"/>
</g>
</svg>
Notes; The svg has been vacumed def'd, saved as plain and then optimised using "Simplify colours Y, Style to xml N, Group Collapsing Y, Enable ID stripping Y, Embed rasters N, Keep editor data N, Enable viewboxing Y, Strip xml prolog N, Set precision 3, Indent None."
Well, I see two options:
First option: (This will be only good if this is a web app; if its a "regular" website this may not be suitable for you)
Use a regular href in the SVG, which links to an anchor. That is - a #something url. Just a hash.
Now use a "special" hash which you can recognize, and then hook to the window's "hashchange" event, and see if the hash == '#my_special_hash' - then redirect to wherever you like.
Second option:
Put a placeholder href in the SVG, and read the SVG content with JavaScript.
Then replace the href with the url you really want, and inject it to the page.
Most browsers support SVG as a source image, and as an object.
You can see how the Raphael library builds SVG if you need actual code. Note that it uses VML for fallback because of lack of support in some old browsers.
Good luck! :-)
Set the background-image css property on the anchor to the svg image and it will be clickable.
I used one in this page.
#infoButton {
display: block;
float: left;
background-image: url('info.svg');
background-repeat: no-repeat;
width: 70px;
height: 70px;
}
Be sure to always put display: block; when using SVG some browsers don't support SVG properly.