question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Accessibility issues with Turbo navigation

See original GitHub issue

Hi Turbo team,

Our team migrated to using turbo drive and turbo frame in our Rails app around 3 months ago. We have received reports and discovered that turbo navigation poses accessibility issues for our screen reader users. Some of these issues, we can alleviate on our end through better guidance and additional accessibility feedback updates. Other issues, we do not see any workarounds for. We wanted to share our investigation and the feedback we’ve gotten with you.

Findings

Expected behavior

With a standard, hard page navigation, there are default mechanisms built in that allow a browser to communicate to a screen reader user that page navigation has taken place. For instance, when page navigation happens, the page title will be announced by the screen reader.

In addition, some screen readers have settings that can be toggled to specify what happens when loading a new web page like “Speak webpage summary” or “Automatically speak the webpage”. When these settings are toggled, a screen reader user can expect certain announcements to be made on page load.

Turbo frame

When a turbo frame navigation happens, there is no feedback given to screen reader users to indicate anything has happened.

Turbo drive

  • When a turbo drive navigation happens, there is inconsistent feedback given to screen reader users to indicate anything has happened. We saw inconsistent results across different screen reader and browser combinations.
    • With VoiceOver/Safari, the new page title is announced somewhat frequently.
    • With NVDA/Chrome, the announcement is much more infrequent or non-existent. The most commonly used screen readers are NVDA and JAWS so announcements being made in VoiceOver is not enough. (Source: WebAim: Screen Reader / Browser combinations) The screen reader settings for behavior that should happen at page load like, “Speak webpage summary” or “Automatically speak the webpage” are not respected, even in scenarios where the page title is announced.

Workarounds and Caveats

  • We worked around the lack of page navigation announcements by populating the aria-live region with the page title. We use this approach for both turbo frame and turbo drive navigations. However there are still caveats to this.
    • We noted above that with turbo drive, page title announcements are inconsistently made. As a result, we end up with duplicate page title announcements at times. We are not sure if there’s anything within turbo drive that results in page title announcements, but it is inconsistent and need to ensure it happens.
    • Similarly, with turbo drive, the entire body gets swapped out. aria-live region needs to be on the page, then updated dynamically for it to work. In order to trigger the announcement of the page title when a turbo drive navigation happens, we had to rely on a hack to insert an aria-live region to the page on page load, then update the content 200ms delay to trigger the announcement. This is not ideal.
  • We are also working internally to provide better guidance for turbo-frame use to avoid accessibility issues.
  • It’s worth calling out that aria-live regions are not supported on braille displays so aria-live regions aren’t enough to convey that something has happened. With a regular page navigation, the browser can communicate the page title as needed to display on the braille display. This means that people who rely on braille readers will not benefit from the aria-live workaround
  • We’ve determined there is no way for us to guarantee that the screen reader settings like “Speak webpage summary” or “Automatically speak the webpage”. This is not something we can or would want to implement ourselves.

Other issues

Because the focus can get completely lost on a turbo frame or turbo drive navigation, focus management is necessary. . We have found that some of this comes down to us using turbo frame when we shouldn’t be, but others of these, we’ll need to carefully manage focus, We are still figuring out how focus management should be handled in various scenarios but wanted to call out that this is a problem.

Videos

We’ve recorded some videos in a sandbox environment to demonstrate these findings below:

https://user-images.githubusercontent.com/16447748/197065530-6dee9d4a-df29-4a9d-9118-ae684c2f1a12.mp4

This video demonstrates the issues of turbo drive with VoiceOver/Safari.

  • I am navigating in a sandbox environment that has been set up for testing.
  • I have the VoiceOver utility settings open showcasing that the “Speak page summary” setting is on in VoiceOver.
  • I first navigate to a link with turbo drive disabled. VoiceOver announces the page title of the new link and provides a summary of the navigated page.
  • I then navigate with turbo enabled. With turbo drive, VoiceOver does announce the page title of the new link, but does not provide a summary of the navigated page as expected.

https://user-images.githubusercontent.com/16447748/197065550-fb4f5572-183a-4f98-878d-dc31abd5a863.mp4

This video demonstrates the issues of turbo drive with NVDA/Chrome.

  • I am navigating in a sandbox environment that has been set up for testing.
  • I have my NVDA settings open showcasing that the Automatic say all on page load box is checked.
  • I first navigate to a link with turbo drive disabled. NVDA reads out the page title and speaks everything on the page.
  • I then navigate back and to the same link with turbo drive enabled. With turbo drive, NVDA does not announce the page title nor does it respect the setting to speak everything on the page.

https://user-images.githubusercontent.com/16447748/197065564-5095cbd9-f5d8-44af-907b-6a33d61ab2f4.mp4

This video demonstrates the issues of turbo frame with NVDA/Chrome.

  • I am navigating in a sandbox environment that has been set up for testing.
  • There are demos set up for basic frames, promoted frames, and target _top frames.
  • I first navigate through these links with turbo drive disabled. NVDA reads out the page title when I activate the links, and also announces all the content on the page, according to the Automatic say all on page load setting.
  • I then navigate through the same frames with turbo enabled. With turbo frame, nothing is announced indicating page navigation has happened.

In summary

While websites built in Rails can come with some accessibility benefits baked in, and Turbo enables these systems to incorporate more app-like behaviors, the way that Turbo is handling some specific cases of navigation negate those accessibility benefits.

We wanted to pass along our findings so that these concerns can be addressed appropriately and more accessibility guidance can be provided to consumers of Turbo, especially since Turbo is reaching wider adoption in the Rails community.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:17
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
brunoprietogcommented, Oct 25, 2022

Maybe it’s controversial what I’ll say, but as a blind user, one of the things I like most about SPAs is that I don’t have to hear notices that a page changed or hear the page summary every time it loads. I simply enter on a link and continue using the application normally as if nothing happened. I understand that this doesn’t respect the screen reader settings when changing pages, but that’s really what you’re looking for, to have the feeling that the page doesn’t reload.

However, the focus management issue can be a bit awkward. For example, the button to add a star to a GitHub repository. If you press it, the screen reader should indicate that now the button is not to add a star, but to remove it. But that doesn’t happen, the screen reader simply mutes and you have to move with up and down arrows to identify that the same button now says something else. I know that’s not a turbo frame, but it’s an example that has similar behavior and produces the same effect. I’m used to it and it doesn’t bother me, but I admit that it can be confusing.

Another thing that might be useful is that Firefox with NVDA always announces page changes. On GitHub, this translates to always hearing page announcement messages twice, unless navigating using turbo frames.

While this might be a problem, I think there are other much more important accessibility issues. In my opinion, I would not consider these types of errors to be serious accessibility issues.

Thinking of some proposal to handle focus, one could listen to a global or Turbo frame visit and focus on some important element, such as the main region or an important element of the Turbo frame. I think this is much more comfortable than receiving the focus at the top of the page, but this is more a matter of personal taste and it is very difficult to reach agreements.

Maybe there could be some meta tag that contains the id of an element that turbo should focus on the next visit. There could also be another meta tag containing the announcement for screen readers.

Another option could be to default to announcing the page title every time a change occurs on the page. I don’t think it’s such a big deal to have a message announced twice, considering that most users stop announcements that are no longer relevant with the control key.

For a temporary solution, the announcement message could be in a permanent div with aria-live. Instead of replacing the body element every time turbo makes a visit, one would have to listen for the turbo:before-visit event, and look for an element like div#app, changing the element that is replaced. This trick works since Turbo 7.2 and is also recommended when there are iframes from external services that do not survive the replacement of the body element. In this way, the delay of the announcement to screen readers could be removed.

In addition, it is currently possible to focus on a specific element with the autofocus attribute each time turbo performs a visit. While the specification says that autofocus works with button, input, select and textarea HTML elements, I have been able to verify that it works with any element that can be focused by the browser using Turbo.

I think it is unfair to say that an application that uses Turbo has serious accessibility problems. As a blind user I really appreciate using applications like Hey, Basecamp or GitHub itself, even when you started using Turbo and did not announce page changes, and while it may be a drawback, I think it is much more serious not to respect things like header levels, regions, modal dialogs, cmboboxes, menus, etc.

I don’t think developers using Turbo are making applications inaccessible just because of that. In my opinion, the conclusion is more alarmist than it really is.

Probably this discussion goes beyond what is expected from accessible web browsing in a SPA. Gatsby, for example, forces the screen reader to read the entire contents of the newly loaded page in all cases. Next.js only reads the title of the new page, which it extracts from the page title or a level 1 header.

Summarizing, I think a good starting point would be for Turbo to announce by default the change of a page title when browsing, giving some option to set up a custom announcement and an element to focus during the next visit.

What do you think? It would be interesting to hear more experiences from screen reader users.

1reaction
brunoprietogcommented, Oct 28, 2022

Hi @manuelpuyol,

I discovered something else yesterday.

If you apply morphdom when replacing instead of using replaceWith, I notice a big improvement in focus management.

import morphdom from "morphdom"

addEventListener("turbo:before-render", ({ detail }) => {
  detail.render = morphdom
})

For example, if I am in a navigation bar that has links and the link representing the current page is marked with aria-current=“page”, when I press enter on one of the links that redirects to a new page, the focus is not lost and the screen reader immediately says “current page”.

So, I thought the same could result for turbo frames, and there is a big improvement. The problem is that sometimes it fails but I can’t detect the error, and I don’t know if there is some Turbo error when evolving an incorrect turbo frame or morphdom is not able to process the new turbo frame.

What do you think about this? Would you be willing to investigate something like this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Issues · hotwired/turbo - GitHub
Accessibility issues with Turbo navigation. #774 opened on Oct 21 by khiga8 · 6 · turbo-cable-stream-source is not getting replaced.
Read more >
Navigation accessibility failures - AccessibilityOz
When navigation is not present, is broken, or is not readable by all users, web content becomes inaccessible. In order for your web...
Read more >
Navigate with Turbo Drive - Hotwire Turbo
Turbo Drive issues restoration visits in response to history navigation that has already taken place, typically via the browser's Back or Forward buttons....
Read more >
Heading Levels | PDF Accessibility and Compliance
Heading levels represent the basic model for navigation in most web content and in PDF files as well (back in the day, PDF...
Read more >
Navigation - Usability & Web Accessibility - Yale University
Navigating through repeated blocks of content on each page, such as headers and menus, can be tedious. Websites should provide skip links to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found