Home > Enterprise >  Hide and SVG's animate ids for accessibility purposes
Hide and SVG's animate ids for accessibility purposes

Time:12-28

I'm doing a react component which is an SVG animation. The react component's code is something like this:

const Loading = ({ className, ...props }) => {
  return (
    <svg
      aria-label="animated block"
      width="32"
      height={"32"}
      className={className}
      {...props}
    >
      <rect x="1" y="0" width="19" height="8" opacity="0.4" rx="5">
        <animate
          id="anim1"
          attributeName="width"
          from="19"
          to="8"
          begin="0s;anim2.end"
          dur="0.3s"
        />
        <animate
          id="anim2"
          attributeName="width"
          from="8"
          to="19"
          begin="anim1.end"
          dur="0.3s"
        />
      </rect>
    </svg>
  )
}

When showing a page with more than one of these, the accessibility linters show me the error "id attribute value must be unique".

Is there any way to avoid this error?

I've tried using aria-hidden both in the svg element and in each animate element, but with no success.

CodePudding user response:

It seems like the only reason you currently need IDs on those <animate> elements is because you have two separate animations that each start when the other ends:

<svg width="32" height="32" viewBox="0 0 32 32">
  <rect x="1" y="0" width="19" height="8" opacity="0.4" rx="5">
    <animate id="anim1" attributeName="width" from="19" to="8" begin="0s;anim2.end" dur="0.3s" />
    <animate id="anim2" attributeName="width" from="8" to="19" begin="anim1.end" dur="0.3s" />
  </rect>
</svg>

It would be better to write this as a single <animation> element, using the values attribute and repeatCount instead of to and from attributes on two animation elements that reference each other. The exact same animation can be achieved like this:

<svg width="32" height="32" viewBox="0 0 32 32">
  <rect x="1" y="0" width="19" height="8" opacity="0.4" rx="5">
    <animate attributeName="width" values="19;8;19" to="8" dur="0.6s" repeatCount="indefinite" />
  </rect>
</svg>

This eliminates the need to reference one element from another, and therefore removes the need for IDs entirely.

CodePudding user response:

Maybe you can pass a unique id in props

Example:

const Loading = ({ className, id, ...props }) => {
  return (
    <svg
      aria-label="animated block"
      width="32"
      height={"32"}
      className={className}
      {...props}
    >
      <rect x="1" y="0" width="19" height="8" opacity="0.4" rx="5">
        <animate
          id={`${id}-anim1`}
          attributeName="width"
          from="19"
          to="8"
          begin="0s;anim2.end"
          dur="0.3s"
        />
        <animate
          id={`${id}-anim2`}
          attributeName="width"
          from="8"
          to="19"
          begin="anim1.end"
          dur="0.3s"
        />
      </rect>
    </svg>
  )
}

  • Related