F98: Touch Detection That Locks Out Keyboard Users
Keisha · AI Research Engine
Analytical lens: Community Input
Community engagement, healthcare, grassroots
AI-assisted · Source-linked · Editorially reviewed · Methodology
Trust note
This article was drafted with AI assistance, reviewed against accessibility.chat editorial standards, and should be treated as research and education rather than legal advice. We prioritize primary sources and correct material errors.

A touchscreen is detected. Instantly, the site switches to touch-only event listeners — and every keyboard and switch device user on that device loses access. This is WCAG 2.2 Failure F98 (opens in new window), and it's a pattern that survives in codebases precisely because it looks like progressive enhancement. It isn't.
The Failure
F98 describes a specific anti-pattern: web content that detects a touchscreen, then exclusively wires up touch-based event listeners — discarding keyboard and mouse interactions entirely. The W3C documents two common detection methods that trigger this failure.
The first uses the Touch Events API:
// Failure pattern — Touch Events API detectionif (window.TouchEvent || ('ontouchstart' in window)) { // Only touch listeners registered target.addEventListener('touchend', ...);} else { // Mouse/keyboard listeners only reach non-touch devices target.addEventListener('click', ...);}The second uses CSS Media Queries Level 4 interaction features:
// Failure pattern — pointer:coarse detectionif (window.matchMedia && window.matchMedia("(pointer:coarse)").matches) { // Only touch listeners registered target.addEventListener('touchend', ...);} else { target.addEventListener('click', ...);}Both patterns share the same structural problem: they treat input modality as binary and fixed. Touch detected? Touch only. No touch? Mouse and keyboard only. The reality of modern device usage is far more complex — and this failure document exists because that complexity has real human consequences.
The violated success criterion is 2.5.6 Concurrent Input Mechanisms (opens in new window), which requires that web content not restrict use of input modalities available on a platform. Detecting a touchscreen doesn't mean the user will use touch, or that touch is their only available mechanism.
Why This Matters
The device landscape has shifted significantly. Tablets with external keyboards. Laptops with touchscreens. Hybrid devices where users switch between stylus, keyboard, and touch mid-session. A wheelchair user might have a touchscreen tablet mounted to their chair — and use a Bluetooth keyboard or switch access device as their primary input. A user with motor disabilities may prefer a mouse even on a touchscreen device because fine motor control makes touch targets unreliable.
When F98 is present, these users encounter a wall. The touchend event never fires from their keyboard. The click event never fires because the branch that registers it was never reached. Interactive controls — links, form inputs, custom widgets — simply stop responding.
This isn't a minor inconvenience. For a user who depends on a switch device to navigate, an unresponsive button isn't a usability friction point. It's a hard stop. The content is inaccessible, full stop.
The historical context matters here: this pattern emerged from a legitimate problem. Early mobile browsers added a ~300ms delay between a tap and the click event firing, making touch interactions feel sluggish. Developers worked around this by listening to touchend directly. That problem has been resolved in modern browsers (opens in new window), but the workaround pattern persisted in codebases, sometimes for years, long after the underlying problem disappeared. Technical debt with accessibility consequences.
Our research on automated vs. manual testing methodologies is directly relevant here: F98 is exactly the kind of failure that automated scanners routinely miss. A tool can't easily determine whether a touchend listener is the only registered listener, or whether it's supplementing a click handler. This requires code review and manual testing across input modalities.
The Fix
The correction is straightforward in principle: register event listeners for all input modalities, regardless of what's detected. The click event is the right foundation — it fires for mouse clicks, keyboard Enter/Space activation, and touch taps. Layer touch-specific listeners on top of that baseline, not instead of it.
// Correct pattern — register click for all devicestarget.addEventListener('click', handleInteraction);// Optionally add touch-specific handling for enhanced experience// without removing the universal click listenerif (window.TouchEvent || ('ontouchstart' in window)) { target.addEventListener('touchstart', handleTouchStart);}For keyboard accessibility specifically, ensure that any custom widget also handles keydown events for Enter and Space where appropriate — click alone doesn't cover all keyboard interaction patterns for complex widgets.
The WCAG Understanding document for 2.5.6 (opens in new window) is explicit: the intent is that users can switch between input mechanisms at any time, and content should not make assumptions about which mechanism a user will use based on device detection.
For teams using frameworks, check whether third-party component libraries are making these assumptions internally. A custom carousel or date picker built with touch-only gesture detection can introduce F98 even when your own code is clean.
Applying This
Catching F98 requires a deliberate multi-input testing protocol. Automated tools will not reliably surface this. Here's what a practical review process looks like:
| Testing Method | What It Catches | Limitation |
|---|---|---|
| Automated scanner | Missing ARIA, contrast, alt text | Cannot determine which event listeners are registered or whether they're exclusive |
| Code review | Conditional event listener branches | Requires reviewer familiarity with the failure pattern |
| Manual — keyboard only | Whether keyboard activates interactive controls | Doesn't distinguish F98 from other keyboard failures |
| Manual — touch device + external keyboard | Whether keyboard works on a touch-capable device | The specific test F98 requires |
| Manual — switch access simulation | Whether switch-accessible controls respond | Catches the most severe impact |
The critical test: connect an external keyboard to a touchscreen device (a tablet or touchscreen laptop), then navigate and activate every interactive element using only the keyboard. If controls that work via touch stop responding to keyboard input, F98 is present.
In code review, flag any conditional block that registers event listeners only inside a touch-detection branch. The question to ask: "If this condition is true, does a keyboard user still have a registered handler?" If the answer is no, that's the failure.
For teams managing large codebases, search for touchend and touchstart listeners. For each one, verify that a corresponding click or keyboard handler exists unconditionally. This is a targeted grep, not a full audit — a quick win that operational capacity allows even resource-constrained teams to execute.
The compliance framework research we've published notes that organizations often struggle to prioritize which WCAG failures to address first. F98 should rank high: it's a complete barrier for affected users, it's fixable with a small code change, and the 300ms performance concern that originally motivated the pattern no longer applies in modern browsers.
CORS Perspective
From a community input lens, F98 is a case study in how developer assumptions about who uses what device create invisible exclusion. The assumption embedded in this pattern — that touchscreen users are touch users — erases the real diversity of how disabled people interact with technology. Switch users, keyboard-dependent users, and people who rely on assistive input devices attached to touchscreen hardware are precisely the people this failure locks out. Operationally, the fix is low-cost and the detection method (connect keyboard to touchscreen device, test every control) is teachable in a single training session. The risk profile is clear: 2.5.6 (opens in new window) is a WCAG 2.2 Level AA requirement, placing this squarely in legal compliance territory for organizations subject to ADA Title II or Title III obligations. Strategically, framing this as "removing a workaround that modern browsers made obsolete" makes remediation an easy organizational sell — you're not adding complexity, you're cleaning up technical debt that happens to be a civil rights barrier.
About the Keisha lens
A community-impact lens. Frames findings around who is excluded and what a barrier means in practice, with emphasis on healthcare and grassroots access.
Keisha is an AI analyst lens, not a human staff member. It helps frame this article through a consistent accessibility perspective.
Specialization: Community engagement, healthcare, grassroots
View all articles using this lens →Primary source reviewed: https://www.w3.org/WAI/WCAG22/Techniques/failures/F98 (opens in new window)
Transparency Disclosure
This article was drafted with AI assistance and reviewed against our editorial methodology. We disclose that process so readers can judge the work clearly.