Focus When Dialog Closes — Returning Focus After Dialog Dismissal
In this tutorial, you will learn about Focus When Dialog Closes. We cover key concepts, practical examples, and best practices to help you master this topic.
When a dialog closes, focus must return to the element that triggered the dialog, maintaining the user's context and preventing disorientation.
In this tutorial, you'll learn Focus Management for dialog dismissal.
What You'll Learn
By the end of this lesson, you'll understand the importance of focus restoration, how to store and restore the trigger element, and how to handle edge cases.
Why It Matters
Without focus restoration, users are left at the top of the page or at an unexpected location after dismissing a dialog, requiring them to navigate back to their previous position.
Real-World Use
Doda Browser's settings dialog stores the trigger element reference on open and restores focus when the dialog closes.
Focus Restoration Flow
flowchart LR A[User clicks trigger] --> B[Store trigger reference] B --> C[Open dialog] C --> D[User dismisses dialog] D --> E[Restore focus to trigger] E --> F[User continues from original position]
Implementing Focus Restoration
class DialogManager {
constructor() {
this.lastTrigger = null;
}
open(dialog, trigger) {
this.lastTrigger = trigger;
dialog.hidden = false;
const focusable = dialog.querySelector(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
(focusable || dialog).focus();
}
close(dialog) {
dialog.hidden = true;
if (this.lastTrigger && document.contains(this.lastTrigger)) {
this.lastTrigger.focus();
}
this.lastTrigger = null;
}
}
const dialogManager = new DialogManager();
Handling Multiple Dialogs
class DialogStack {
constructor() {
this.stack = [];
}
open(dialog, trigger) {
this.stack.push({ dialog, trigger });
dialog.hidden = false;
// Focus first element
}
close(dialog) {
const entry = this.stack.pop();
dialog.hidden = true;
if (entry && entry.trigger && document.contains(entry.trigger)) {
entry.trigger.focus();
}
}
}
Deletion Scenarios
When the trigger element no longer exists (e.g., it was removed during dialog interaction), find a reasonable alternative:
function closeDialog(dialog, trigger) {
dialog.hidden = true;
if (document.contains(trigger)) {
trigger.focus();
} else {
// Fallback: focus the first element in the previous section
document.querySelector('main h1').focus();
}
}
Common Mistakes
- Not restoring focus: User is left at the top of the page.
- Restoring focus to the wrong element: The trigger reference was overwritten by another dialog.
- Not checking if the trigger still exists: The trigger may have been removed or disabled.
- Restoring focus to a hidden element: The trigger may have been hidden during the dialog.
- Not handling nested dialogs: Each dialog must restore focus to its own trigger.
Practice and Challenge
1. Where should focus go when a dialog closes? Back to the element that triggered the dialog.
2. Why store the trigger element on open? Because the user may interact with other elements while the dialog is open.
3. What if the trigger element no longer exists? Focus a reasonable alternative, like the main heading.
4. How do you handle nested dialogs? Use a stack to store trigger references for each level.
5. Challenge: Implement a dialog with nested confirmations. Ensure each level restores focus to its correct trigger.
FAQ
Mini Project
Build a dialog system with full focus restoration. Handle: single dialog, nested dialogs, trigger removal, and fallback focus.
What's Next
Continue to Focus Trap Implementation to learn about building a robust focus trap.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro