Example 1: same page links

Clicking the above "Example 1: in-page links" link shifted focus to this section. This is built-in functionality in modern browsers accomplished using an anchor tag with an href that points at a section's id.

<a href="#section-1">
  jump to section 1
<a>
<section id="section-1" tabindex="-1">
</section>
Look ma, no javascript! Example 2: element removed

Example 2: element removed

When a focused element is removed from the page, focus is brought to the body element which starts the user back at the top of the page. This can can cause confusing and annoying experiences for keyboard-only users.

For dynamic applications that allow users to delete items from the page, focus needs to be retained to avoid this.

There are usually many "right" answers. It depends on the context.

nextRow.focus()
nextDelete.focus()
nextInput.focus()
emptyMsg.focus()
Example 3: element added

Example 3: element added

When a new element is added to the page based on user-interaction, focus should be brought to the new element.

Similar to the above removal examples, where focus should go specifically depends on what the user is performing...

newItem.focus()
Example 4: modal dialog

Example 4: modal dialog

Modal dialogs require quite a few considerations when it comes to focus...

  • Shift focus to modal when trigger is clicked
    modal.focus()
  • Trap focus within modal
    modal.addEventListener('keydown')
  • When closed, return focus to the trigger which launched it
    trigger.focus()
Example 5: SPA navigation

Example 5: single page app (SPA) navigation

Many modern web applications are single page applications or "SPAs".

SPAs are applications which do not trigger a full page load when navigating from one page to another.

Focus should be brought somewhere logical when a new page in the app is loaded.

          h1.focus()
        
Go to new page Example 6: loading state

Example 6: loading state

You might've caught this in the previous example... For asynchronous transitions from one state to another, the loading state needs to be exposed to screen reader users. One way of doing so, is to bring focus to the loading text and returning it somewhere logical once loading is complete.

loader.focus()

Example 7: notifications

Example 7: notifications

Similar to loading states, notifications need to be exposed to screen reader users. In certain cases, these notifications should receive focus to ensure this information is announced. In other cases, like when a user is in the middle of performing a task, focus should not be stolen and instead role="alert" should be used which triggers a live region announcement to the user without having to shift focus anywhere.

notification.focus()

Back to top