Focus Management in JavaScript: Mastering the User Experience, One Tab at a Time

Focus management is a vital aspect of accessibility, especially for keyboard and assistive technology users. This section will delve deep into controlling tab order, preserving context, and crafting seamless interactive experiences.

ShareShare

Focus Management in JavaScript: Mastering the User Experience, One Tab at a Time

In a world where user interfaces are increasingly dynamic and complex, focus management is a key aspect of accessibility. It's central to how users, particularly those using keyboard navigation or assistive technologies, interact with your application.

Without proper focus management, applications can inadvertently create user experience issues such as:

  • Baffling keyboard users due to unexpected focus shifts
  • Trapping screen reader users in navigational dead ends
  • Interrupting smooth form flows
  • Generating inaccessible modals, menus, and widgets

This article will provide an in-depth understanding of:

  • The concept of focus and its behavior in HTML
  • The importance of tab order and focus indicators
  • Strategies for focus management in Single Page Applications (SPAs) and React
  • Creating focus traps and restoring focus context
  • Testing strategies and common pitfalls in focus management

The Concept of Focus in HTML

In the realm of HTML, focus refers to the specific element currently ready to receive keyboard input. At any given time, only one element can be in focus.

Focusable elements typically include:

  • Form controls such as <input>, <textarea>, <button>
  • Anchor tags with an href attribute (<a href>)
  • Elements with a tabindex attribute set to "0" ([tabindex="0"])
  • Elements made programmatically focusable via the element.focus() method

Navigating with Tab Order

The tab order is a fundamental concept in keyboard navigation. Users can cycle forward through focusable elements by pressing the Tab key, and backwards using Shift + Tab.

The tab order is primarily determined by two factors:

  1. Source order: Elements are focused from top to bottom as they appear in the HTML source code.
  2. tabindex attribute: A tabindex of "0" implies the element follows the natural order, a positive value (>0) sets a custom order overriding the source order, and a value of "-1" makes the element programmatically focusable only.

As a best practice, avoid using a tabindex greater than "0" as it disrupts the natural flow of the document and breaks user expectations.


Focus Indicators: Guiding the User's Attention

Most browsers provide default focus rings (a blue outline on Chrome, dotted line in Firefox) that indicate the currently focused element.

Removing these indicators can lead to a confusing user experience:

button:focus {
  outline: none; /* ❌ This is a bad practice */
}

Instead, you should customize them to suit the design aesthetics of your application:

button:focus-visible {
  outline: 2px solid #00f; /* A customized focus indicator */
}

The :focus-visible pseudo-class is a powerful tool that allows you to only show focus outlines when the user is navigating via keyboard, not mouse clicks.


Managing Focus in Single Page Applications

In Single Page Applications (SPAs), including those built with React, managing focus becomes a critical task. When the route changes or a modal opens, it's imperative to manually shift the focus to the appropriate element:

useEffect(() => {
  document.getElementById("page-title").focus();
}, [location.pathname]);

You should also allow focus on your main content regions by setting role="region" and tabindex="-1":

<main id="main" tabindex="-1">...</main>

Crafting Focus Traps

In dialogs or modals, it's crucial to confine focus within the overlay. This phenomenon, known as a focus trap, prevents the user's focus from accidentally leaving the modal and getting lost in the rest of the page.

There are several libraries available to help implement focus traps:

  • focus-trap (npm)
  • react-focus-lock
  • @reach/dialog

Here's a basic example of how to manually create a focus trap:

const handleKeyDown = (e) => {
  if (e.key === "Tab") {
    // Check if focus is leaving modal bounds
    // Cycle back to first/last element
  }
};

Restoring Focus Context

It's important to remember where the user's focus was before opening a modal or overlay. This practice, known as restoring focus, helps to maintain a consistent user experience:

const previouslyFocused = document.activeElement;

openModal();

modalClose(() => {
  previouslyFocused.focus();
});

This strategy preserves the user's context, a critical UX practice for keyboard users.


Implementing Skip Links

Skip links provide a shortcut for users to skip over repetitive content and navigate directly to the main content. They're particularly useful for users relying on keyboard navigation:

<a href="#main-content" class="skip-link">Skip to main content</a>

To ensure a seamless experience, make skip links visible only when focused:

.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: 0;
}

Learning from Real-World Examples

Highly accessible websites such as GOV.UK and GitHub can provide valuable insights into effective focus management strategies:

GOV.UK

  • Focus is explicitly managed on every route change
  • Provides prominent skip links and heading focus management

GitHub

  • When dropdowns or modals are closed, the focus is returned to the previous control
  • Employs aria-activedescendant for combobox navigation

Anti-Patterns to Avoid

Some common pitfalls in focus management include:

  • Removing focus outlines without providing an alternative
  • Opening modals without shifting the focus to them
  • Failing to return focus to the original context after closing overlays
  • Setting tabindex="0" indiscriminately
  • Making hidden elements focusable

Testing Focus Management

To ensure your focus management is effective, it's crucial to:

  • Navigate your application using only the keyboard
  • Use accessibility testing tools such as Axe DevTools or Lighthouse
  • Verify that the visual focus indicator is clear and noticeable
  • Test screen reader navigation with tools such as NVDA or VoiceOver

Conclusion: Accessibility Begins with Focus

If users can't focus on an element, they can't interact with it. In essence, focus isn't merely a state—it's a conversation between your interface and your users. Therefore, it's vital to guide that conversation gently, ensuring clarity and predictability to keep users grounded.

Remember, accessible applications don't just work—they stay in focus.

Subscribe for Deep Dives

Get exclusive in-depth technical articles and insights directly to your inbox.

about

Ehsan Hosseini

Ehsan Hosseini

me [at] ehosseini [dot] info

Staff Software Engineer and Tech Lead with a track record of leading high-performing engineering teams and delivering scalable, end-to-end technology solutions. With experience across web, mobile, and backend systems, I help companies make smart architectural decisions, scale efficiently, and align technical strategy with business goals.

© 2025 Ehsan Hosseini. All rights reserved.