Keyboard Navigation Between List and Detail Panes

Permalink to "Keyboard Navigation Between List and Detail Panes"

In a split view, the list and the detail are neighbours on screen but far apart in the tab order. A keyboard user in row 3 of a 200-row list who wants to reach the detail’s Save button may have to Tab through the rest of the list’s controls, the toolbar and every field in the detail first. Desktop applications solved this decades ago with F6, which cycles focus between panes. Web apps can do the same, plus named landmarks and skip links for users who navigate by structure.

This guide belongs to master-detail & split views.

Spec reference

Permalink to "Spec reference"
  • SC 2.4.1 Bypass Blocks (A) — a mechanism is needed to bypass repeated blocks. In a split view, the list is a large block between the user and the detail; F6, skip links and landmarks are such mechanisms.
  • SC 1.3.1 Info and Relationships (A) — panes as landmarks (main, complementary, region with names) are programmatic structure.
  • SC 2.4.3 Focus Order (A) — returning to a pane should restore where the user was.
  • SC 2.1.4 Character Key Shortcuts (A) — F6 is not a character key, so it is unaffected.
  • SC 3.3.2 Labels or Instructions (A) — shortcuts should be documented.
F6 cycling across panes Chain: F6 moves focus from the toolbar to the list's last focused row, then to the detail's last focused element, then back to the toolbar; Shift+F6 goes the other way. F6 cycling across panesToolbarfilter field lastusedList panerow 37, as leftDetail paneAmount field, asleftToolbarback to the startF6F6F6
Each pane remembers where the user was.

When to use — and when not to

Permalink to "When to use — and when not to"

Add F6 and named panes to any layout with two or more large, side-by-side interactive areas: list and detail, navigation tree and content, editor and preview. Add skip links when the first pane is long and sits before the second in the DOM.

Do not override F6 in browsers where it already moves focus to the address bar and back, unless focus is inside your application area. Chrome and Firefox use F6 to cycle between browser UI and the page; your handler only runs when the page has focus, which is fine — but do not call preventDefault() when focus is on the last pane, so users can still reach the address bar.

The misapplication: relying only on landmarks. Screen reader users can jump by landmark, but sighted keyboard users cannot; they need F6 or skip links.

Who each mechanism serves Comparison: landmarks serve screen reader users with landmark navigation; F6 and skip links serve sighted keyboard users and screen reader users alike. Who each mechanism serves✗ Landmarks onlyScreen reader users jump with D, R or rotorSighted keyboard users Tab through everythingMagnifier users lose track of where focus wentNothing to document✓ Landmarks plus F6 and skip linksSame, plus F6F6 jumps panes in one pressSkip links are visible on focusKeys documented in help

Annotated code example

Permalink to "Annotated code example"
<a class="skip-link" href="#detail-h">Skip to record details</a>  <!-- visible on focus (SC 2.4.1) -->

<div class="split">
  <section class="pane" data-pane aria-labelledby="list-h">
    <h2 id="list-h">Invoices</h2>
    …list…
  </section>
  <section class="pane" data-pane aria-labelledby="detail-h">      <!-- named region (SC 1.3.1) -->
    <h2 id="detail-h" tabindex="-1">INV-1042 details</h2>
    …detail…
  </section>
</div>
const panes = [...document.querySelectorAll('[data-pane]')];
const lastFocus = new WeakMap();

document.addEventListener('focusin', (e) => {
  const pane = e.target.closest('[data-pane]');
  if (pane) lastFocus.set(pane, e.target);                  // remember per pane (SC 2.4.3)
});

document.addEventListener('keydown', (e) => {
  if (e.key !== 'F6') return;
  const current = document.activeElement.closest('[data-pane]');
  const i = panes.indexOf(current);
  const next = e.shiftKey ? i - 1 : i + 1;
  if (next < 0 || next >= panes.length) return;              // let the browser take F6 to its UI
  e.preventDefault();
  const target = lastFocus.get(panes[next]) ?? panes[next].querySelector('h2');
  target.focus();
});

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"
Key Action Expected announcement AT deviations
F6 from list Focus detail’s last element “Amount, edit, 1,240.00” (with region name on entry in NVDA) JAWS may not announce the region name on focus entry
Shift+F6 from detail Back to list row “INV-1042, row 37” —
F6 from the last pane Browser UI (address bar) Browser-specific Expected
Tab to skip link “Skip to record details, link” — —
D (NVDA) / R (JAWS) Next landmark or region “INV-1042 details, region” Requires accessible names on sections
Mechanisms and the users they reach Matrix of F6, skip links and named landmarks against sighted keyboard users, screen reader users, magnifier users and voice control users. Mechanisms and the users they reachSighted keyboardScreen readerMagnifierVoice controlF6 cyclingYesYesYes"Press F6" worksSkip linksYesYesVisible targetSay the linkNamed landmarksNot reachableYesNot reachableNot reachable
Combine all three; each misses someone on its own.

Integration context

Permalink to "Integration context"

Within the list pane, arrow keys and roving focus apply, as in focus handoff in master-detail layouts. Dashboards with many widgets use a similar idea at larger scale — see keyboard navigation between dashboard widgets. If the panes are resizable, the splitter between them has its own pattern, described in the window splitter pattern for resizable panes.

Gotchas

Permalink to "Gotchas"

F6 on macOS. Mac keyboards often need Fn+F6, and some users have function keys mapped to media controls. Offer a second shortcut (for example Ctrl+Alt+Arrow) and the skip links.

Collapsed panes. If a pane is collapsed or hidden on narrow screens, skip it in the cycle.

Too many landmarks. Making every widget a landmark dilutes landmark navigation. Two or three named panes per view is the useful range.

Framework notes

Permalink to "Framework notes"

In React, put the F6 handler in the layout component and use refs for panes; store last focus in a useRef(new WeakMap()). In Angular, the CDK FocusKeyManager is for items within a widget, not panes — a simple host listener on the layout component is enough. In Vue, a composable usePaneCycling(panesRef) can be shared across split views.

// Vue composable sketch
export function usePaneCycling(panes) {
  onMounted(() => document.addEventListener('keydown', onKey));
  onBeforeUnmount(() => document.removeEventListener('keydown', onKey));
  function onKey(e) { if (e.key === 'F6') cycle(panes.value, e); }
}

Testing checklist

Permalink to "Testing checklist"

Design system notes

Permalink to "Design system notes"

Bake pane cycling into the split-view layout component, with a panes API that registers names and focus targets. Product teams then get F6, skip links and landmark names by using the layout, rather than by remembering to add them.

FAQ

Permalink to "FAQ"
Is F6 a recognised convention on the web?

It is a desktop convention that browsers also use for their own UI. Many web apps — mail clients, IDEs in the browser, office suites — adopt it, and keyboard users often try it.

Do skip links satisfy 2.4.1 on their own?

Yes, a skip link is a sufficient technique. F6 and landmarks are additions that make movement faster.

Should F6 go to the pane's first control or its last focused one?

Last focused, falling back to the heading. Users return to a pane to continue, not to start over.

What about three panes?

F6 cycles through all three in visual order. Name each clearly, and consider Ctrl+1, Ctrl+2, Ctrl+3 to jump directly, documented in help.

Should toolbars count as panes for F6?

A toolbar above the list is a reasonable stop in the cycle, especially if it holds filters users return to often. Global page navigation usually is not; landmarks and skip links already cover it, and including it makes the cycle longer.

How do I tell users that F6 exists?

List it in the keyboard shortcut help dialog, mention it in the description of each pane’s heading region for screen reader users, and show a brief hint the first time a user moves between panes with Tab several times in a row.

Permalink to "Related"

← Back to Master-Detail & Split Views