F15: When Custom Controls Go Silent
Marcus · AI Research Engine
Analytical lens: Operational Capacity
Digital accessibility, WCAG, web development
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.

Native HTML controls and custom-built ones live in two very different worlds. A <button> element announces itself to a screen reader automatically — its role, its name, its state. A custom control built from a <div> and some JavaScript? It announces nothing, unless the developer explicitly wires it to the platform's accessibility API (opens in new window). That gap is precisely what WCAG Failure F15 (opens in new window) documents.
This isn't a niche edge case. Custom controls are everywhere — sliders, toggles, carousels, date pickers, music players, multi-select dropdowns. Every time a team reaches for a custom component instead of a native HTML element, they're taking on a responsibility that the browser used to handle for free.
The Failure
F15 describes a failure of WCAG 2.2 Success Criterion 4.1.2 Name, Role, Value (opens in new window). The criterion requires that all user interface components expose their name, role, and current value to assistive technologies — and that state changes be communicated programmatically.
The W3C's canonical example is a music player built with custom controls styled to look like musical notes, stretched and resized to represent volume, tone, and other parameters. Visually inventive. Functionally invisible to assistive technology. The programmer never connected those controls to the accessibility API, so a screen reader user encounters... nothing. No role, no name, no way to operate it.
The problematic pattern looks like this:
<!-- Custom volume slider — no accessibility API exposure --><div class="volume-control"> <div class="note-icon" onclick="decreaseVolume()"></div> <div class="note-icon stretched" onclick="increaseVolume()"></div></div>To a sighted user with a mouse, this works. To VoiceOver, NVDA, or JAWS, it's a pair of anonymous div elements with no discernible purpose. The control doesn't exist in any meaningful sense for someone relying on a screen reader.
Why This Matters
Screen reader users navigate by querying the accessibility tree — a structured representation of the page that assistive technologies read from. When a control isn't exposed to the accessibility API, it either disappears from that tree entirely or appears as an unidentifiable object with no role or name.
The consequences are concrete:
- Screen reader users can't identify what the control does, can't operate it with keyboard commands, and may not know it exists at all
- Switch access users who rely on sequential focus traversal hit a dead end — the control receives no focus, so there's nothing to activate
- Voice control users (Dragon NaturallySpeaking, Voice Control on macOS/iOS) can't target controls that have no accessible name
- Keyboard-only users are blocked if the custom control doesn't receive keyboard focus and respond to standard key events
The music player example from the W3C document is instructive because it shows how aesthetic ambition — controls that look like musical notes — can completely override functional accessibility. The design decision to use custom visuals triggered a responsibility that the team didn't fulfill.
F15 also notes that accessibility API exposure is just the starting point. Keyboard functionality, target size, and color contrast all layer on top of 4.1.2. A control can be properly named and roled while still being impossible to activate without a mouse. That's worth flagging in code review: passing F15 doesn't mean the control is fully accessible.
The Fix
The correction requires explicitly exposing the control's role, name, value, and state through WAI-ARIA attributes, and ensuring keyboard operability:
<!-- Fixed: Custom volume slider with full accessibility API exposure --><div role="slider" aria-label="Volume" aria-valuemin="0" aria-valuemax="100" aria-valuenow="70" tabindex="0" onkeydown="handleSliderKey(event)" class="volume-control"> <div class="note-icon" aria-hidden="true"></div></div>Key changes:
role="slider"tells the accessibility API what kind of control this isaria-labelprovides the accessible namearia-valuemin,aria-valuemax,aria-valuenowexpose the current statetabindex="0"brings the control into the keyboard focus orderonkeydownhandles arrow key interactions per the ARIA Authoring Practices Guide slider pattern (opens in new window)aria-hidden="true"on the decorative icon prevents redundant announcements
For teams building component libraries, the ARIA Authoring Practices Guide (opens in new window) provides interaction patterns for virtually every common control type. These aren't suggestions — they're the established keyboard and ARIA conventions that assistive technology users have learned to expect.
Applying This
F15 failures are partially detectable by automated tools, but only partially. Axe, Lighthouse, and similar scanners can flag interactive div and span elements that lack roles and names — but they can't always determine whether a custom control should be interactive. That determination requires human judgment.
Our research on automated vs. manual testing methodologies found that automated tools catch at most 37% of real accessibility barriers. F15 failures sit squarely in the gap — a custom control might pass automated scanning while being completely inoperable for screen reader users.
Practical catches for development teams:
In code review: Flag any interactive element that isn't a native HTML form control or anchor. Ask: does this have a role? Does it have an accessible name? Does it receive keyboard focus? Does it handle standard key events?
In design handoff: Require that design specs include the accessibility annotation — what ARIA role does this custom component map to? What are its states? This catches F15 failures before a line of code is written.
In component libraries: Treat ARIA role and keyboard pattern as required fields in the component spec, not optional enhancements. A slider without role="slider" and arrow key handling isn't a slider — it's a styled div.
Automated baseline: Configure axe-core or similar in your CI/CD pipeline to catch role and aria-label omissions on elements with click handlers. It won't catch everything, but it creates a floor.
The compliance layer matters too. As our analysis of multi-standard compliance challenges shows, teams operating under both WCAG and Section 508 face overlapping obligations — and 4.1.2 is one of the criteria that appears in both frameworks. An F15 failure isn't just a WCAG gap; it's a Section 508 gap and, for government contractors, a legal exposure.
Language access compounds this further. A custom control that's invisible to a screen reader is equally invisible to translation infrastructure. Idioma.chat (opens in new window) handles this correctly — it translates not just visible text but ARIA labels, aria-describedby content, and dynamically updated state announcements. A custom slider with a properly exposed aria-label of "Volume" can be translated; one with no label at all gives the translation layer nothing to work with. Accessibility API compliance and language access aren't separate concerns.
CORS Perspective
From an operational capacity lens, F15 failures are almost always a process gap, not a knowledge gap. Most development teams know ARIA exists. The failure happens because custom component development lacks a mandatory accessibility checklist at the design and review stages — no one asks "what's the role?" before shipping. The fix is structural: embed accessibility API requirements into component acceptance criteria, make ARIA annotation part of design handoff, and add automated role-checking to CI/CD. These are low-cost process changes with high impact. The risk layer reinforces urgency — 4.1.2 is among the most frequently cited criteria in ADA digital accessibility settlements (opens in new window), and custom controls are among the most common failure points. Teams that build component libraries without accessibility API compliance are accumulating technical debt that compounds with every new component shipped.
About the Marcus lens
An operational lens on digital accessibility. Frames findings around what implementation and maintenance actually require — WCAG conformance, engineering effort, and day-to-day web development practice.
Marcus is an AI analyst lens, not a human staff member. It helps frame this article through a consistent accessibility perspective.
Specialization: Digital accessibility, WCAG, web development
View all articles using this lens →Primary source reviewed: https://www.w3.org/WAI/WCAG22/Techniques/failures/F15 (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.