Don’t Use aria-label on Static Text Elements (2024)

Lobsters Hottest Tools

Summary

This article explains why using aria-label or aria-labelledby on static text elements like divs and spans is an accessibility antipattern, as these attributes are not permitted on those elements without role overrides, and provides guidance on correct usage.

<p><a href="https://lobste.rs/s/2q39ny/don_t_use_aria_label_on_static_text">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 07/13/26, 03:53 PM

# Don’t Use aria-label on Static Text Elements Source: [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/) ## Too Long; Didn’t Read [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#too-long-didnt-read](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#too-long-didnt-read)Don’t use the`aria\-label`or`aria\-labelledby`attributes on`<div\>`s,`<span\>`s, or other elements representing static/noninteractive text\-level semantics, such as`<p\>`,`<strong\>`,`<em\>`, and so forth, unless those elements’ roles have been overridden with roles that expect accessible names\. That’s a bit of a mouthful, and I couldn’t fit it all in the title\. ## The Antipattern [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#the-antipattern](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#the-antipattern)A*very*common accessibility bug involves applying the[`aria\-label`or`aria\-labelledby`attributes](https://benmyers.dev/blog/aria-labels-and-descriptions/)to static, text\-level semantics, especially`<div\>`s and`<span\>`s\. ``` <!-- 🚨 The following examples are all invalid 🚨 --> <span aria-label="Vegetarian"> 🌱 </span> <div aria-labelledby="about"> <h2 id="about"> About </h2> </div> <div tabindex="-1" aria-label="Draggable item. Click, tap, or press Space to select. Drag, or use arrow keys to move."> <!-- … --> </div> ``` However,**`aria\-label`and`aria\-labelledby`aren’t permitted on these elements**— at least, not without also changing those elements’ roles\. This means that in*most*browser/screenreader combinations \(we’ll get to[a notable exception](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#but-voiceover)shortly\), users generally won’t receive invalidly applied`aria\-label`s or`aria\-labelledby`s, making these accessibility “fixes” anything but\. The short, rule\-of\-thumb\-friendly explanation here is that`aria\-label`and`aria\-labelledby`are generally intended for interactive elements*\(buttons, links, form controls\)*and[landmark regions](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/)\. The longer, more precise explanation is that HTML elements are mapped to[roles](https://benmyers.dev/blog/aria/#role), which specify which kind of thing the element represents\. CertainARIAattributes are only permitted on certain roles\.`aria\-label`and`aria\-labelledby`replace an element’s[accessible name](https://benmyers.dev/blog/aria/#name), which only some roles are permitted to have in the first place\. The way`aria\-label`and`aria\-labelledby`are defined in the[ARIA 1\.2 spec](https://www.w3.org/TR/wai-aria-1.2/#aria-label), they are permitted on any role***except***the following:`caption`,`code`,`deletion`,`emphasis`,`generic`,`insertion`,`paragraph`,`presentation`,`strong`,`subscript`, and`superscript`— generally, your static, noninteractive, text\-level semantics\. At time of writing, the[ARIA 1\.3 draft spec](https://www.w3.org/TR/wai-aria-1.3/#aria-label), which browsers have taken a headstart in supporting, also prohibits`aria\-label`and`aria\-labelledby`on the`definition`,`mark`,`none`,`suggestion`,`term`, and`time`roles\. This means that, per the specs, the following elements aren’t allowed an`aria\-label`or`aria\-labelledby`out of the box, until you start overriding roles: Here there be chonky tablesThe following tables were assembled by crossreferencing the ARIA 1\.2 spec and ARIA 1\.3 draft spec with the[HTML Accessibility API Mappings 1\.0 draft spec\.](https://www.w3.org/TR/html-aam-1.0/)These tables almost certainly aren’t perfect, but should hopefully be complete enough for most scenarios\. Roles Prohibited from`aria\-label`or`aria\-labelledby`in ARIA 1\.2RoleHTML Elements with Default Role`caption`- `<caption\>` - `<figcaption\>` `code`- `<code\>` `deletion`- `<del\>` - `<s\>` `emphasis`- `<em\>` `generic`- Custom elements - `<a\>`without an`href` - `<area\>`without an`href` - `<b\>` - `<bdi\>` - `<bdo\>` - `<body\>` - `<data\>` - `<div\>` - `<footer\>`\(when scoped to`<main\>`or other sectioning content\) - `<header\>`\(when scoped to`<main\>`or other sectioning content\) - `<i\>` - `<pre\>` - `<q\>` - `<samp\>` - `<small\>` - `<span\>` - `<u\>` `insertion`- `<ins\>` `paragraph`- `<p\>` `presentation`*None\.*`strong`- `<strong\>` `subscript`- `<sub\>` `superscript`- `<sup\>` Roles Newly Prohibited from`aria\-label`or`aria\-labelledby`in ARIA 1\.3 DraftRoleHTML Elements with Default Role`definition`- `<dd\>` `mark`- `<mark\>` `none`*None\.*`suggestion`*None\.*`term`- `<dt\>` `time`- `<time\>` This matters because browsers adhere to these specs when assembling[accessibility trees](https://benmyers.dev/blog/accessibility-tree/)for screenreaders to consume, and screenreaders are generally built around supporting these specs\. It’s less that`aria\-label`doesn’t “work” on static, text\-level semantics, but that it’s not even intended to\.[note 1](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-1) If a browser/screenreader combination does handle`aria\-label`and`aria\-labelledby`on static elements like it does permitted roles, that’s an exception to the rule\. Which brings us to a common source of confusion: ## But VoiceOver… [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#but-voiceover](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#but-voiceover)It’s important to test changes with actual assistive technologies like screenreaders, but this can cause a footgun of its own if we test just one tool and assume that its behavior is representative of all similar tools\. We can see a solid example of this with the VoiceOver screenreader built into macOS\. When it comes to`aria\-label`s on generic elements, VoiceOver generally*does*announce the contents of the`aria\-label`\. If that’s the behavior you were expecting, then testing with VoiceOver alone would seem to suggest that this is a condoned, functioning pattern\. In actuality, VoiceOver is doing what many user agents do in the face of invalid code: compensating for developers’ misguided intent so as to not penalize users\.**That`aria\-label`“works” on generic elements in VoiceOver is a nonstandard remediation of noncompliant code, not an endorsement of a technique working as intended\.** As[WebAIM’s surveys of screenreader users](https://webaim.org/projects/screenreadersurvey10/#primary)have borne out, VoiceOver for macOS is severely overrepresented by developers and site/app testers compared to disabled day\-to\-day screenreader users\.[note 2](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-2)When relying on solely VoiceOver for macOS when testing, developers and testers are optimizing for a platform that few disabled users are actually on, with no sense of the expense caused to users on other platforms\. This isn’t to say you shouldn’t test on VoiceOver or consider the VoiceOver user experience… just that it should be one tool of many in your accessibility testing toolkit\. ## Alternatives [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#alternatives](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#alternatives)If we can’t put`aria\-label`or`aria\-labelledby`on static text elements, what should we do instead? It depends, but here’s how I’d approach a few different scenarios: ### Was the Label Addressing a Problem Worth Solving in the First Place? [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#was-the-label-addressing-a-problem-worth-solving-in-the-first-place](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#was-the-label-addressing-a-problem-worth-solving-in-the-first-place)[`aria\-label`is a code smell](https://ericwbailey.website/published/aria-label-is-a-code-smell/)— not necessarily inherently wrong, but often a sign that we might be going off the beaten path\. In some cases, the`aria\-label`might have been put in place to address a perceived problem that might not have been worth solving in the first place, or for which a solution could make things worse in other ways\. For instance, sometimes developers will attempt to use`aria\-label`to[micromanage screenreaders’ pronunciations of words\.](https://adrianroselli.com/2023/04/dont-override-screen-reader-pronunciation.html)In attempting to fix pronunciations, the resulting markup hacks can often make the text completely inscrutable in braille output,[note 3](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-3)and can complicate voice control usage as well\. Meanwhile, pronunciation depends heavily on which text\-to\-speech engine is in use, and[we’re assuming the mispronunciation is even a real, blocking problem in the first place\.](https://benmyers.dev/blog/overriding-screenreader-pronunciations/) On a similar token, sometimes`aria\-label`is used to provide[verbose, redundant, potentially off\-base control hints](https://adrianroselli.com/2019/10/stop-giving-control-hints-to-screen-readers.html), which we could opt to rip out\. These kinds of techniques often arise from incomplete understandings of how screenreader users navigate the web as well as unvalidated assumptions about how they would prefer to receive information, and so the best alternative just might be removing those`aria\-label`s and`aria\-labelledby`s\. ### Use Visible Text [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-visible-text](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-visible-text)In some cases, the`aria\-label`was intended to serve as a sort of alternative text\. In the case of iconography, oftentimes we can opt to rework the design in favor of exposing the information as raw, visible, universal text\. After all, if blind readers would benefit from some extra context or clarity, who’s to say sighted readers wouldn’t benefit from the same? ``` <!-- Instead of… --> <span aria-label="Vegetarian"> 🌱 </span> <!-- Try… --> <span>🌱 Vegetarian</span> <!-- Or maybe… --> <span> <span aria-hidden="true">🌱</span> Vegetarian </span> ``` ### Use Visually\-Hidden Text [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-visually-hidden-text](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-visually-hidden-text)Ah, the design remains firm, unbudging\. We can’t clutter the experience with visible text, it would seem\. Another thing we could do then is a one–two punch of marking the visible contents as`aria\-hidden`, and then using[visually\-hidden styles](https://www.tpgi.com/the-anatomy-of-visually-hidden/)to provide an alternative for screenreaders to expose: ``` <!-- Instead of… --> <span aria-label="Vegetarian"> 🌱 </span> <!-- You could do… --> <span aria-hidden="true">🌱</span> <span class="visually-hidden">Vegetarian</span> ``` ### Use More Semantically Applicable Elements [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-more-semantically-applicable-elements](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#use-more-semantically-applicable-elements)`<div\>`doesn’t accept an`aria\-labelledby`, but if we’re trying to apply one pointing it to a heading, then chances are good that we’re trying to mark out a region of the page, and what we really want is something more like a labeled[`<section\>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/section)or[`<article\>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/article)element instead\. ``` <!-- Instead of… --> <div aria-labelledby="about"> <h2 id="about"> About </h2> <p>…</p> </div> <!-- Let’s make a useful landmark --> <section aria-labelledby="about"> <h2 id="about"> About </h2> <p>…</p> </section> ``` This is especially true for interactive elements —[reverse\-engineering all of the accessibility requirements for interactive elements often just isn’t worth it\.](https://benmyers.dev/blog/clickable-divs/) ### Add an Applicable Role [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#add-an-applicable-role](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#add-an-applicable-role)In some cases, we actually might want to keep the`aria\-label`or`aria\-labelledby`, and just add an applicable role\. ``` <!-- Instead of… --> <span aria-label="Vegetarian"> 🌱 </span> <span aria-label="Kaomoji table flip"> (╯°□°)╯︵ ┻━┻ </span> <!-- It might be more appropriate to expose these like images… --> <span role="img" aria-label="Vegetarian"> 🌱 </span> <span role="img" aria-label="Kaomoji table flip"> (╯°□°)╯︵ ┻━┻ </span> ``` --- [https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#footnotes](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#footnotes)1. I often see discussions around`aria\-label`on static elements get framed as whether it “works” in a given browser/screenreader combination or not\. That said, whether something “works” is often more of a value judgment based how a developer expects things to behave based on their understanding of the world, with little consideration given that the developer could be misguided and their expectations misplaced\. If something behaves like a developer expects, but that behavior goes against what’s been spec’d out… is it really fair to call that “working”? \|[Back to \[1\]](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-ref-1) 2. In the[2023–2024 screenreader user survey](https://webaim.org/projects/screenreadersurvey10/), just 8\.2% of*disabled*respondents reported using VoiceOver for macOS as their primary screenreader, whereas*23\.7%*of nondisabled respondents \(generally understood to be developers, testers, and other accessibility professionals\) reported using VoiceOver for macOS as their primary screenreader\. This jives with the note further down that nondisabled users were nearly three times likelier to use macOS than disabled users were\. \|[Back to \[2\]](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-ref-2) 3. In the same 2023–2024 screenreader user survey,[38% of disabled respondents](https://webaim.org/projects/screenreadersurvey10/#braille)reported that they use their screenreader with[braille output\.](https://en.wikipedia.org/wiki/Refreshable_braille_display)Assuming this survey is representative*\(which, as with any survey, is its own can of worms\)*, this means that pronunciation\-tackling markup hacks have the potential to confuse about 2 out of every 5 screenreader users, rather than*\(potentially\)*clarifying things for those users\. \|[Back to \[3\]](https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/#fn-ref-3) ---

Similar Articles

Don't put aria-label on generic elements like divs

Hacker News Top

This article explains why using aria-label on generic HTML elements like divs or spans violates ARIA spec and leads to inconsistent screen reader behavior, with browser testing results.

ARIA, anti-patterns, and you

Lobsters Hottest

The article criticizes the misuse of ARIA and the ARIA Authoring Practices Guide (APG), warning against using LLM agents to generate code from the APG, and emphasizes that native HTML should be preferred over ARIA for accessibility.

Fixing my tooltip accessibility mistake

Hacker News Top

Jake Archibald shares an accessibility mistake he made implementing tooltips with popover="hint" and aria-describedby, and explains the correct pattern after feedback from accessibility experts.

The <noscript> element as a trap

Lobsters Hottest

The article discusses the limitations of the <noscript> HTML element, which only provides fallback content when JavaScript is completely disabled, not when JavaScript fails due to other reasons. It recommends using DOM APIs to dynamically update content instead.

On the <dl>

Simon Willison's Blog

A blog post by Ben Meyer shares new-to-me facts about the HTML <dl> element, including that multiple <dd> can follow a <dt>, grouping within <div>, ARIA labeling, and that they've been called 'description lists' since 2008.