SVG text accessibility
Asked Answered
P

3

7

I have the following structure

<h2>
  <svg viewBox='-5 -40 100 50'>
    <!-- some filters that get applied on the elements below -->
    
    <clipPath id='c'>
      <text id='t'>Scooby</text>
    </clipPath>
    
    <g clip-path='url(#c)'>
      <rect x='-5' y='-40' width='100%' height='100%'/>
      <path/>
    </g>
    
    <use xlink:href='#t'/>
    <use xlink:href='#t'/>
  </svg>
</h2>

How can I ensure the text inside the clipPath ("Scooby") gets seen by screen readers and only once?

I know SVG text should be read by screen readers, but is that the still the case when it's inside a clipPath element? And what about use copies of it?

I'm using this structure in order to get some fancy effects (think stuff like this) on the heading text (and ditch the .jpg image that's currently used).

Patronizing answered 26/10, 2018 at 6:4 Comment(0)
R
6

Remove the SVG from your screenreader using aria-hidden and define the label for your h2 using aria-labelledby.

<h2 aria-labelledby="t">
  <svg viewBox='-5 -40 100 50' aria-hidden="true">
    <!-- some filters that get applied on the elements below -->

    <clipPath id='c'>
      <text id='t'>Scooby</text>
    </clipPath>

    <g clip-path='url(#c)'>
      <rect x='-5' y='-40' width='100%' height='100%'/>
      <path/>
    </g>

    <use xlink:href='#t'/>
    <use xlink:href='#t'/>
  </svg>
</h2>
Reward answered 26/10, 2018 at 8:11 Comment(2)
@RobertMonfera it does work for me in Chrome, using NVDAReward
This is the best/simplest approach for screen readers. The downside is that it doesn't affect copy & paste: some browsers will copy & paste two copies of your text (for the shadow-DOM text elements in the two <use> elements), some will get nothing (because they don't treat the shadow copies as real text). The text inside the clipPath is never accessible or selectable.Delanos
G
0

Add aria-hidden to suppress screen reading on specific elements, it'll read "Scooby" just once:

<h2>
  <svg viewBox='-5 -40 100 50'>
    <!-- some filters that get applied on the elements below -->

    <clipPath id='c'>
      <text id='t'>Scooby</text>
    </clipPath>

    <g clip-path='url(#c)'>
      <rect x='-5' y='-40' width='100%' height='100%'/>
      <path/>
    </g>

    <use aria-hidden="true" xlink:href='#t'/>
    <use aria-hidden="true" xlink:href='#t'/>
  </svg>
</h2>
Gretchengrete answered 26/10, 2018 at 6:26 Comment(0)
F
0

The aria-label attribute is intended for use when text is not visible on screen

https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute

<h2 aria-label="Scooby">
  <svg> ... </svg>
<h2>

or alternatively, I believe most screen readers will use the <title> SVG element.

<h2>
  <svg>
    <title>Scooby logo</title>
    ...
  </svg>
<h2>

You also have the option of using other ARIA attributes, such as aria-labelledby.

Frantz answered 26/10, 2018 at 6:51 Comment(1)
<title> (or <desc>) is solid general advice, though your code snippet would still need aria-hidden as in my answerGretchengrete

© 2022 - 2024 — McMap. All rights reserved.