SVG accessibility causing invalid HTML (duplicate ID's) - svg

Have an interesting one for the hive. I've done quite a bit of searching about and haven't found an answer to this on S.O. or elsewhere.
I am working on making our website as accessible as possible, this includes providing text alternatives to non-text content. (WCAG 1.1.1)
So far, we've followed the recommendations of CSS Tricks and Sitepoint
https://www.sitepoint.com/tips-accessible-svg/
https://css-tricks.com/accessible-svgs/
by adding:
role="img"
<title>
<desc>
and aria-labelledby, and providing an id for each <title> and <desc>
This works a treat when there is only one of a particular icon on the page. The problem arises when we have the same icon on the page more than once. Because our SVG's are being inlined, id'ing the <title> and <desc> tags will cause validation errors, which is also a no-no for accessibility. ( WCAG 4.1.1 )
So the question then becomes, how can we make our SVGs accessible while still maintaining valid HTML? My first thought was to pull the title and desc text into an aria-label on the tag, but would that then read twice to non-sighted users? Is it fine to leave off the aria-labelledby? Any help is much appreciated!
The full SVG code as it currently stands:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="120px" height="120px" viewBox="0 0 120 120" enable-background="new 0 0 120 120" xml:space="preserve" role="img" aria-labelledby="rings-svg rings-svg-desc" class="rings">
<title id="rings-svg">Ring</title>
<desc id="rings-svg-desc">An empty circle ring</desc>
<g>
<g>
<path fill="#E5E5E5" d="M60,112.151C31.245,112.151,7.85,88.756,7.85,60C7.85,31.245,31.245,7.851,60,7.851
S112.15,31.245,112.15,60C112.15,88.756,88.755,112.151,60,112.151z M60,9.426C32.113,9.426,9.425,32.113,9.425,60
S32.113,110.576,60,110.576S110.575,87.887,110.575,60S87.887,9.426,60,9.426z"></path>
</g>
<g>
<path fill="#E5E5E5" d="M60,117.5C28.295,117.5,2.5,91.705,2.5,60S28.295,2.5,60,2.5s57.5,25.795,57.5,57.5S91.705,117.5,60,117.5
z M60,4.075C29.163,4.075,4.075,29.162,4.075,60S29.163,115.925,60,115.925S115.925,90.838,115.925,60S90.837,4.075,60,4.075z"></path>
</g>
</g>
</svg>

If you can't change the id inside each element, you may be able to insert the accessible alternatives with the id once at the start of the page in a display:none element:
<div style="display:none">
<div id="rings-svg">Ring</title>
<div id="rings-svg-desc">An empty circle ring</desc>
</div>
And then insert your SVG in multiple places in your code
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="120px" height="120px" viewBox="0 0 120 120" enable-background="new 0 0 120 120" xml:space="preserve" role="img" aria-labelledby="rings-svg rings-svg-desc" class="rings">
<title>Ring</title>
<desc>An empty circle ring</desc>
<g>
<g>
<path fill="#E5E5E5" d="M60,112.151C31.245,112.151,7.85,88.756,7.85,60C7.85,31.245,31.245,7.851,60,7.851
S112.15,31.245,112.15,60C112.15,88.756,88.755,112.151,60,112.151z M60,9.426C32.113,9.426,9.425,32.113,9.425,60
S32.113,110.576,60,110.576S110.575,87.887,110.575,60S87.887,9.426,60,9.426z"></path>
</g>
<g>
<path fill="#E5E5E5" d="M60,117.5C28.295,117.5,2.5,91.705,2.5,60S28.295,2.5,60,2.5s57.5,25.795,57.5,57.5S91.705,117.5,60,117.5
z M60,4.075C29.163,4.075,4.075,29.162,4.075,60S29.163,115.925,60,115.925S115.925,90.838,115.925,60S90.837,4.075,60,4.075z"></path>
</g>
</g>
</svg>

Related

Cannot change the size of a use SVG element

this is the raw code I've received. Just a cross defined as a polygon :
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 115.9 80" style="enable-background:new 0 0 115.9 80;" xml:space="preserve">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5
78.8,40.5 "/>
</svg>
and this is what I've done :
<svg class="icons" version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px">
<symbol id="cross">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5 78.8,40.5" style="fill:#6511e4;"/>
</symbol>
</svg>
<div class="cross">
<svg viewBox="0 0 115.9 80" width="15" height="15">
<use href="#cross" id="cross-1"/>
</svg>
</div>
following the solution for the same problem someone else had (Cannot Change SVG <use> icon size when linked to <symbol>)
but this is not working :/ I just want for exemple to resize the cross with a 15px width and 15px height.
Could someone provide me the solution as well as some explanations ? thanks : )
If you encapsulate a SVG drawing in a symbol, the viewBox attribute moves from the <svg> to the <symbol> element.
The viewBox values of your source are not really helpful. A tight bounding box around the grafic can be achieved with viewBox="58.2 28.2 20.6 20.6". You can find it with the original file loaded in a browser. Then do
document.querySelector('polygon').getBBox()
The returned object provides you with x/y/width/height values you can feed into the viewBox.
I'd like to point out there is an implicit sizing going on here: The symbol is shown according to the x/y/width/height values of the <use> element where it is referenced. None of them are present; they default to 0 (position) and 100% (size). In other words: the <use> element just fills its surrounding <svg> element, where width and height are set.
<svg class="icons" width="0px" height="0px">
<symbol viewBox="58.2 28.2 20.6 20.6" id="cross">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5 78.8,40.5" style="fill:#6511e4;"/>
</symbol>
</svg>
<div class="cross">
<svg width="15" height="15">
<use href="#cross" id="cross-1"/>
</svg>
</div>

SVG Path From Polygon Longitudes and Latitudes - issue

I have used the code verbatim from this post to dynamically create SVG paths from Lats & Lngs and for 80% of the time it's working very nicely but I have several polygons that are not rendering correctly in SVG
I have prepared an example in JSFiddle showing 1 that works & 1 that doesn't ...
<div style="padding:20px;">
<div>
Top SVG = NOT Working
<svg width="200" height="200" viewBox="227.131 154.886 0.007 0.006">
<path d="M227.125,154.881 227.125,154.881 227.131,154.881 227.132,154.881 227.132,154.882 227.132,154.886 227.132,154.886 227.131,154.886 227.131,154.886 227.129,154.884 227.126,154.881z"> </path>
</svg>
</div>
<div>
Bottom SVG = Working
<svg width="200" height="200" viewBox="227.136 154.905 0.009 0.014">
<path d="M227.145,154.907 227.140,154.905 227.141,154.910 227.138,154.914 227.136,154.919 227.141,154.919 227.145,154.919 227.145,154.916 227.145,154.912z M227.139,154.914 227.140,154.913 227.141,154.913 227.141,154.913 227.141,154.914 227.140,154.914 227.139,154.914z"> </path>
</svg>
</div>
</div>
I'd appreciate it if someone could point out my issue.
ALSO - I would like to know how and where to include a stroke color & width in this html. Thanks!!
I think there are a couple of problems with the first SVG:
The viewBox is incorrect. It doesn't match the shape. It should be more like:
viewBox="227.125 154.881 0.007 0.005"
The first two values (minX and minY) were wrong. How did this happen? I don't know. The code in that question looks alright at first glance, but I haven't attempted to debug it.
Secondly, I think there is likely a floating point issue. There are five orders of magnitude difference between the x and y offset of the shape, and its size. It seems you may be striking some floating point rounding issues, or something like that.
If you reduce the x and y coordinates, the shape renders correctly.
<div style="padding:20px;">
<div>
Top SVG = NOT Working
<svg width="200" height="200" viewBox="7.125 4.881 0.007 0.005">
<path d="M7.125,4.881 7.125,4.881 7.131,4.881 7.132,4.881 7.132,4.882 7.132,4.886 7.132,4.886 7.131,4.886 7.131,4.886 7.129,4.884 7.126,4.881z"
stroke="red" stroke-width=".0002"/>
</svg>
</div>
<div>
Bottom SVG = Working
<svg width="200" height="200" viewBox="227.136 154.905 0.009 0.014">
<path d="M227.145,154.907 227.140,154.905 227.141,154.910 227.138,154.914 227.136,154.919 227.141,154.919 227.145,154.919 227.145,154.916 227.145,154.912z M227.139,154.914 227.140,154.913 227.141,154.913 227.141,154.913 227.141,154.914 227.140,154.914 227.139,154.914z"> </path>
</svg>
</div>
</div>
To avoid this problem with other shapes, you could modify the code to subtract the minX and minY value from all the coordinates. After you fix issue #1, though, of course!
The first SVG is located outside the drawing area/viewBox, however You can add the stroke inside the <g> tag that wraps the graphic, as in the second SVG theres two shapes and I added stroke to one only.
Check this code:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<g stroke-width="3" stroke="#00CF00">
<polygon points="15,81 113,9 170,172 52,189 "/>
</g>
</svg>
<br />
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<circle cx="96.3" cy="93" r="62.3"/>
<g stroke-width="3" stroke="#FFFFFF">
<polygon style="fill:#00CF00;" points="71.7,56 144,92 71.7,128.3 "/></g>
</svg>

SVG xlink:href not working in Chrome

I'm new to SVG. I'm trying to put a SVG file with linkable regions (like an image map) on my page and make it responsive. The SVG displays, but the linkable areas aren't working in Chrome. Works fine in FF, IE11, and Edge.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 880 371" style="enable-background:new 0 0 880 371;" xml:space="preserve">
<g id="Background_xA0_Image_1_">
<image style="overflow:visible;" width="880" height="371" id="Background_xA0_Image" xlink:href="data:image/jpeg;... />
</image>
</g>
<g id="Layer_2_xA0_Image_1_">
<a id="Layer_2_xA0_Image" xlink:href="http://www.example.com" transform="matrix(1 0 0 1 572 215)">
<image style="overflow:visible;" width="195" height="42" xlink:href="data:image/png;...>
</image>
</a>
</g>
<g id="Layer_1_xA0_Image_1_">
<a id="Layer_1_xA0_Image" xlink:href="http://www.anotherexample.com" transform="matrix(1 0 0 1 308 164)">
<image style="overflow:visible;" width="137" height="46" xlink:href="data:image/png;...>
</image>
</a>
</g>
</svg>
I'm working with a JPG file that I sliced up in Photoshop and then exported to a SVG from Illustrator. This is the code it produced.
Just realized elements within the svg are clickabel - the problem was actually the cursor not changing styles so I thought it wasn't working.
I added cursor:pointer; to the links and it looks good now.

SVG rotation cuts off the edge

I am trying to rotate a SVG on a T-Shirt designer project but edges of the SVG are getting cut off. The code for the SVG is as follows:
Before Rotation (Everything is correct in this)
<g xmlns="http://www.w3.org/2000/svg" transform="scale(2,2)rotate(0,50,50)" id="clip1">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace" enable-background="new 0 0 100 100" viewBox="0 0 100 100" height="100px" width="100px" y="0px" x="0px" id="Layer_1" version="1.1">
<g>
[POLYGON CODE WAS HERE]
</svg>
</g>
After Rotation (One of the edges is getting cut off!!!)
<g xmlns="http://www.w3.org/2000/svg" transform="scale(2,2)rotate(45,50,50)" id="clip1">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace" enable-background="new 0 0 100 100" viewBox="0 0 100 100" height="100px" width="100px" y="0px" x="0px" id="Layer_1" version="1.1">
<g>
[POLYGON CODE WAS HERE]
</svg>
</g>
Everything in the above 2 codes is the same except for the rotate(...) function.
The screenshot of what is going wrong can be found here - http://i.imgur.com/Kr5Azx3.png. In the right side image, the elbow is cut off as well as the background behind that. The SVG file code is present here - http://pastebin.com/LfC7TkwV
Is this the default behavior of SVG rotation or am I missing some other tag to make this work? Any help will be really appreciated.
Thanks.
As Erik says, the rotate operation is causing part of the design to fall outside the viewport. You may have to add a small translate() to your transform, and/or enlarge the size of your viewBox so that it encompasses the new larger bounding box.

canvas in foreignObject in defs/use not displayed

I want to use JavaScript to draw on an html5 canvas embedded in svg (in an html5 page). Drawing on "cvs" works just fine if done this way:
<svg id="fig" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024">
<foreignObject x="0" y="0" width="512" height="512">
<body xmlns="http://www.w3.org/1999/xhtml">
<canvas id="cvs" width="512" height="512"></canvas>
</body>
</foreignObject>
</svg>
but not if done with the canvas in and referred to in a use tag. The drawing simply doesn't appear. Inspecting the element in Safari tells me that the the dimensions of the use element are NaN x NaN; Firebug says 0x0.
<svg id="fig" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024">
<defs>
<foreignObject id="circles" x="0" y="0" width="512" height="512">
<body xmlns="http://www.w3.org/1999/xhtml">
<canvas id="cvs" width="512" height="512"></canvas>
</body>
</foreignObject>
</defs>
<use x="0" y="0" xlink:href="#circles"></use>
</svg>
Is this a bug? Expected behavior? Do I just not understand how to use foreignObject (highly likely)?
You can't point to a foreignObject element directly, it says so in the SVG specification
‘svg’, ‘symbol’, ‘g’, graphics element or other ‘use’ only. So you could point to a <g> or <svg> element that had a <foreignObject> element as a child for instance.

Resources