RedwoodJS

中国镜像

# Accessibility (aka a11y)

We built Redwood to make building websites more accessible (we write all the config so you don't have to), but Redwood's also built to help you make more accessible websites. Accessibility shouldn't be a nice-to-have. It should be a given from the start, a core feature that's built-in and well-supported.

There's a lot of great tooling out there that'll not only help you build accessible websites, but also help you learn exactly what that means.

With all this tooling, do I still have to manually test my application?

Unequivocally, yes. Even with all the tooling in the world, manual testing's still important, especially for accessibility. The GDS Accessibility team found that automated testing only catches ~30% of all the issues.

But just because the tools don't catch 'em all doesn't mean they're not valuable. It'd be much harder to learn what to look for without them.

# Accessible Routing with Redwood Router

For single-page applications (SPAs), accessibility starts with the Router. Without a full-page refresh, you just can't be sure that things like announcements and focus are being taken care of the way they're supposed to be. Here's a great example of how disorienting SPAs can be to screen-reader users. On navigation, nothing's announced. It's important not to understate the severity of this; the lack of an announcement isn't just buggy behavior, it's broken.

Normally the onus would be on you as a developer to announce to screen-reader users that they've navigated somewhere new. That's a lot to ask, and hard to get right, especially when you're just trying to build your app. Luckily, if you're writing good content and marking it up semantically, there's nothing you have to do! Redwood automatically and always announces pages on navigation. Redwood looks for announcements in this order:

  1. RouteAnnouncement
  2. h1
  3. document.title
  4. location.pathname

The reason for this is that announcements should be as specific as possible; more specific usually means more descriptive, and more descriptive usually means that users can not only orient themselves and navigate through the content, but also find it again. If you're not sure if your content is descriptive enough, see the W3 guidelines.

Even though Redwood looks for a RouteAnnouncement first, you don't have to have one on every page—it's more than ok for the h1 to be what's announced. RouteAnnouncement is there for when the situation calls for a custom announcement.

The API is simple: RouteAnnouncement's children will be announced; note that this can be something on the page, or can be visually hidden using the visuallyHidden prop:

// web/src/pages/HomePage.js

import { RouteAnnouncement } from '@redwoodjs/router'

const HomePage = () => {
  return (
    // this will still be visible
    <RouteAnnouncement>
      <h1>Welcome to my site!</h1>
    <RouteAnnouncement>
  )
}

export default HomePage 
// web/src/pages/AboutPage.js

import { RouteAnnouncement } from '@redwoodjs/router'

const AboutPage = () => {
  return (
    <h1>Welcome to my site!</h1>
    // this won't be visible
    <RouteAnnouncement visuallyHidden>
      All about me
    <RouteAnnouncement>
  )
}

export default AboutPage 

Whenever possible, it's good to maintain parity between the visual and audible experience of your app. That's just to say that visuallyHidden shouldn't be the first thing you reach for. But it's there if you need it!

Note that if you have more than one RouteAnnouncement, Redwood uses the most specific one, that way if you have multiple layouts, you can override as needed.