Search code examples
svgaccessibilitypagespeed

Can I use an SVG title tag as an input label?


PageSpeed Insights is complaining with "Form elements do not have associated labels" on our site.

The relevant code I'm using is:

<input id="input-1" type="checkbox">
<label for="input-1">
  <svg>
    <title>This is the label text</title>
    <!-- rest of svg -->
  </svg>
</label>

Should this be sufficiently accessible? (I understand that using SVG icons without text is not optimal accessibility for sighted users, but that is not what PageSpeed is complaining about here.)


Solution

  • The Computation steps in the Accessible Name and Description Computation standard specifically mention the <title> element as a valid means to provide text for a label.

    E. Host Language Label: Otherwise, if the current node's native markup provides an attribute (e.g. alt) or element (e.g. HTML label or SVG title) that defines a text alternative, return that alternative in the form of a flat string as defined by the host language, unless the element is marked as presentational (role="presentation" or role="none").

    (I emphasised the important part)

    So when it comes to conformance, you’re good.

    But, what is important for accessibility is also the practical part. How many users have difficulties due to insufficient support in browsers or in assistive technology? You should definitely test this.

    According to a11y support, the SVG <title> element had no support in VoiceOver on iOS, and only partial support on macOS. I can confirm that it’s still an issue in Firefox.

    I would recommend using either aria-label or a visually hidden element to provide alternative texts for SVG icons.

    /* https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html */
    .visually-hidden:not(:focus):not(:active) {
      clip: rect(0 0 0 0); 
      clip-path: inset(50%);
      height: 1px;
      overflow: hidden;
      position: absolute;
      white-space: nowrap; 
      width: 1px;
    }
    <input id="input-1" type="checkbox">
    <label for="input-1">
      <svg aria-label="This is the label text" data-altlabel="svg-title" width="50" height="50">
        <title id="svg-title">This is the label text</title>
        <!-- rest of svg -->
        <rect width="50" height="50" fill="#cc0000"></rect>
      </svg>
    </label>
    
    <input id="input-2" type="checkbox">
    <label for="input-2">
      <span class="visually-hidden">This is the label text</span>
      <svg aria-hidden="true" width="50" height="50">
        <!-- rest of svg -->
        <rect width="50" height="50" fill="#cc0000"></rect>
      </svg>
    </label>