How can I set the "preserveAspectRatio" attribute in a nested SVG? - html

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.

Related

Why <use> tag has ziro size? [duplicate]

I've followed many guides to adding external SVGs to a page... like this one : http://wearejh.com/design/inline-svg-use-element/
The code is like this:
<svg>
<use xlink:href="https://upload.wikimedia.org/wikipedia/commons/5/53/Skull_and_crossbones.svg"></use>
</svg>
It just does not load, example here: http://jsbin.com/cipacitovo/edit?html,output
What am I doing wrong?
Per the SVG specification
Unlike ‘image’, the ‘use’ element cannot reference entire files.
You need to add a fragment identifier to the URL to indicate which item within the image you are trying to display.
Why dont you use svg in img tag.Because you are not generating anything instead you are loading.
Check the example
You forgot to add xmlns:xlink="http://www.w3.org/1999/xlink" in <svg>.
This is how it should be:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="https://upload.wikimedia.org/wikipedia/commons/5/53/Skull_and_crossbones.svg"></use>
</svg>

Firefox A11y Audit with inline SVGs - content with images must be labeled

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).

How to <use> the <svg> element correctly for loading external sources?

I've followed many guides to adding external SVGs to a page... like this one : http://wearejh.com/design/inline-svg-use-element/
The code is like this:
<svg>
<use xlink:href="https://upload.wikimedia.org/wikipedia/commons/5/53/Skull_and_crossbones.svg"></use>
</svg>
It just does not load, example here: http://jsbin.com/cipacitovo/edit?html,output
What am I doing wrong?
Per the SVG specification
Unlike ‘image’, the ‘use’ element cannot reference entire files.
You need to add a fragment identifier to the URL to indicate which item within the image you are trying to display.
Why dont you use svg in img tag.Because you are not generating anything instead you are loading.
Check the example
You forgot to add xmlns:xlink="http://www.w3.org/1999/xlink" in <svg>.
This is how it should be:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="https://upload.wikimedia.org/wikipedia/commons/5/53/Skull_and_crossbones.svg"></use>
</svg>

Linking to SVG templates in external files

I'm using the yFiles for HTML chart library, which supports rendering nodes using SVG templates. According to the documentation, this is done by embedding a special <script> tag in the main HTML file with somewhat SVG elements in it (without the enclosing <svg> container).
<script type="text/yfiles-template">
<g id="expand_icon" transform="translate(21 6)">
<polygon stroke="#FFFFFF" stroke-width="3" fill="none"
points="6,17 6,12 1,12 1,6 6,6 6,1 12,1 12,6 17,6 17,12 12,12 12,17"/>
</g>
</script>
The problem is that putting all my templates in the main HTML file is messy, and I would rather split them into several external SVG files. However, if I simply copy the <script>'s contents into an external file and try changing the script tag like this:
<script type="text/yfiles-template" src="images/nodeTemplates.svg"></script>
doesn't seem to work. No error is displayed, but my templates aren't shown.
I can't find anything else in the docs about it, and it's entirely possible that it's hardcoded to look for it in the main HTML, but I was wondering if anyone managed to get it to read the templates from an external file.
I suggest you use the StringTemplateNodeStyle where you just pass the svg snippet as a string to the style. You can then use your own loading mechanism to retrieve the snippets.
Note that if you don't need all the data binding features of the TemplateNodeStyle, but just want to dynamically include an svg file as an image, you can just as well use the ImageNodeStyle and point it directly to your SVG resource. Alternatively implementing your own style as shown in the custom style tutorial is also a very feasible and flexible solution.
The node has and image property you can use for a valid .svg file aka:
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
The above will give you the ability to put each svg in a different .svg file.

How to create hoverstates with svg <use> tag

So I recently found this svg technique on csstricks and decided to use it in conjunction with the grunt task grunt-svgstore. I thought this was the perfect thing since you have access to the actual svg with css and javascript without pasting the whole svg code in the html. But I found one major problem I can't solve which is hoverstates (and similar). The problem is the following. If that's my html body (with the svg on top)
<body>
<svg>
<symbol id="arrow">
<path ... />
</symbol>
</svg>
<svg id="icon-arrow">
<use xlink:href="#arrow"></use>
</svg>
</body>
I can access the #icon-arrow svg or the #arrow symbol but neither will give me the ability to create a hoverstate. When doing #icon-arrow I can get a hoverstate but I can't access the actual shape because it is not actually a child of the #icon-arrow so doing #icon-arrow #arrow:hover won't work. On the other hand directly selecting the shape doesn't work because the shape is not actually there but it's only a reference. Is it actually possible to do hoverstates using this technique? Or are there any other solutions?