F85: When Dialogs Appear Where Keyboard Users Can't Find Them
Jamie · AI Research Engine
Analytical lens: Strategic Alignment
Small business, Title III, retail/hospitality
AI-assisted · Source-linked · Editorially reviewed · Methodology
Trust note
This article was drafted with AI assistance, reviewed against accessibility.chat editorial standards, and should be treated as research and education rather than legal advice. We prioritize primary sources and correct material errors.

Automated testing catches roughly 37% of accessibility barriers at best — and focus order failures like F85 sit squarely in the 63% that tools miss. That number comes from our research on testing methodology gaps, and it matters here because F85 is almost invisible to scanners. The dialog renders. The button exists. Nothing flags as broken. But for a keyboard user, the interface is effectively a locked door.
WCAG 2.2 Failure F85 (opens in new window) documents a specific, common pattern: a dialog or menu opens on the page, but focus stays wherever it was — usually on the trigger button — while the dialog sits somewhere else in the DOM. The user has no idea the dialog appeared. They press Tab. Nothing happens with the dialog. They press Tab again. And again. Eventually, after cycling through every other focusable element on the page, they land in the dialog — if they're patient enough to get there.
This isn't a theoretical edge case. It's one of the most common interaction failures in modern web applications.
The Failure
F85 (opens in new window) is a documented failure of Success Criterion 2.4.3 Focus Order (opens in new window), which requires that if a web page can be navigated sequentially, the navigation order preserves meaning and operability.
The W3C document describes two distinct failure patterns:
Pattern 1 — Dialog appended to the end of the DOM. A non-native HTML dialog is created and placed at the end of the document structure. JavaScript reveals it visually, but no script moves focus into it. The dialog floats above the page content visually, but in the keyboard navigation order, it's at the very end — after every nav link, every form field, every footer element. The user must Tab through the entire page to reach it.
Pattern 2 — Menu dismissed, focus dropped. When a user closes an embedded menu, focus is set to document instead of returning to the trigger control. The user is effectively teleported to the beginning of the Tab sequence and must navigate forward again to resume where they left off.
Both patterns share the same root problem: the sequential navigation order doesn't reflect the visual and logical structure of the interface.
Why This Matters
For a compliance officer reading a DOJ settlement or a developer reviewing a pull request, the abstract description of F85 can feel distant. Walk through it as a keyboard user would.
You're filling out a form. You press a button labeled "Add address." A modal dialog appears — visually, right in front of you. But your focus is still on the button. You press Tab. Focus moves to the next element after the button in the DOM — a sidebar link, maybe, or a footer item. The dialog is nowhere in your Tab sequence yet. You have no idea if it opened. You might press Escape, thinking nothing happened. You might keep tabbing, confused. If you use a screen reader, you may hear the dialog announced — but you still can't interact with it without tabbing all the way around the page.
For users who rely on keyboard navigation — people with motor disabilities, users of switch access devices, screen reader users — this isn't an inconvenience. It's a functional barrier. The task cannot be completed efficiently, and in many cases, cannot be completed at all without knowing to use a workaround that the interface never communicates.
The cognitive load compounds the problem. Users with cognitive disabilities who are already managing a complex task now face an interface that behaves differently from what they see.
The Fix
The problematic pattern looks like this — a dialog revealed by toggling a CSS class, with no focus management:
// Failure pattern: reveals dialog visually, ignores focusfunction openDialog() { const dialog = document.getElementById('signup-dialog'); dialog.classList.remove('hidden'); // Focus stays on the trigger button — never moves to dialog}The corrected pattern moves focus to the dialog or a logical first focusable element within it immediately on open, and returns focus to the trigger on close:
// Correct pattern: manages focus on open and closefunction openDialog() { const dialog = document.getElementById('signup-dialog'); const trigger = document.activeElement; // capture trigger before moving focus dialog.classList.remove('hidden'); dialog.setAttribute('aria-modal', 'true'); // Move focus to dialog container or first focusable child const firstFocusable = dialog.querySelector( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); if (firstFocusable) { firstFocusable.focus(); } else { dialog.setAttribute('tabindex', '-1'); dialog.focus(); } // On close, return focus to trigger dialog.addEventListener('close', () => { dialog.classList.add('hidden'); trigger.focus(); }, { once: true });}The W3C document also addresses a nuanced edge case worth noting: sometimes returning focus to the original trigger isn't logical. If a user deletes an item from a list and the trigger no longer exists, focus should move to the next logical element — the next item in the list, or the list container. That's not a failure of 2.4.3. The standard requires logical focus order, not mechanical return-to-origin.
For native HTML <dialog> elements, the browser handles much of this automatically. The showModal() method moves focus into the dialog, and closing it returns focus to the trigger. Using the platform where possible is the most robust approach.
<!-- Native dialog: browser manages focus on showModal() / close() --><dialog id="confirm-dialog"> <h2>Confirm deletion</h2> <button id="confirm-btn">Delete</button> <button id="cancel-btn">Cancel</button></dialog><script> const dialog = document.getElementById('confirm-dialog'); const trigger = document.getElementById('open-btn'); trigger.addEventListener('click', () => { dialog.showModal(); // focus moves into dialog automatically }); document.getElementById('cancel-btn').addEventListener('click', () => { dialog.close(); // focus returns to trigger automatically });</script>Applying This
For a developer reviewing a pull request, the question to ask is simple: when this element opens, where does focus go? If the answer is "nowhere new," that's F85.
Three practical catches for your workflow:
In code review: Search for any function that shows, reveals, or toggles a dialog or menu. If it doesn't contain a .focus() call or use showModal(), flag it. This is a one-line check that catches the majority of F85 failures before they ship.
In manual testing: Tab-only navigation through any interactive flow that involves dialogs or menus. If you open a dialog and your next Tab keypress doesn't land inside it, the focus order is broken. This takes minutes and catches what automated tools cannot — as our research on hybrid testing approaches makes clear, this class of failure requires human judgment.
In design review: If a designer specifies a dialog or flyout panel, ask where focus goes when it opens and where it returns when it closes. Building focus management into the design spec — not retrofitting it into code — is where the real efficiency gain lives.
The ARIA Authoring Practices Guide dialog pattern (opens in new window) provides a complete reference implementation for teams building custom dialog components. It covers focus trapping, Escape key handling, and return focus — the full interaction model, not just the open/close moment.
CORS Perspective
From a strategic alignment lens, F85 is a high-leverage fix with a low implementation cost — a .focus() call and a stored trigger reference. The risk profile is real: focus order failures in high-use flows (checkout dialogs, account modals, form confirmations) are exactly the kind of barrier that generates complaints and, in Title III contexts, litigation exposure. But the more important frame is operational: because automated tools miss this class of failure, organizations that rely solely on scanning tools will ship F85 repeatedly across their codebase. The fix isn't just patching individual dialogs — it's establishing a code review practice and a manual testing protocol that makes focus management a first-class concern, not an afterthought. That's the difference between resolving a finding and building the capacity to prevent it.
About the Jamie lens
A strategy lens for small business and Title III. Frames findings around cost, sequencing, and what a retail or hospitality operator can realistically act on first.
Jamie is an AI analyst lens, not a human staff member. It helps frame this article through a consistent accessibility perspective.
Specialization: Small business, Title III, retail/hospitality
View all articles using this lens →Primary source reviewed: https://www.w3.org/WAI/WCAG22/Techniques/failures/F85 (opens in new window)
Transparency Disclosure
This article was drafted with AI assistance and reviewed against our editorial methodology. We disclose that process so readers can judge the work clearly.