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.

Tab-based navigation on Gatsby sites is broken

See original GitHub issue

Description

Gatsby puts page content in a div with tabindex="-1" which means clicking anywhere in the page resets tab focus back to the top. The normal behaviour is that focus is sent to the focusable element that is nearest to the click.

The div in question is:

<div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper">

I think this is likely an accessibility regression. If not, it is at least a deviation from how tab-based navigation is expected to work.

As I understand this is some trick to achieve focus trapping/locking that is brought over by @reach/router but it’s not clear to me how this is an improvement over the default behaviour that I see on almost every well-built site I visit (e.g. https://gov.uk - an accessibility champion to me).

Steps to reproduce

  1. Go to https://gatsbyjs.com and scroll towards the middle of the page then double click to select the word “multiple” as I have done in the screenshot below:
image
  1. Now hit the <kbd>Tab</kbd> key and you should see that the “Skip to content” link at the top of the page is focused (the actual behaviour) instead of the “Explore 2000+ plugins” link in the screenshot (the expected behaviour). It’s quite jarring the lower down the page you are and then hitting tab either intentionally or indavertently only to get sent back to the top of the page.

  2. To establish that the current behaviour is broken, in your devtools locate the #gatsby-focus-wrapper div and delete the tabindex="-1" attribute from it.

  3. Now repeat steps 1 and 2. This time you’ll notice that the focus goes to the “Explore 2000+ plugins” link as expected.

Expected result

Covered in steps to reproduce

Actual result

Covered in steps to reproduce

Environment


  System:
    OS: macOS 10.15.7
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
    Shell: 5.7.1 - /usr/local/bin/zsh
  Binaries:
    Node: 12.18.1 - /var/folders/11/zcvk9j4j7rd_dj0t5hcv9wc80000gp/T/yarn--1610674348120-0.6652836311657397/node
    Yarn: 1.22.5 - /var/folders/11/zcvk9j4j7rd_dj0t5hcv9wc80000gp/T/yarn--1610674348120-0.6652836311657397/yarn
    npm: 6.14.10 - /usr/local/bin/npm
  Languages:
    Python: 2.7.16 - /usr/bin/python
  Browsers:
    Chrome: 87.0.4280.141
    Firefox: 84.0.2
    Safari: 14.0.2
  npmGlobalPackages:
    gatsby-cli: 2.12.87

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

10reactions
agusterodincommented, Nov 14, 2021

This is a huge deal. I’m surprised that more people haven’t noticed or don’t care.

I understand that this is to help screen reader users start at the beginning of a page on route change but what Reach did is pretty annoying. Breaking the standard behavior for users that switch between keyboard and mouse frequently (like me) is no solution. I opted to manually focus to the first h1 in the content container on route change to accommodate screen reader users.

I ended up getting rid of the tabindex in the focus wrapper with this:

useEffect(() => {
    const gatsbyFocusWrapper = document.getElementById('gatsby-focus-wrapper')
    if (gatsbyFocusWrapper) {
      gatsbyFocusWrapper.removeAttribute('style')
      gatsbyFocusWrapper.removeAttribute('tabIndex')
    }
  }, [])
7reactions
vladarcommented, Jan 15, 2021

Thank you for opening this @disintegrator

Gatsby uses reach-router and tabindex is set there to control focus for screen-reader environments: https://github.com/reach/router/blob/e203fe612236851a0bd3c77dba693e539a351c62/src/index.js#L376

I understand that this is confusing but this was discussed previously in-depth here: https://github.com/gatsbyjs/gatsby/issues/7310 and https://github.com/reach/router/issues/63

We will have to replace reach/router to actually fix it.

I am going to close this as a duplicate because there is nothing actionable on our side at the moment. We can get back to it if we decide to go away from reach-router.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nested router inside of Gatsby layout component
Currently I have a layout component that contains my site header and side navigation menu. Each page loads within the body of the...
Read more >
Gatsby Link API
For internal navigation, Gatsby includes a built-in component for creating links between internal pages and a navigate function…
Read more >
Accessible tabbed navigation with React - clubmate.fi
Modern and accessible tabbed navigation which spark joy in the user and in the dev. For tabs to be good it needs to...
Read more >
React: Navigation Without React-Router - Nick Coughlin
For example if you don't want to have to update your application when the React-Router library makes a breaking change, which is about...
Read more >
Creating a Gatsby Site with WordPress Data - CSS-Tricks
Again, Muhammad's post is excellent help because it breaks down what ... Porting navigation menu from the WordPress into Gatsby site turns ...
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