When should a control use aria-disabled="true" instead of the HTML disabled attribute, and what must you handle yourself if you do?
answer
- one is real, one is only an announcement
- tab order is the whole tradeoff
- discoverable versus inert
- you inherit every job it stops doing
- a stale state is the follow-on bug
basics
~20 sUse aria-disabled when the control must stay focusable and discoverable — toolbar items, or a submit button whose blocked reason the user needs to read. It only announces the state, so you must block the action, style the control, and keep it out of any effect yourself.
solid answer
~50 sThe HTML `disabled` attribute genuinely disables a form control: it drops out of the tab order, stops firing activation events, its value is not submitted with the form, and it matches `:disabled`. That is usually right — but an unfocusable control is one a keyboard or screen reader user tabbing through the page never encounters, so they cannot discover it exists or find out why it is unavailable. `aria-disabled="true"` is the alternative: it announces the element as disabled while leaving it fully focusable and fully functional. That is the tradeoff. Choose it when discoverability matters — items in a toolbar or menu, a submit button that should explain what is still missing. Choose it also for elements that have no `disabled` attribute at all, like a link or a `role="button"` div. Having chosen it, you own everything `disabled` used to do: return early in the handler, apply the styling yourself, and remember the value still submits.
go deeper
Know that the HTML disabled attribute really disables a control while aria-disabled only announces the state, and that the ARIA version leaves the control focusable and clickable.
Enumerate what native disabled does — no focus, no events, no submission, matches :disabled — and explain that each of those becomes your responsibility once you switch to aria-disabled.
Justify the choice from user impact: argue when discoverability beats inertness, especially in toolbars and blocked submit flows, and describe how you keep the state and its explanation accurate as conditions change.
Set the house rule so teams stop deciding ad hoc — when the product disables at all versus letting submission surface errors, and how the component API prevents a half-implemented aria-disabled from shipping.
## What the native attribute actually does `disabled` is an HTML content attribute, valid on `<button>`, `<input>`, `<select>`, `<textarea>`, `<fieldset>`, `<optgroup>`, `<option>` and form-associated custom elements. Setting it has several distinct effects at once: - The control becomes **unfocusable** and leaves the tab sequence. - Click and most activation events are not dispatched from it. - Its value is **not submitted** with the form. - It stops participating in constraint validation. - It matches the `:disabled` pseudo-class. - It is exposed to the accessibility tree as disabled, so screen readers announce "dimmed" or "unavailable". Note that it is not available on every element. A link has no `disabled` attribute; neither does a `<div>` you gave `role="button"`. There is nothing to set. ## The cost of unfocusable Removing a control from the tab sequence removes it from the experience of anyone navigating by keyboard or reading linearly with a screen reader. They may never learn the control exists — and when the control is the reason they are stuck ("Submit" is greyed out because a field above is incomplete), silence is exactly the wrong response. The user has no target to inspect, nothing to focus, and no announcement to read. This is worse in composite widgets. In a toolbar, menu or tablist, the APG patterns move focus with arrow keys through a known set of items; an item that vanishes from that set makes the widget's structure shift underneath the user. The WAI-ARIA Authoring Practices therefore recommend keeping disabled items in such widgets focusable. ## What aria-disabled changes — and does not ```html <button aria-disabled="true" aria-describedby="why-blocked">Publish</button> <p id="why-blocked">Add a title before publishing.</p> ``` `aria-disabled="true"` is a state. It changes exactly one thing: the accessibility tree reports the element as disabled, and a screen reader announces it that way. It does not remove focusability, does not stop click or keyboard activation, does not affect form submission, and does not match `:disabled` — so a stylesheet targeting `:disabled` will not touch it and you need an attribute selector instead. Everything the native attribute was doing for you becomes your job: 1. **Block the action.** Your activation handler must check the state and return without doing the work. Do not rely on `pointer-events: none`, which stops the mouse but not the keyboard. 2. **Style it.** The control must look unavailable, and the styling must not rely on `:disabled`. 3. **Handle submission.** If it is a form control with a value and the control is meant to be inert, the value still goes to the server; validate there too. 4. **Keep the state honest.** It is a state, so it flips — the moment the blocking condition clears, the attribute must clear with it. ## Choosing between them Reach for native `disabled` by default. It is one attribute, it is impossible to get half-right, and for an ordinary form field that is simply not applicable right now — a shipping field on a digital-only order — silently removing it from the tab sequence is fine and even kind. Reach for `aria-disabled` when any of these hold: - The control is in a composite widget where the item set should stay stable. - The user needs to find the control to learn *why* it is unavailable, typically paired with a description that explains the blocker. - The element has no native `disabled` attribute — a link, or an element with `role="button"`. - You want the control to remain hoverable and inspectable for a tooltip, which browsers often suppress on truly disabled controls. A note on the modern alternative for submit buttons: rather than either kind of disabling, many teams now leave the submit button fully enabled and let submission surface the validation errors, which is the most discoverable option of all. The disabled-submit pattern exists mainly to prevent double submissions and to signal incompleteness; if you keep it, `aria-disabled` with an explanatory description is the accessible form of it. ## What not to do Do not set both on the same element. `disabled` already exposes the disabled state, so `aria-disabled` adds nothing and creates a second value that can drift. Do not use `aria-disabled="false"` as a way to "re-enable" a natively disabled control — it cannot override the HTML attribute's behaviour, only muddy what is reported. And do not treat `aria-disabled` as a security or integrity measure: it prevents nothing, so the server must still reject what the UI intended to block.
- A designer wants the disabled Submit button to show a tooltip explaining what is missing. Which approach does that push you toward?`aria-disabled`. A natively disabled button is unfocusable and browsers commonly suppress its pointer events, so a keyboard user can never reach the tooltip and a mouse user may not trigger it either. Keeping the button focusable with `aria-disabled="true"` and associating the explanation as a description means the reason is reachable by both keyboard and screen reader.
- Is aria-disabled="true" enough to stop a form control's value from being submitted?No. It changes only what the accessibility tree reports. A control with `aria-disabled="true"` is still a successful form control, so its value is included in the submission, and it still participates in constraint validation. If the value must not reach the server you need the native `disabled` attribute, or you must exclude it in your submit handler and validate server-side regardless.
- Why should you avoid pointer-events: none as the way to make an aria-disabled control inert?It only blocks pointer interaction. The control remains in the tab sequence and still activates on Enter or Space, so keyboard and screen reader users can trigger the action you believed was blocked — and the failure is invisible to anyone testing with a mouse. The activation handler itself must check the state and return early.
- Should you ever set both disabled and aria-disabled on the same element?No. The native attribute already exposes the disabled state to the accessibility tree, so the ARIA attribute is redundant and introduces a second value that can contradict the first if only one gets updated. Pick one per control based on whether it should remain focusable, and let that single source describe the state.
saying these in an interview costs you the question
- Believing aria-disabled prevents clicks or form submission
- Using pointer-events: none as the whole disabling mechanism
- Setting both disabled and aria-disabled on one control
- Styling with :disabled and expecting it to match aria-disabled
- Assuming a greyed-out submit button needs no explanation