How a Blind Developer Fixed Screen Reader Focus Jumping in Drupal Core

By Yahya , GABLVM Staff, 5 March 2026

I am Yahya, and at GABLVM (Global Advocacy of Blind and Low Vision Muslims), we build accessible digital experiences for our community. I am a blind developer who uses VoiceOver on macOS and iOS, JAWS, and NVDA daily. When I encounter accessibility barriers, I do not just report them. I fix them.

This is the story of how I found and fixed a screen reader bug in Drupal core that has likely affected every VoiceOver user who has ever administered a Drupal website.

The Bug: Focus Jumping on Every Tap

While administering our Drupal 11 website, I noticed something frustrating. With the toolbar open (say, the Shortcuts tray), every time I tapped on page content, VoiceOver would announce a toolbar element instead of what I actually tapped. I would tap on a heading, and VoiceOver would say "Structure." I would tap on a paragraph, and it would say "Appearance." The focus was jumping into the toolbar tray instead of landing on the page content I was trying to interact with.

This was not a minor annoyance. It made the entire admin experience unusable for screen reader users who rely on touch navigation. Every interaction with the page became a fight against the toolbar stealing focus.

Understanding the Root Cause

To understand why this happens, you need to know two things about VoiceOver and the Drupal toolbar.

First, VoiceOver uses spatial hit-testing. When you tap on the screen, VoiceOver does not just check what DOM element is under your finger. It builds an accessibility tree of all visible elements, then performs a spatial lookup: essentially asking "what accessible element occupies this screen coordinate?" This is different from how a mouse click works.

Second, Drupal toolbar trays use position: fixed. When a tray is open (like Shortcuts or Administration), it is fixed to the top of the viewport. Even though it might only be visually 39 pixels tall, its accessible elements remain in the accessibility tree and are positioned at the top of the screen in VoiceOver spatial coordinates.

The result: VoiceOver spatial hit-testing on anything near the top of the viewport would land on the fixed-position toolbar tray instead of the page content behind it. The tray was invisible to sighted users at that scroll position, but fully visible to assistive technology.

The Fix: inert + aria-hidden

The solution uses two complementary attributes to fully isolate toolbar trays from assistive technology while keeping them visually open and mouse-accessible:

  • inert. This HTML attribute makes an element and all its descendants non-interactive. It removes them from the tab order, blocks click events, and critically, removes them from the accessibility tree. This is what stops VoiceOver spatial hit-testing from landing on tray elements.
  • aria-hidden="true". This removes elements from the accessibility tree. While inert alone should be sufficient, we found that aria-hidden provides an additional layer of protection, particularly for VoiceOver tap gestures.

Here is how the fix works:

  1. All trays start inert. When the toolbar initializes, every tray gets the inert attribute. Closed trays are completely blocked from assistive technology.
  2. When a tray opens, it stays inert and gets aria-hidden. This is the key insight. The tray is visually open, but completely blocked from interaction. Neither assistive technology nor mouse clicks can reach it. Sighted mouse users access the tray through the toolbar trigger buttons, just like keyboard users.
  3. Tab-to-enter pattern. When a keyboard or screen reader user wants to access the tray, they press Tab from the toolbar trigger button. This removes both inert and aria-hidden, making the tray fully interactive. Focus moves to the first focusable element in the tray.
  4. Focus-out restores isolation. When focus leaves the tray (by tabbing past the last element or clicking elsewhere), inert and aria-hidden are restored, hiding the tray from assistive technology again.
  5. Escape closes the tray. Pressing Escape closes the active tray and returns focus to the trigger button that opened it.

Why aria-hidden Alone Was Not Enough

During development, we tried using only aria-hidden="true" without inert. While aria-hidden does remove elements from the accessibility tree, VoiceOver on iOS and macOS still performed spatial hit-testing that could land on the fixed-position tray elements. The inert attribute was necessary to fully block VoiceOver from reaching those elements.

This is an important detail for accessibility engineers: aria-hidden tells assistive technology to ignore an element, but it does not prevent the browser from including the element in layout calculations that VoiceOver uses for spatial navigation. inert is the stronger guarantee.

Testing Across Screen Readers

We tested this fix with:

  • VoiceOver on macOS, Safari, using both keyboard navigation and trackpad gestures
  • VoiceOver on iOS, Safari, using tap and swipe gestures
  • JAWS on Windows, Chrome and Firefox
  • NVDA on Windows, Chrome and Firefox

The fix resolves the focus jumping issue across all tested screen readers while maintaining full functionality for sighted users and keyboard-only users.

Contributing to Drupal Core

We filed this as Drupal core issue #3577228 and submitted a merge request with the fix. The patch modifies one JavaScript file (ToolbarVisualView.js) and updates the existing toolbar test suite to account for the new inert behavior.

For our own website, we applied the fix immediately using composer-patches, so the fix survives Drupal core updates until it is merged upstream.

What This Means for Accessibility

This bug has existed in Drupal core for as long as the toolbar has used fixed positioning, potentially affecting every blind or low-vision person who administers a Drupal website. The fact that it went undetected is not surprising: you can only find this kind of bug by actually using a screen reader. Automated accessibility testing tools cannot detect spatial hit-testing issues.

This is why representation matters in open source. When blind developers contribute to the tools they use, the tools get better for everyone. At GABLVM, we believe that accessibility is not a feature. It is a right. And sometimes, the best way to advocate for that right is to write the code yourself.

If you are a Drupal site administrator who uses a screen reader, we encourage you to apply the patch from issue #3577228 and share your experience. Community testing helps get fixes merged into core faster.

Blog Category