Search topics
Hold-to-confirm buttons and other timed key presses
A saved list deletes only while Enter is held for 1.5 seconds, or pressed again within 3 seconds, so a single quick press from a switch, speech input or a screen reader does nothing.
setTimeout(deleteList, 1500) The problem
People whose switch, speech input, on-screen keyboard or screen reader sends one quick press can't delete a list, and people who press slowly run out of time.
A shop's account page lists the customer's saved lists, such as Kitchen ideas with 14 items, each with a way to delete it. The designer wanted deleting to take a moment's thought without a dialog in the way, so the button says "Hold to delete": keep it pressed, with the mouse, a finger, Enter or Space, and a fill sweeps across it; let go before 1.5 seconds and it drains away. A second version of the same idea is a plain "Delete list" button that changes to "Press again to delete" after the first press, and changes back after 3 seconds.
Both work with a keyboard, as long as the hands and the keyboard can keep time. A switch user's press, a spoken "press Enter" and a tap on an on-screen keyboard each arrive as one quick press and release: the fill starts and drains in the same moment, and the list stays. Pressing again in time means reaching the button again within 3 seconds, which a switch scan or a spoken command may not manage.
Success criterion 2.1.1 asks for every function to work from a keyboard "without requiring specific timings for individual keystrokes". The Understanding document gives two examples of such timings: keystrokes that have to be repeated or made within a short period of time, and a key that must be held down for an extended period before the keystroke registers. The hold button is the second, and the "press again" button is the first. Both handle the keyboard, and both still fail: the only way to delete is to press in time.
Making the times kinder doesn't change the result. A shorter hold or a longer window is still a timing someone can miss. The way to pass is to remove the clock from the keystroke.
The failure rarely shows up in testing, because the people who build and test the page press keys the way the timer expects. It shows up as a customer who "can't delete anything" and an account full of lists they meant to remove.
4 of 10 groups affected
- No vision (affected)
- Low vision (not affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (affected)
- Reach, strength (affected)
- Cognitive (affected)
- Seizures (not affected)
- Limited manipulation A switch press, a spoken "press Enter" and a tap on an on-screen keyboard each send one quick press and release, so the hold never fills, and a scan or a spoken command can take longer than 3 seconds to reach the button again.
- Limited reach and strength People with tremors or weak hands may not keep a key down for 1.5 seconds without slipping, and those who use Bounce Keys to stop doubled presses have the second press ignored if it comes too soon.
- Without vision In browse mode a screen reader presses a button with a single click, so the hold never fills, and the change to "Press again to delete" may not be read before the 3 seconds are up.
- Limited language, cognitive and learning abilities Nothing says how long to hold or how quickly to press again, and the button changes back by itself, so people who stop to read it are left unsure whether anything happened.
The control is a native button with a visible name, so a scan finds nothing wrong, and a script that presses Enter sees a button that does nothing, which it can't tell apart from a button that is waiting for something else. Pressing a delete button on a live site is not a test an audit can run anyway. The EaseWeb audit reads the words on the page instead: "Hold to", "press and hold", or "press again to" near a control is sent to review. A hold with no words, or a "press again" that appears only after the first press, is found by nothing. AI coding tools will build hold-to-confirm buttons when asked, with keydown and keyup handlers so they work with a keyboard, and may stop there: the timing half of 2.1.1 is the half that is easy to forget.
Try it
Tab to the button under Kitchen ideas and press Enter once, quickly, as a switch or speech input would.
Then try to delete the list at your own pace. The panel under the lists shows how long the key was held, or how long is left to press again.
Broken Can you fix this?
Saved lists
Kitchen ideas
14 items
Guest room
6 items
Last press: none yet
The fix
Let one press open a question that waits, or delete with an Undo that stays.
- 1No action needs a key held down, or pressed again, within a set time.
- 2One quick press of Enter or Space reaches every action, or a confirmation that waits.
- 3After deleting or undoing, focus moves to something still on the page.
A button that deletes only while held
<h2>Saved lists</h2><ul> <li> <h3>Kitchen ideas</h3> <p>14 items</p> <button type="button" id="delete-list" class="hold"> <span class="hold-fill" aria-hidden="true"></span> Hold to delete </button> </li> …</ul>One press opens a question that waits
<h2 id="lists-heading" tabindex="-1">Saved lists</h2><ul> <li id="list-kitchen"> <h3>Kitchen ideas</h3> <p>14 items</p> <button type="button" id="delete-list">Delete list</button> </li> …</ul> <dialog id="confirm-delete" role="alertdialog" aria-labelledby="confirm-title" aria-describedby="confirm-message"> <form method="dialog"> <h2 id="confirm-title">Delete “Kitchen ideas”?</h2> <p id="confirm-message">The list and its 14 saved items will be deleted.</p> <button value="keep" autofocus>Keep list</button> <button value="delete">Delete list</button> </form></dialog>The only way to delete is to keep a key or a pointer down for 1.5 seconds. One quick press starts the timer and stops it again straight away, and a screen reader's click in browse mode is over just as quickly, or never starts it at all.
The moment of thought the hold was for is now a question, and it waits as long as the person needs. One click, tap, Enter or Space opens it, and one more press answers it. Focus starts on Keep list, so a press that repeats keeps the list, and once the list is gone, focus moves to the heading above the lists instead of falling to the page's body. How to make the question itself read out is covered in confirmation dialogs that don't read out their question.
Both pass 2.1.1, and neither asks anyone to keep time. The question costs one more press on every delete, but it needs nothing from the server, and it stops a mistake before it happens: choose it when what is deleted can't come back. Undo keeps deleting to a single press, which suits people who tidy up often and anyone for whom every press is effort, but it only works when the server can restore the list: choose it when deleting is frequent and reversible. Whichever you choose, a press and hold with a mouse or a finger can stay as a quicker way in for people who like it, as long as a click, a tap, Enter and Space do the whole job without it. Let that hold finish when the finger or button is lifted, and cancel when it slides off, as buttons that act on press and can't be cancelled explains.
Use a native button for the control, so Enter and Space work without a key handler of your own, and give it its own focus ring: the fill that sweeps across a hold button is not a focus indicator. A control built from a div fails 2.1.1 in a different way, covered in div buttons that can't be reached with Tab, and a missing ring in missing focus indicators on custom buttons.
Don't fix the Before by changing its numbers. A 0.5 second hold still has to be held, and a 10 second window still closes. Count every timer that starts on keydown, pointerdown or a first click, and make sure none of them stands between a person and an action.
The same failure comes in other shapes than delete buttons, and each has a single-press way.
- Hold to record a voice message: press once to start and once to stop, with a Stop button that shows the time recorded.
- Hold Space to talk in a call: a Mute button that toggles, with the held Space kept as an extra for people who like it. A Space that acts anywhere on the page, not only on a focused control, gets in the way of speech input and typing the same way single-key shortcuts that can't be turned off do, so let people turn it off too.
- Hold an eye icon or Shift to show a password: a Show password button that stays on until it is pressed again, with
aria-pressedsaying which state it is in. - Press Escape twice to close an editor: one Escape closes it, and if unsaved work would be lost, a question that waits asks first.
Key combinations are not timed presses. Ctrl + K is pressed as one chord, and Sticky Keys lets people press it one key at a time; nothing is held for a set time. Session time-outs and other limits on a whole task are a different criterion, 2.2.1 Timing Adjustable, not this one.
Fixing this with an AI coding assistant? Get this guide as Markdown, or get every guide in your coding agent.
Verify the fix
5 checks, no mouse.
Test with: Keyboard, Speech input, Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after changing the shared button or list component.
Limits
This is a starting pattern, not a guarantee for every application. The snippets leave out the server calls and restoring a list to its place among several. A press and hold made with a mouse or a finger, and long presses that open menus, are covered from the pointer's side in right-click, long-press and swipe actions with no button. Test the complete journey with a keyboard, a switch, speech input and 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.