Sentinel Focus — Using Sentinel Elements for Focus Trapping
In this tutorial, you will learn about Sentinel Focus. We cover key concepts, practical examples, and best practices to help you master this topic.
Sentinel focus uses invisible tabbable elements at the start and end of a container to detect when Tab or Shift+Tab would leave the container, then cycles focus back.
In this tutorial, you'll learn the Focus Management sentinel pattern.
What You'll Learn
By the end of this lesson, you'll understand the sentinel focus technique, how it differs from event-based focus trapping, and when to use each approach.
Why It Matters
The sentinel approach is simpler and more reliable in some scenarios, especially when focusable elements are added or removed dynamically.
Real-World Use
Doda Browser uses sentinel focus for complex dialog components where the focusable content is loaded dynamically.
Sentinel Focus Architecture
flowchart LR A[Sentinel Start] --> B[Focusable element] B --> C[Sentinel End] D[Tab on sentinel end] --> E[Move focus to sentinel start] F[Shift+Tab on sentinel start] --> G[Move focus to sentinel end] E --> B G --> C
Implementing Sentinel Focus
<div class="dialog" role="dialog" aria-modal="true">
<!-- Sentinel: catches Shift+Tab leaving the dialog -->
<div tabindex="0" class="focus-sentinel sentinel-start"></div>
<!-- Dialog content -->
<h2>Settings</h2>
<input type="text" placeholder="Name" />
<button>Save</button>
<!-- Sentinel: catches Tab leaving the dialog -->
<div tabindex="0" class="focus-sentinel sentinel-end"></div>
</div>
function setupSentinelFocus(container) {
const sentinelStart = container.querySelector('.sentinel-start');
const sentinelEnd = container.querySelector('.sentinel-end');
sentinelStart.addEventListener('focus', () => {
// Shift+Tab on first real element sent us here
// Move focus to the last real element
const lastFocusable = getLastFocusable(container);
if (lastFocusable) lastFocusable.focus();
});
sentinelEnd.addEventListener('focus', () => {
// Tab on last real element sent us here
// Move focus to the first real element
const firstFocusable = getFirstFocusable(container);
if (firstFocusable) firstFocusable.focus();
});
}
function getFirstFocusable(container) {
return container.querySelector(
'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
);
}
function getLastFocusable(container) {
const all = container.querySelectorAll(
'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
);
return all[all.length - 1];
}
Sentinel vs Event-Based Trapping
| Aspect | Sentinel | Event-based |
|---|---|---|
| Implementation | DOM-based | JavaScript event |
| Dynamic content | Handles automatically | Needs refresh |
| Complexity | Simple | More logic |
| Browser support | Universal | Universal |
| Flexibility | Less flexible | More flexible |
Accessibility of Sentinels
Sentinels should be invisible but not hidden from the accessibility tree:
.focus-sentinel {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
/* Do NOT use display:none or visibility:hidden */
/* Do NOT use aria-hidden="true" */
}
Common Mistakes
- Hiding sentinels with display:none: They become unfocusable.
- Using aria-hidden on sentinels: They are removed from the accessibility tree.
- Not positioning sentinels correctly: They should not disrupt visual layout.
- Sentinels with no real focusable elements: The cycle breaks if no elements exist.
- Multiple sentinels on the same dialog: Only one pair is needed per container.
Practice and Challenge
1. What is a sentinel element? An invisible focusable element placed at the start and end of a container to trap focus.
2. How does sentinel focus differ from event-based trapping? Sentinels use DOM elements to catch Tab events rather than intercepting keydown events.
3. Why should sentinels not use display:none? Because they would not be focusable.
4. When is sentinel focus preferable? When the container's content is dynamic and focusable elements change frequently.
5. Challenge: Implement sentinel focus for a side panel component. Include both sentinel elements and dynamic content.
FAQ
Mini Project
Build a dialog component using sentinel focus trapping. Include dynamic content loading within the dialog and verify the trap works after content updates.
What's Next
Continue to Focus History to learn about remembering and restoring focus position.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro