The HTML aria-disabled attribute
The aria-disabled attribute tells assistive technology that an element is disabled, but it disables nothing. A <button aria-disabled="true"> still takes focus, fires clicks and submits its form until your script stops it. Use native disabled unless the control has to stay in the Tab order.
Overview
The aria-disabled attribute marks an element as perceivable but not editable or operable. HTML's disabled attribute removes a control from the Tab order, dims it and drops it from form data. The ARIA state does none of that.
A <button aria-disabled="true"> stays in the Tab order, fires click on Enter and Space, and submits its form. An input with the attribute takes typing and sends its value, and :disabled matches neither element.
That gap is why you'd use it. A control left in the focus order can be easier to find, and an undimmed one easier to read. Authors may use it on a button instead of disabled, as long as a script does the disabling. A <div role="button"> needs it as well, since a div doesn't respect disabled.
The state reaches inside. It applies to the element and its focusable descendants, so a button, link or input inside an aria-disabled role="group" is exposed as disabled while all three still work. Take care with containers that mix form controls and links, since the links count as disabled too.
WAI-ARIA 1.2 deprecates it as a global attribute and says future versions will allow it only on roles that specifically support it. Those include button, link, group, tab, menuitem, gridcell, checkbox, textbox and listbox. The generic role isn't one of them, so on a bare <div> the use is deprecated.
Syntax
<button aria-disabled="true">Pay now</button>
<div role="button" tabindex="0" aria-disabled="true">Edit</div>
Values
| Value |
|---|
| true | false |
Example
<form id="order">
<p style="margin:8px 0"><label><input type="checkbox" id="terms"> I accept the terms</label></p>
<button id="pay" aria-disabled="true" style="color:#595959">Pay now</button>
<p id="out" role="status" style="overflow-wrap:anywhere"></p>
<p>Press Pay now, then check the box and press it again.</p>
</form>
<script>
const form = document.getElementById('order');
const terms = document.getElementById('terms');
const pay = document.getElementById('pay');
const out = document.getElementById('out');
terms.addEventListener('change', function () {
pay.setAttribute('aria-disabled', String(!terms.checked));
pay.style.color = terms.checked ? '' : '#595959';
out.textContent = terms.checked ? 'Pay now is available.' : '';
});
form.addEventListener('submit', function (e) {
e.preventDefault();
out.textContent = pay.getAttribute('aria-disabled') === 'true'
? 'The script blocked that. Accept the terms first.'
: 'aria-disabled is false, so a real handler would send the form here.';
});
</script>
Best practices
- Block the action in your own code while
aria-disabledis true. Check the attribute first in each handler, and callpreventDefault()on clicks and submits. - Don't rely on
pointer-events: none. It stops mouse clicks but not keyboard activation. - Style
[aria-disabled="true"]yourself, because no default style applies. Change the appearance so the state shows, and remember that a control left in the focus order may still need to pass color contrast requirements. - Tell people when the control comes back, for example with a
role="status"message.























