
Native built-in browser elements you can use today instead of ARIA or ROLE attributes
Replace ARIA roles with semantic HTML and use native elements for better accessibility and cleaner code.
When building accessible web applications, developers have long relied on ARIA and role attributes to fill gaps in native HTML.
But today, many of those gaps are gone. Modern browsers support a wide range of semantic HTML elements and built-in behaviors that make ARIA redundant in most cases, often with better results and fewer bugs.
This shift towards native accessibility features means that developers can now create accessible web applications using built-in browser elements and attributes, rather than relying solely on ARIA and ROLE only.
We’ll explore the native built-in browser elements and attributes that you can use today to improve accessibility, and how they can replace or complement ARIA and ROLE attributes in your web development workflow. By leveraging these native features, you can simplify your code, improve maintainability, and create more accessible web applications for everyone.
The first rule of ARIA
The first rule of ARIA is straightforward: Don’t use ARIA if you can use native HTML
.
This principle encourages developers to leverage semantic HTML whenever possible, reserving ARIA for cases where native elements cannot provide the necessary functionality. By adhering to this rule, developers can create more accessible and maintainable web applications.
Why move away from ARIA?
Move away from ARIA
doesn’t mean stop caring about accessibility
. It means: use the native HTML feature first, and only reach for ARIA when HTML genuinely can’t express the semantics or behaviour. The reasons are practical, not ideological.
Browser-engine privilege
Native elements get their semantics, keyboard behaviour, focus management, validation feedback, and accessibility-tree mappings baked into the browser’s C++ code.
ARIA is only a set of hints that the browser must retrofit onto a generic div or span.
That retrofit is inconsistent across screen-reader / browser pairs and is still missing pieces (e.g. accessible value text for some roles).
Less code, less maintenance
<dialog open> gives you focus trapping, Esc to close, inert background, and exposes role="dialog" automatically.
Re-creating the same with role="dialog", aria-modal="true", inert polyfill, focus-loop script, keydown listener, and a11y-tree tests is ~150 lines you now own forever.
Smaller payload, faster render
Every aria-* attribute is extra bytes in HTML, extra DOM properties to parse, extra work for the accessibility engine.
Built-in resilience to future spec changes
When ARIA 1.3 re-defines aria-expanded or when Chrome changes how aria-hidden interacts with inert, your carefully tested ARIA widget may suddenly break
in Canary.
Native elements shield you from that churn as the browser vendor owns the fix.
Mobile and voice-input compatibility
TalkBack, VoiceOver on iOS, and Siri/Dragon all have special code paths for button, select, <input type="range">, etc.
Those paths often ignore the ARIA you added and fall back to the native role, or worse, expose both and create duplicate announcements.
Security and performance isolation
Custom widgets usually need extra JavaScript event listeners (keydown, click, blur, focus, touchstart).
More JavaScript surface leads to a larger attack surface, longer JavaScript task time, higher interaction-to-next-paint (INP).
Internationalisation for free
A native <input type="date"> automatically uses the user’s locale for day/month order and screen-reader pronunciation.
Your role="combobox" calendar popup speaks English month names even if the user’s screen reader is set to Japanese.
Future-proofing for new input modalities
Eye-tracking, switch devices, and stylus-first UAs optimise for native controls because they can query the OS for role, state, and hit-target geometry.
They can’t do that with a <div role="slider"> drawn on a canvas.
Easier testing and audits
Does the HTML validator complain?
is a single, deterministic check.
Does NVDA 2024.2 + Firefox 126 expose the correct value text for
is not.aria-valuetext when the node is re-parented under aria-hidden="false"?
Legal, procurement safety
EN 301 549 v3.2.1 (clause 11.4.1.2.1) makes WCAG 2.2 Success Criterion 4.1.2 legally binding for EU public-sector ICT. The normative text requires only that standard UI components be used according to specification
and that custom components expose name, role, state and value programmatically.
The stronger sentence If an HTML element with the required semantics exists, it must be used instead of ARIA
does not appear in WCAG itself, but reflects guidance from the WAI-ARIA 1.2 specification (§1.1 Rich Internet Application Accessibility), which states:
WAI-ARIA is intended to be used as a supplement for native language semantics, not a replacement. When the host language provides a feature that provides equivalent accessibility to the WAI-ARIA feature, use the host language feature. WAI-ARIA should only be used in cases where the host language lacks the needed role, state, and property indicators. Use a host language feature that is as similar as possible to the WAI-ARIA feature, then refine the meaning by adding WAI-ARIA. For instance, a multi-selectable grid could be implemented as a table, and then WAI-ARIA used to clarify that it is an interactive grid, not just a static data table. This allows for the best possible fallback for user agents that do not support WAI-ARIA and preserves the integrity of the host language semantics.
Nevertheless, auditors and conformity assessment bodies, including SiteLint, routinely treat reliance on native HTML as best practice and may record excessive or redundant ARIA as a failure of clause 11.4.1.2.1 if it results in incorrect name, role, state, or value information.
When ARIA is still justified
The ARIA is still justified in the following cases:
- Composite widgets with no HTML equivalent (e.g., a multi-select tree-grid, a slider-with-thumb-labels, a tabs-with-automatic-activation pattern).
- Temporary bridging until a native element ships and reaches your support matrix (e.g.,
selectmenuis still behind a flag orinput type checkboxwith theswitchattribute). - Visual designs that must break native rendering but still need to expose the same semantics (rare, and even then start with
buttonand restyle withappearance: nonefirst). - Cases where native semantics exist but are not yet consistently interpreted by assistive technologies. In such situations, ARIA attributes may be temporarily required to ensure correct name, role, or state exposure across screen reader and browser combinations.
Native HTML replacements for ARIA roles and attributes
Let’s explore and see how modern HTML makes many ARIA roles and attributes obsolete:
| Use case | Native HTML element, attribute | ARIA you can delete | Notes |
|---|---|---|---|
| Button | <button>, <input type="button|submit|reset"> | role="button", aria-pressed | Use aria-pressed only for toggle buttons |
| Link | <a href="…"> | role="link" | Native link behavior is fully accessible |
| Heading | <h1> to <h6> | role="heading", aria-level | Semantic structure is built-in |
| Text and structural elements | <p>, <ul>, <li>, <table>, <section>, etc. | All matching role="…" | Native semantics cover all these roles |
| Image / icon | <img alt="…"> | role="img" | Use alt="" for decorative images |
| Form controls | <input>, <textarea>, <select>, <progress>, <meter> | role="textbox", role="checkbox", etc. | Use HTML5 validation attributes instead of ARIA |
| Validation states | required, disabled, readonly, pattern, min, max, step | aria-required, aria-disabled, aria-readonly, aria-invalid | Native attributes trigger built-in validation |
| Error text / description | <label> + <span id="…"> | role="tooltip" | Use aria-describedby only when needed |
| Live region | <output> | aria-live, aria-atomic, aria-relevant | <output> is treated as a live region |
| Disclosure widget | <details><summary> | role="button", aria-expanded, aria-controls | Browser exposes expand/collapse state |
| Modal dialog | <dialog> + showModal() | role="dialog", aria-modal, focus trap scripts | Native focus management and ESC to close |
| Select menus / combobox | <select> | role="listbox", aria-expanded, aria-selected | Stylable with appearance: base-select |
| Hidden content | inert attribute | aria-hidden="true" | Blocks both keyboard and screen reader access |
| Keyboard shortcuts | accesskey attribute | role="button" + JavaScript hotkeys | Native shortcut support |
| Landmarks | <main>, <nav>, <header>, <footer>, <aside>, <form> | role="main", role="navigation", etc. | Use semantic elements directly |
| Grouping / captioning | <fieldset>, <legend>, <figure>, <figcaption> | role="group", role="figure" | Native grouping semantics |
| Ordered steps | <ol> | role="list", role="listitem" | Built-in list semantics |
| Visual separator | <hr> | role="separator" | Native visual and semantic meaning |
| Line break | <br> | role="none" | No need to override semantics |
| Generic wrapper | <div>, <span> | role="none", role="presentation" | Already mapped as generic |
| File upload | <input type="file"> | role="button" on wrapper | Native file picker behavior |
| Color picker | <input type="color"> | role="button", aria-haspopup, aria-expanded | Native color selection UI |
| Slider | <input type="range"> | role="slider", aria-valuemin/max/now | Native range semantics |
| Progress bar | <progress> | role="progressbar", aria-valuemin/max/now | Native progress semantics |
| Meter / gauge | <meter> | role="progressbar" | ARIA role="meter" doesn’t exist |
| Date / time picker | <input type="date|time|month|week"> | role="combobox", aria-expanded, aria-haspopup | Native calendar UI |
| Search landmark | <form role="search"> | role="search" on div | Use form for landmark |
| Block quote | blockquote | role="blockquote", role="figure" | Native semantic meaning |
| Captions / subtitles | <track kind="captions|subtitles"> | ARIA live-region hacks | Native media captioning |
| Focus indicator | :focus-visible CSS | role="button" + tabindex="0" on span | Use CSS for visual focus |
Conclusion
ARIA is a polyfill. Polyfills are meant to disappear as the platform fills the gaps.
Every time you choose button over <div role="button">, you retire code, reduce risk, and let the browser do the heavy lifting.
Overall, incorporating native HTML elements into web development not only enhances accessibility but also simplifies the coding process. By prioritizing these elements over ARIA roles and attributes, developers can create more robust and user-friendly web applications.
Always remember that while ARIA can be useful in specific scenarios, it should be considered a last resort when native HTML cannot achieve the desired functionality.
Need help with digital accessibility?
- Audit and debug pages with reports in a user-friendly format directly from the browser.
- Install when you can't use browser extension.
- Audit fully rendered pages, including themes and plugins.
- Effortlessly audit every page automatically. Integrate a code snippet and manage multiple sites from a central dashboard.
Comments