Skip to content

noDisabledAttribute (JavaScript)

biome.json
{
"linter": {
"rules": {
"nursery": {
"noDisabledAttribute": "error"
}
}
}
}

Discourages the disabled attribute on form controls and on elements that act as buttons.

This is an opinionated usability rule, not a Web Content Accessibility Guidelines (WCAG) requirement. A form control with the native disabled attribute can’t receive keyboard focus, so people who move through a page with the Tab key skip over it. Keeping an unavailable control focusable can make it easier to discover with a keyboard or assistive technology.

The rule reports the following elements when disabled is set:

  • Buttons: button elements, and input elements with the button, submit, reset, or image type. A button is still reported when a role other than button is assigned, because disabled continues to change its native behavior.
  • Fields that support the readOnly attribute: textarea elements, and input elements whose type accepts typed input, such as text, email, number, or date. An input with no type, or with a type that browsers don’t recognize, is a text field.
  • Other form controls: select elements, and input elements with the checkbox, radio, range, color, or file type.
  • fieldset elements, because a disabled fieldset disables every form control inside it.
  • Built-in elements that aren’t form controls and whose first valid explicit role is button. The disabled attribute has no effect on these elements.

The rule doesn’t report option and optgroup elements, input elements with the hidden type, or input elements whose type is a dynamic expression or can come from a spread attribute.

The unsafe fix depends on the reported element:

  • For fields that support it, the fix replaces disabled with readOnly. A read-only field can receive focus and can’t be edited. Unlike a disabled field, its value is still submitted with the form, and browsers don’t apply disabled styling to it.
  • For buttons, other form controls, and elements with the button role, the fix replaces disabled with aria-disabled. The ARIA attribute only exposes the disabled state to assistive technology. It does not prevent pointer or keyboard activation, change form submission or validation, omit values from submitted data, or add disabled styling. Implement those behaviors and provide disabled styling, including for forced-colors mode.
  • A fieldset has no fix. Mark each form control inside it instead. Disabling a fieldset can be appropriate when the whole group doesn’t apply to the user, for example the details of a second applicant when there is only one applicant. In that case, suppress the diagnostic.
<button disabled>Save</button>
code-block.jsx:1:9 lint/nursery/noDisabledAttribute  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ Avoid the native disabled attribute on this button.

> 1 │ <button disabled>Save</button>
│ ^^^^^^^^
2 │

ℹ A disabled form control can't receive keyboard focus, so it can't be reached with the Tab key.

ℹ Replace it with aria-disabled, which only exposes the disabled state to assistive technology. It does not suppress pointer or keyboard activation, form submission or validation, or apply disabled styling. Implement those behaviors, including forced-colors styling.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Use aria-disabled instead.

1 │ <button·aria-disabled="true">Save</button>
│ +++++ +++++++
<input type="email" disabled />
code-block.jsx:1:21 lint/nursery/noDisabledAttribute  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ Avoid the native disabled attribute on this field.

> 1 │ <input type="email" disabled />
│ ^^^^^^^^
2 │

ℹ A disabled form control can't receive keyboard focus, so it can't be reached with the Tab key.

ℹ Replace it with readOnly, which keeps the field focusable and prevents edits. Unlike a disabled field, a read-only field is still submitted with its form and doesn't get disabled styling.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Use readOnly instead.

1 │ - <input·type="email"·disabled·/>
1 │ + <input·type="email"·readOnly·/>
2 2 │

<select disabled><option>Monthly</option></select>
code-block.jsx:1:9 lint/nursery/noDisabledAttribute  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ Avoid the native disabled attribute on this form control.

> 1 │ <select disabled><option>Monthly</option></select>
│ ^^^^^^^^
2 │

ℹ A disabled form control can't receive keyboard focus, so it can't be reached with the Tab key.

ℹ Replace it with aria-disabled, which only exposes the disabled state to assistive technology. It does not suppress pointer or keyboard activation, form submission or validation, or apply disabled styling. Implement those behaviors, including forced-colors styling.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Use aria-disabled instead.

1 │ <select·aria-disabled="true"><option>Monthly</option></select>
│ +++++ +++++++
<fieldset disabled><input type="text" /></fieldset>
code-block.jsx:1:11 lint/nursery/noDisabledAttribute ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ Avoid the native disabled attribute on this fieldset.

> 1 │ <fieldset disabled><input type="text" /></fieldset>
│ ^^^^^^^^
2 │

ℹ A disabled fieldset disables every form control inside it, so none of them can be reached with the Tab key.

ℹ Mark each form control inside the fieldset instead: use readOnly on fields that support it and aria-disabled on other controls.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<div role="button" disabled>Save</div>
code-block.jsx:1:20 lint/nursery/noDisabledAttribute  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The disabled attribute has no effect on this element.

> 1 │ <div role="button" disabled>Save</div>
│ ^^^^^^^^
2 │

ℹ The button role changes accessibility semantics but does not add native button behavior.

ℹ Replace it with aria-disabled, which only exposes the disabled state to assistive technology. It does not suppress pointer or keyboard activation, form submission or validation, or apply disabled styling. Implement those behaviors, including forced-colors styling.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Use aria-disabled instead.

1 │ <div·role="button"·aria-disabled="true">Save</div>
│ +++++ +++++++
<>
<button aria-disabled="true">Save</button>
<input type="email" readOnly />
<select aria-disabled="true"><option>Monthly</option></select>
<input type="hidden" disabled />
</>