Skip to content

Focus Management

Page Focus is an important part of keyboard-only and screen reader navigation.

Make sure you handle or your setup like a SPA Router is setting the focus properly on page or context changes. Consider of using Reach Router because of the build-in accessibility feature.

From the technical side, we have to assign an invisible focus, so the user can continue the navigation inside this new content.

Example setup:

<body>
<nav><!-- focusable navigation --></nav>
<main>
<!-- more markup with focusable HTMLElements -->
<h1 class="dnb-h--xx-large dnb-no-focus" tabindex="-1">Main Title</h1>
<a href="/path">I'm now focusable on next tab</a>
</main>
</body>

Managing the Focus state

Make sure you ...

  • set the focus on the content (e.g. <h1 class="dnb-h--xx-large">) after a navigation action, initiated by the user.
  • set the focus into a menu or navigation area, if it has an opening mechanism.
  • also set the focus back to the content, once the menu or navigation area gets closed.

A more complex focus management is build in already to the Modal Component. There we actually also disable focus possibility on the content behind, so the user only can navigate inside the modal.

Helper tool

The @dnb/eufemia has a build-in helper, to manage basic focus handling. This helper also handles both the tabindex="-1" and the class="dnb-no-focus" situation. So what does it do?

  1. You define on beforehand what should get focus with a css selector (class or id). This (setPageFocusElement) can be set on the very first application start.
  2. Later one, once the focus should be set, you call a second function applyPageFocus. This function will use the beforehand defined selector and execute domNode.focus().

Focus helper

Set focus on a HTML Element, that exists inside the DOM. It can be any HTML Element, no matter if it's an interactive element or not. No interactive elements will be handled by changing the tabindex to 0 alongside a CSS class dnb-no-focus, so no blue focus border is visible.

Simple example:

import { applyPageFocus } from '@dnb/eufemia/shared/helpers'
applyPageFocus('.my-selector')
applyPageFocus('#my-id')

Asynchronous example:

import {
setPageFocusElement,
applyPageFocus,
} from '@dnb/eufemia/shared/helpers'
// 1. Somewhere in your app, set either an element, or a CSS Selector
setPageFocusElement('.css-selector', 'MyCustomName')
// 2. Later you can call this action, once it's time to activate the new focus state
applyPageFocus('MyCustomName', (element) => {
/* optional callback */
})

Skip Link

The @dnb/eufemia also has a small setup for a skip link

Our solution is CSS only and should work for all kinds of application setups. Demo example below:

  1. Place an Anchor with a HTML class .dnb-skip-link like blow, as the very first HTML element tag:
<a class="dnb-skip-link" href="#content-id">Skip to content</a>
  1. Define an unique element id, like id="content-id", on your content wrapper:
<body>
<a class="dnb-skip-link" href="#content-id">Skip to content</a>
<header>
<nav>
<!-- Nav links or content to skip -->
</nav>
</header>
<main id="content-id">
<!-- Content goes here -->
</main>
</body>

That's it. The styles are included in both the dnb-ui-basis and dnb-ui-core styling packages.

NP: If you link the anchor to only a <div id="content-id">, then you have to make sure you also add a tabindex.

...
<div id="content-id" tabindex="-1" class="dnb-no-focus">
<!-- Content goes here -->
</div>
...