I stumbled upon a problem.
I am using Chrome 34.0.1847.116 m - latest verstion.
The <use> seems to work OK on <circle> but not on <foreignObject> tag.
<svg height="400" width="400">
<foreignObject id="first" x="120" y="120" width="180" height="180">
<div xmlns="http://www.w3.org/1999/xhtml" style="height: 800px">
<ul>
<li><strong>First</strong> item</li>
<li>
<em>Second</em> item
</li>
<li>Thrid item</li>
</ul>
</div>
</foreignObject>
<!--<circle id="first" cx="150" cy="50" r="100" fill="lime" />-->
<polygon id="second" class="poly-in" points="300,200 200,300 100,200 200,0" style="fill:blue;stroke:purple;stroke-width:1" />
<use id="use-first" xlink:href="#first" href="#first" />
Sorry, your browser does not support inline SVG.
</svg>
This doesn't work (bug) ...
But, I can get <use> to work when referencing a <circle>
And, I can get <foreignObject> to work when not referenced by a <use>
I am very confused and don't know if I am misunderstanding something or is it a bug. I've been reading w3c paper on SVG and cannot figure it out.
I am looking identical behaviour than in example 2 but for the code posted here with <foreignObject>.
The "unexpected behaviour" is actually an expected -- if not very well documented -- limitation of the <use> element.
The W3 specs you linked to only allow to reference , or a graphics element -- a <foreignObject> tag is not a valid reference for <use>.
You could technically get around the specs by referencing a <g> or <svg> tag which then contains the <foreignObject> as a child. However, most browsers don't support foreign objects in a <use> element however it is worded.
Although your example of a bulleted list is harmless, there would be serious implementation difficulties from supporting arbitrary copies of any and all HTML, especially when you factor in the way style properties are supposed to be inherited from the <use> element. See this thread on the W3 SVG mailing list for more discussion (use the "next in thread" link to read all the responses).
Browsers currently have enough problems with interactive graphics properties and <use> elements, I would not expect to see an extension of <use> to foreign objects any time soon (although hopefully SVG2 will have clearer language indicating that it isn't possible).
Working around the issue will really depend on the specifics of what you're trying to do. #gilly3 made some suggestions. You may need to resort to Javascript if you want to copy a large chunk of HTML for use in multiple contexts.
If you wrap your <foreignObject> in a <switch> and add a corresponding fallback element (such as <text>) you can reference the <switch> from the <use> and the fallback element will display. Obviously, this is less than ideal. And it doesn't work in FireFox or IE.
http://jsfiddle.net/Uz6XZ/4/
As an alternative, if your goal is just to bring the <foreignObject> to the front, I've found you can do so by specifying position: relative on the <div>. That's a bit of a hack and only works in Chrome, not FireFox or IE.
http://jsfiddle.net/Uz6XZ/3/
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.
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 a star rating component that currently has the following semantic. The SVG are just stars.
<div role='img' aria-label="6 out of 6 ratings">
<svg role="presentation"></svg>
<svg role="presentation"></svg>
<svg role="presentation"></svg>
<svg role="presentation"></svg>
<svg role="presentation"></svg>
<svg role="presentation"></svg>
</div>
I have used the role='img' aria role as I want to ideal treat this image as one image. I have then used the role='presentation' aria role on the SVG as I think the SVG's alone provide no extra information so want to remove the semantic meaning to the SVG and it's children. I read about the presentation role here.
I read a article on SVG accessibility and they go with slightly difference approach. The example they give is the following:
<body>
...
<svg xmlns=http://www.w3.org/2000/svg role="img" aria-labelledby="title desc">
<title id="title">Circle</title>
<desc id="desc">Large red circle with a black border</desc>
<circle role="presentation" cy="60" r="55" stroke="black" stroke-width="2"
fill="red" />
</svg>
…
</body>
They use role='img on the svg. I believe this does not apply to my situation and would be better for me to keep role='presentation' on my SVG?
They use title and desc. I believe that as a single star SVG it would not provide any extra benefit to the user? Also hovering over the SVG would reveal the title (and desc?) which I do not want.
Coming back to my example of how I currently have it:
Is there anything I can do to improve the accessibility/ semantic design to make it more user friendly?
Have I correctly used the right aria role for the container and the SVG?
Should I be able to tab through my rating image (as a whole) as for the aria-label to be read out?
Are there any other aria attributes I should be using?
Looking at the example on semantic-ui, they have no aria roles from what I can see.
The MDN Web docs for img role has a link to a star rating role="img" example
They use aria-hidden instead of role="presentation"
According to the specs, the img role should already make its children presentational
I would add that being accessible implies more than just being accessible for screenreaders. For instance "3 blacks stars, 2 white stars" in the MDN example is something people may not understand (eg. people naturally reading from right-to-left).
"Grandma: Honey, Is it better to have 5 white stars, or 5 black stars?"
I would say that adding "Note: 3/5" next to the ratings, might be a good help.
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?
I have HTML page where I render SVG and all works fine in modern browsers and IE9+. IE8 however doesn't display svg and all I see is empty box. I'm trying to make IE8 and older browsers not to render it at all but all attempts at usual display: none;, width: 0 etc failed. I tried to hide it via JS call but nothing seems to work. If I change width/height directly in HTML it seems to work though. My SVG part is below, if anyone could give me an idea how to get IE not to display this SVG tag that would be great.
<div class="slide panel">
<svg width="1000" height="500">
<mask width="1000" height="500" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" id="m1">
<circle cx="200" cy="200" r="200" fill="white" />
</mask>
<image preserveAspectRatio="xMidYMid slice" mask="url(#m1)" xlink:href="<?php echo get_template_directory_uri(); ?>/images/banner1.jpg" width="1000" height="500" class="target"/>
</svg>
<!-- the rest of HTML code -->
EDIT: this is wordpress site so an option would be detecting what browser made request in php and returning different HTML for IE8 only. Is this reliable solution though? How usually is it done?
EDIT2: Found solution.. I ended up wrapping svg in another div and setting it to display: none; for IE8 only, changing size via JS, css etc didnt work at all on SVG tag itself.. God, I hate IE :/
You don't have to wrap your SVGs into another element. It's sufficient to add proper namespace declarations and target those, like:
[xmlns="http://www.w3.org/2000/svg"] {
display: none;
}
You could also use modernizr, a custom test or a simple html tag switch with conditional comments to add the classes inlinesvg and no-inlinesvg (or something similar), respectively, to the HTML tag:
.no-inlinesvg [xmlns="http://www.w3.org/2000/svg"] {
display: none;
}
Hope this helps!
I would not hide SVG, instead use this little hack that gets the job done.
<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">
Additional Info
Late answer here, but in my testing, Josh C's solution won't work, presumably because since IE8 doesn't know what an <svg> is, it isn't able to apply styles to it.
What worked in my case was to wrap the <svg> in a <div id="svgWrapper">. Then a modification of Josh's solution works quite nicely:
<!--[if lte IE 8]>
<style type="text/css">
#svgWrapper { display: none; }
</style>
<![endif]-->
In my particular case, I was already adding an outer wrapper class in the case of IE, so all I needed was a new style targeting .ie8 #svgWrapper and it seemed to test well.
EDIT: I need to learn to read better. Clearly the OP reached the same conclusion and answer was totally unnecessary.