问题
The way to provide an accessible name for an <img>
element is via its alt
attribute. Similarly, the way to provide an acessible name for an <svg>
element is via its <title>
element.
If I have an img
tag within an a
tag, the accessible name of the link is the accessible name of the img
. However, if I have an svg
within an a
tag, the link has has no accessible name even if the svg
does. Why is this?
This is apparent within both Lighthouse audits and also the Accessibility tab of Firefox dev tools.
<a href="/fern">
<img src="/bracken" alt="Bracken" />
</a>
<a href="/fern">
<svg role="img" viewBox="0 0 100 100">
<title>Bracken</title>
<use xlink:href="/ferns_sprite.svg#bracken"></use>
</svg>
</a>
I could add an aria-label to the link, but that seems like duplication.
回答1:
Short Answer
Visually hidden text is still the most robust way to ensure link text is read out.
There are other ways of doing this that are neater such as using the alt
attribute on an external image or aria-labelledby
on an inline SVG so I have included those in the answer below.
Long Answer
Most modern screen readers will not have a problem with this (NVDA and JAWS both read the title text in my quick test) but some older ones (including old versions of NVDA, JAWs etc.) will not work.
I believe that the comment that "desc" is the equivalent of "alt" is not correct as I explained in this answer on title vs description on SVG (the first three lines are relevant).
To further expand on this here is what the W3C says about SVGs in the proposed spec update:-
The ‘title’ child element represents a short text alternative for the element.
On a link, this could be the title or a description of the target resource; on an image or drawing object, it could be a short description of the graphic; on interactive content, it could be a label for, or instructions for, use of the element; and so forth.
source: https://www.w3.org/TR/SVG2/struct.html#TitleElement
The ‘desc’ element represents more detailed textual information for the element such as a description. This is typically exposed to assistive technologies to provide more detailed information, such as a description of the visual appearance of a graphic or help to explain the functionality of a complex widget. It is not typically available to other users, so should not be used for essential instructions.
source: https://www.w3.org/TR/SVG2/struct.html#DescElement
External SVGs
For external SVG files the recommended way to ensure text is read is to use alt
tags. This may mean slight duplication but alt attributes work back to ie4!
Keep your title
attribute as if someone accesses the image directly they will still get some description of what the image contains.
Inline SVGs
For this you should give your title
an ID. Then add aria-labelledby
to the surrounding link. As stated in the question I linked you can also give the <description>
an ID and link both of them if you wish.
The downside is that aria-labelledby is not as well supported as you might think, but it is perfectly valid and passes WCAG recommendations.
<a href="/fern">
<svg role="img" viewBox="0 0 100 100" aria-labelledby="linkText">
<title id="linkText">Bracken</title>
<use xlink:href="/ferns_sprite.svg#bracken"></use>
</svg>
</a>
The most robust way - visually hidden text.
The above two ways of doing this are correct, but if you support Internet Explorer (which you should if you care about accessibility as usage of IE is higher in the screen reader community) then the most robust way is still visually hidden text.
Visually hidden text is not visible on the screen but will still be read by a screen reader.
Please use the CSS class below to hide text as it has better compatibility than bootstrap sr-only class as explained in this answer I gave.
Notice how I completely hide the SVG in both circumstances using aria-hidden="true"
and also add focusable="false"
on the inline SVG due to Internet Explorer and older Opera browsers making SVGs interactive. The empty alt=""
is still required as a fallback for screen readers that don't fully support aria
.
The below should work all the way back to IE6 and with the CSS class provided should hopefully work for several years to come!
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<a href="/fern">
<span class="visually-hidden">Bracken</span>
<svg role="img" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<title>Bracken</title>
<use xlink:href="/ferns_sprite.svg#bracken"></use>
</svg>
</a>
<a href="/fern">
<span class="visually-hidden">Bracken</span>
<img src="/bracken" alt="" aria-hidden="true" />
</a>
来源:https://stackoverflow.com/questions/63208144/why-does-a-link-not-take-the-title-of-a-contained-svg-as-its-accessible-nam