Also available in Español
The Claim Being Tested
Thursday's essay argued that ARIA is a semantic intervention: it should supply what the native document doesn't already express, not replace what it does. The claim was tested against two shipped mistakes on the same navigation control — an aria-label that replaced a correct accessible name, and a <div role="button"> standing in for a control that already existed as <button>.
This Note takes both apart, one piece at a time, and confirms what's left once everything unnecessary comes off.
Reduction One: The Button
As shipped:
<button aria-label="Dismiss navigation panel">
Close menu
</button>
Before touching anything, walk the accessible name computation the way the browser actually runs it. aria-labelledby: not present. aria-label: present, value "Dismiss navigation panel." The computation stops there. It never reaches the button's own content, because nothing requires it to keep looking once an earlier step has already produced an answer.
Remove the one attribute:
<button>
Close menu
</button>
Walk the computation again. aria-labelledby: not present. aria-label: not present. Content: "Close menu," and <button> is one of the roles the computation reads a name from directly. That's the accessible name now. It always could have been. Nothing was added to produce it. The only change was removing the thing that had been outranking it.
Reduction Two: The Div
The same review's second control, in full:
<div role="button" tabindex="0" class="menu-close">
Close menu
</div>
const closeControl = document.querySelector('.menu-close');
closeControl.addEventListener('click', closeMenu);
closeControl.addEventListener('keydown', (event) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
closeMenu();
}
});
Strip the keydown handler first, leave everything else:
<div role="button" tabindex="0" class="menu-close">
Close menu
</div>
document.querySelector('.menu-close').addEventListener('click', closeMenu);
The div still announces as a button. It's still reachable by Tab. Click still closes the menu. Press Enter or Space instead, and nothing happens at all — role="button" never came with the keyboard activation a real button provides automatically. That was always the keydown handler's job, and it's the only thing that just left.
Strip the rest, and change the element:
<button class="menu-close">
Close menu
</button>
document.querySelector('.menu-close').addEventListener('click', closeMenu);
One listener, unchanged. No role attribute, no tabindex, no keydown handler. Tab still reaches it. Click still closes the menu. Enter and Space close it too, because a native button fires the same click event in response to all three, without being told to. The div needed two separate event bindings to cover what the tag now covers with one.
Whether the Claim Held
Both reductions land on the answer the essay's thesis predicts: a document whose semantics are the correct amount, no more and no less. The button never needed a label — content had already been doing that job, and the only thing standing in its way was an attribute added to satisfy a checklist. The div never needed to be a div. It was carrying a role, a tabindex, and a keydown handler to simulate behavior <button> was always going to provide on its own, for one less event binding than the div ever managed.
Neither fix added anything. Both subtracted exactly the piece that was substituting for something the platform already had, and the result in each case wasn't a smaller version of the same thing. It was the thing working correctly for the first time.
Reference Article:
The Browser Already Has an Accessibility Architecture. Most Projects Ignore It.
Top comments (0)