focus-trap demo
In the demos below, you'll be able to tell that a focus trap is active because it will turn pink. You should also be able to tell because it will trap your focus!
When a trap is active, you can deactivate it by pushing its deactivate button or, if the demo allows, pressing the Escape key.
animated dialog
This focus trap will fade in when activated and fade out when deactivated. Once the trap has been activated
(i.e. onPostActivate
), a "trap activated" message appears next to the Activate button.
Note that the fade animation needs to be written yourself, it is not built into the library.
Trap activated
animated trigger
The activation button for this focus trap will fade out when the trap activates and fade in when the trap deactivates.
If the returnFocus
option is true
, the activation button will receive focus after the trap deactivates.
If the returnFocus
option is false
, the Deactivate button will retain focus after deactivation because that is the last element that was clicked prior to deactivation.
Once the trap has been deactivated (i.e. onPostDeactivate
), a "trap deactivated" message appears next to the "returnFocus" option.
Note that the fade animation needs to be written yourself, it is not built into the library.
Trap deactivated
configurable escape behavior
This focus trap leverages the escapeDeactivates
option as a function
rather than a boolean. By default, pressing ESC will deactivate the trap, but while the trap
is active, you can check or uncheck the option, and the ESC key will behave accordingly.
Since the escapeDeactivates
option received the related KeyboardEvent
,
it could be used to programmatically decide if the ESC key should allow the trap to be
deactivated, perhaps based on the node that's currently focused, or some other condition.
initial element, no escape
If initialFocus
is a selector or DOM node, focus will jump to that specified element when the trap activates.
If initialFocus
is false
(or a function that returns false
), no element will be given focus when the trap activates.
initialFocus
is set to the first tabbable element by default.
Also, in this demo the Escape key does not deactivate the focus trap. You must click the button.
initially focused container
When this focus trap activates, initial focus is on the containing element (which has tabindex="-1"
and is therefore not tabbable).
When you tab through the trap, focus does not return to the containing element.
Also, clicking on an outside element automatically deactivates this trap.
hidden treasures
Focusable nodes are initially hidden and then revealed within the trap.
Use Escape to exit.
sibling traps
Sibling focus traps. When the second trap is deactivated, focus returns to the first trap.
tricky initial focus
In this focus trap, the single focusable button is hidden (the ones you see at first have tabindex="-1"
).
If you activate the trap in this state, the fallbackFocus
option is used to focus the container.
If, however, you first make the focusable button visible by clicking "show focusable button", that button will receive focus when you activate the trap.
input activation
Any change to the input content triggers automatic activation of the focus trap, without changing selection within the input.
delay
focus-trap ensure that the placement of focus within the trap is slightly delayed, so the focused element does not capture the event that originated the activation of the focus trap. For example, the same Enter keystroke won't open and close this trap.
No delay
focus-trap ensure that the placement of focus within the trap is not delayed, so the focused element captures the event that originated the activation of the focus trap.
radio group
A default focus trap that contains a radio group. You should be able to change the radio group with the arrow keys, but Tab should only focus the active radio. (Notice that you need a checked radio in the group for things to work as expected.)
iframe
This focus trap contains an iframe. You should be able to tab into and out of the iframe. But you need to have a focusable element before and after the iframe for things to work as expected.
working inside an iframe
This focus trap can be executed inside an iframe. You should be able to trap the focus inside. You need to have provided the iframe document to the focus-trap before for things to work as expected.
⚠️ As it executes inside the iframe, it cannot prevent clicks on links in the parent document. This is the same drawback as you might experience when putting a focus-trap inside a Shadow DOM.
inside an open shadow dom
This focus trap is instantiated inside an open Shadow DOM. Some users of this library use Web Components to create things like modal dialogs, which means focus needs to be trapped inside the Shadow DOM instance.
When the mouse is clicked on an element inside an open Shadow DOM,
the target node in event.target
is always the shadow host (the node to
which the shadow is attached). Fortunately, event.composedPath()
, a
modern API on the event object, allows focus-trap to determine the actual node that
was clicked inside the shadow.
⚠️ focus-trap is unable to work with closed Shadow DOMs because
event.composedPath()
can't see inside it. In this case, both this
modern API and event.target
point to the shadow host as the actual
element that was clicked, and focus-trap will always determine that the click was
outside the trap (and either prevent it, or always deactivate the trap when the
clickOutsideDeactivates
option is true).
⚠️ See the warning about selector string options when putting a focus trap inside an open Shadow DOM.
with shadow dom
This focus trap contains tabbable elements that are inside
open and closed Shadow DOMs. It configures tabbable
to look for Shadow DOM
elements and provides a reference to the closed Shadow when requested.
allowOutsideClick option
This focus trap can be closed also by clicking a button outside of the trap that is able to control the trap (which is the "activate trap" button in this example). ESC is disabled for this trap.
NOTE: This is different from the clickOutsideDeactivates where merely clicking outside the trap would cause it to be deactivated. In this example, the outside click must take place on the "activate/deactivate trap" button, whose click event handler will programmatically deactivate the trap.
clickOutsideDeactivates option
This focus trap can be closed simply by clicking anywhere outside, and the click outside will also go through and do what it was intentionally dispatched to do (like toggling the checkbox). ESC is disabled for this trap.
The returnFocusOnDeactivate
option controls whether focus should be returned to the last-focused element when the trap was activated (the "activate trap" button) or not -- IIF what you click on outside the trap is not focusable:
- If this option is
true
(the default behavior) but you click on a focusable node outside the trap (like the checkbox), the click will go through, the checkbox will be toggled, and focus will remain on the checkbox. - If
true
but you click on something not focusable (like the page/document), then focus will return to the "activate trap" button (since that was the last-focused node before the trap was activate). - If
false
, then it doesn't matter what you click on (focusable or not), focus will go away from the trap to where you clicked, or to nowhere if you clicked on something not focusable (like the page/document).
setReturnFocus option
With setReturnFocus it is possible to overwrite the returnFocusElement.
setReturnFocus as function
As the function is executed in the process of deactivation, it allows you to dynamically specify which element should be focused after deactivation.
Once the trap is activated, you can still click on one of the 3 deactivate buttons below in order to deactivate the trap.
multiple elements
You can pass multiple elements, and the focus will be kept within those element boundaries (darker color). Clicking outside deactivates.
multiple elements with delete
Pass multiple elements. Update the tabbable nodes in any of those elements on the fly, ensuring there's always at least one container with at least one tabbable node in it at all times.
multiple elements with delete ALL
Pass multiple elements. With the fallbackFocus option configured to the "deactivate trap" button, remove ALL nodes in all trap containers to have the focus fall back to the "deactivate" button on the next tab key press.
Container 1
Container 2
Not in trap (fallback; clicks allowed)
multiple traps with multiple elements
You can have multiple traps with multiple elements. Each trap's elements are in a darker color when their associated trap is active. Clicking outside on the activate and deactivate trap buttons is allowed.
Negative tabindex
This trap has an element with a negative tabindex in the middle, which means that element is focusable but not tabbable. Use the mouse to set focus to it. Once it has focus, you can still use the tab key to go forward or backward in the normal tab order.
Negative tabindex last
This trap has an element with a negative tabindex and it's the last element, which means that element is focusable but not tabbable. Use the mouse to set focus to it. Once it has focus, you can still use the tab key to go forward or backward in the normal tab order.
With open web component
This trap contains an element which is defined in an open web component (i.e. a web component with an open Shadow DOM).
Global trap stack
Use window to have access to trap stack. This allows to have more than one focus-trap library version in the same page.
Customized keyboard navigation
This trap uses the isKeyForward()
and isKeyBackward()
options to enable the use of the j
(backward) and k
(forward)
keys to navigate the trapped elements using the keyboard.
💬 The tab
key still works, but not completely, as it's no longer managed by
the trap. To make full use of these options, the tab
key should be
suppressed entirely or handled differently. You might use these options in a dropdown
list where you're moving focus between items using the arrow keys while reserving the
tab
key for moving beyond the dropdown itself.