Search topics
Search panels that close on Tab and drop keyboard focus
The search panel closes as soon as its field loses focus, ignores Escape, and hides the control that had focus.
The problem
Keyboard users cannot reach the search results, cannot close the panel with Escape, and lose their place when it closes.
A shop's header has a Search button. Activate it and a panel opens below with a search field, a short list of results and a Close button. Type "lamp" and press Tab to reach the first result: the panel disappears, and focus with it. Open it again and press Escape: nothing happens. The next Tab starts from somewhere the user didn't choose.
A blur handler on the field closes the panel whenever the field loses focus, including when focus moves to a result inside the same panel. The result is hidden while it has focus, so the browser drops focus to the page. The results can't be reached by keyboard (2.1.1), focus jumps out of the sequence the user was following (2.4.3), and the Search button never says whether its panel is open (4.1.2).
Keyboard users, screen reader users and switch users can type a query but can't pick a result. When the panel closes, they have to find their place again from the top of the page. Mouse users click a result before the field loses focus, so the bug can go unnoticed for a long time.
The markup is a named button, a labelled field and ordinary links, so a static scan finds nothing to report. The failure only appears when focus moves after the panel is open. Closing on blur is a common suggestion for "close the dropdown when the user clicks away", and AI coding tools reproduce it without checking where focus is going.
Try it
Open Search, type, then press Tab to reach a result.
Can you reach both lamps and the close button? Try Escape too, and watch where focus ends up.
Broken Can you fix this?
Focus: –
A recreated demo. The broken version is intentionally inaccessible.
The fix
Close the panel only when the user asks or has left the whole component, and put focus back on its button when they ask.
- 1Moving focus inside the panel never closes it.
- 2Escape and a named close button close it and return focus to its button.
- 3The opening button says whether the panel is open.
<button type="button" id="search-trigger">Search</button><div id="search-panel" hidden> <label for="search-input">Search products</label> <input id="search-input" type="search"> <ul> <li><a href="/lamps/arc">Arc floor lamp</a></li> <li><a href="/lamps/dome">Dome table lamp</a></li> </ul> <button type="button" id="search-close">Close</button></div><button type="button">Cart</button>Tab from the field closes the panel before the result can be used, and the close button can't be reached at all. Nothing handles Escape, nothing returns focus, and the button has no expanded state.
The panel follows the button in the markup, so Tab goes from the button to the field, the results, the close button and then Cart. Moving focus inside the component keeps the panel open. Escape and Close search both close it and put focus back on Search, which now says whether its panel is open. Tab or Shift + Tab out of the component closes it without moving focus anywhere else. tabindex="-1" on the panel lets a click on its blank space keep focus inside, so that click doesn't close it.
Both pass. The scripted disclosure works in every browser, keeps the panel in the page's own layout, and can close when focus leaves the component, but every piece of it is your code to maintain. The popover needs no script and gets Escape, the expanded state and focus return from the browser. It sits in the top layer, so you position it yourself (with CSS anchor positioning or a few lines of script), and it stays open when the user tabs away. Choose the popover when the browsers you support all have it and an open panel left behind is acceptable. Choose the disclosure when the panel must close on focus-out or lives inside a layout the top layer would break.
Closing on focus-out is a design choice, not a requirement. A panel that stays open after the user tabs away is not a keyboard trap, because focus did leave. What fails is closing while focus is still inside, or pulling focus back in after it has left. If you close on focus-out, check relatedTarget against the whole component, never just the field.
Return focus to the button only when the user closes the panel on purpose, with Escape or the close button. When they Tab away or click elsewhere, leave focus where they put it. In browsers that clear a type="search" field on Escape, you may let a first Escape clear the text and a second close the panel; test both presses.
This is a non-modal panel. Don't add a focus trap, aria-modal or an inert page; those belong to the modal-focus-management guide. If focus stays in the field while the arrow keys move through suggestions, the component is a combobox and follows that pattern instead, with aria-activedescendant and announced results. Name the close control in words, or see icon-buttons for an icon-only ×.
Verify the fix
5 checks, no mouse.
Test with: Keyboard, Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the shared header or search component changes.
Limits
This is a starting pattern for a non-modal search panel, not for comboboxes, menus or dialogs. The snippets omit fetching and announcing results. Test the complete journey, including your real results list, with your target assistive technology.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.