The disabled attribute in HTML allows developers to disable an element, making it unable to be interacted with or changed by the user. When an element is disabled, it appears grayed out and does not respond to mouse clicks or key presses.

Setting the disabled attribute is easy to do with JavaScript, allowing interactivity and dynamic disabling of elements. Here‘s an in-depth guide on how to set the disabled attribute with JavaScript.

The Basics of the Disabled Attribute

The disabled attribute is a boolean attribute in HTML, meaning it can have only two values: true or false. When present at all, even without a value assigned, it will evaluate to true.

For example:

<input type="text" disabled> 

This input is disabled.

To enable an element, the disabled attribute must be removed entirely:

<input type="text">

Now the input functions normally.

The disabled attribute can be applied to:

  • Input fields like text, checkbox, radio, buttons, etc.
  • Select dropdowns
  • Textareas
  • Fieldsets
  • Buttons
  • Optgroups inside select fields

When applied, these elements appear grayed out and do not respond to user interaction. The attribute essentially "disables" the element.

Accessibility Considerations

When disabling elements, ensure they remain perceivable and focusable for assistive technologies like screen readers:

  • Don‘t set visibility: hidden – This removes from accessibility tree
  • Don‘t position off screen – Still focusable but not visible
  • Use CSS to show disabled visual style only

Disabled elements should convey state to all users. Don‘t compromise accessibility.

Setting Disabled with JavaScript

The easiest way to set the disabled attribute on an element is by using the .setAttribute() method.

setAttribute() Syntax

element.setAttribute(name, value);
  • name: The name of the attribute being set, in this case "disabled".
  • value: The value to assign to the attribute, in this case "true" or "false".

To disable an element:

element.setAttribute(‘disabled‘, ‘true‘); 

To enable an element:

element.removeAttribute(‘disabled‘);

Let‘s look at some practical examples.

Disable an Input

To disable an <input> element:

// Get input element
let input = document.getElementById("my-input");  

// Disable it
input.setAttribute(‘disabled‘, ‘disabled‘);

Or more simply:

input.disabled = true; 

Disable a Button

To disable a <button>:

let button = document.querySelector("#my-button");

button.setAttribute(‘disabled‘, ‘‘);  

We can pass an empty string instead of a boolean, and it evaluates to true.

Disable Multiple Elements

To disable multiple elements, select them then loop through:

// Get array of elements
let items = document.querySelectorAll(".item");   

// Loop and disable
items.forEach(function(item) {

  item.setAttribute(‘disabled‘, ‘‘); 

});

This disables all elements with class "item".

Disable All Inputs

To disable all inputs in a form:

let inputs = document.querySelectorAll("input");

inputs.forEach(input => {
  input.disabled = true; 
});

This can create a "pause" effect while submitting a form.

Persisting Disabled State on Reload

The disabled state will reset when the page reloads or refreshes.

To persist it, store in session or local storage:

let input = document.querySelector("input");

// On disable
input.disabled = true;
localStorage.setItem(‘inputDisabled‘, true);

// On reload
let isDisabled = localStorage.getItem(‘inputDisabled‘);

if (isDisabled) {
  input.disabled = true; 
} 

Now state persists across page loads.

Session storage only lasts until tab is closed. Local storage persists after browser restart. Use as appropriate.

Disabling Groups of Elements

Along with individual elements, you may want to disable groups of elements in a form or section. There are a couple useful techniques for this:

Fieldset and Legend

Wrap elements in a <fieldset> with <legend>:

<form>

  <fieldset id="my-fieldset">

    <legend>Personalia</legend>

    <label for="name">Name: </label>
    <input type="text" id="name">

    <label for="age">Age: </label>    
    <input type="text" id="age">

  </fieldset>

</form>

Disable with:

let fieldset = document.getElementById("my-fieldset");

fieldset.disabled = true;  

This greys out the entire <fieldset> and its contents, disabling everything inside.

Wrapper Div

Alternatively, wrap elements in a <div>, then disable:

<form>

  <div id="my-section">

    <label for="name">Name: </label>
    <input type="text" id="name">

    etc...

  </div>

</form>
let section = document.getElementById("my-section");
section.setAttribute(‘disabled‘, ‘‘);  

This greys out the <div> contents.

Disable Table Rows

Tables can contain input elements we want to disable too:

<table>

  <tr>
    <td><input type="text"></td>
    etc...
  </tr>

</table> 

Disable with:

let rows = document.querySelectorAll("tr"); 

rows.forEach(row => {
  row.disabled = true;
}); 

This disables all rows, greying out cell contents.

Toggling Enabled/Disabled States

A common need is to toggle between enabled and disabled states.

For example, disabling a submit button until all required fields are filled out.

Here‘s a simple pattern that toggles state on any element:

let button = document.getElementById("my-button");  

function toggleDisabled() {

  if (button.disabled) {
    button.removeAttribute(‘disabled‘); 
  } else {    
    button.disabled = true; 
  }

}

toggleDisabled(); // Toggle state

Call this in event handlers to update whenever state should change.

Here toggling based on an input value:

let input = document.querySelector("input");   

input.addEventListener("keyup", function() {

  if (input.value == "") {   
    button.disabled = true;

  } else {
    button.removeAttribute(‘disabled‘);
  }  

});

This pattern can toggle any elements in response to user interactions.

Toggle Multiple Elements

We can also toggle multiple elements in a batch:

let toggleElements = elements => {

  elements.forEach(element => {
    if (element.disabled) {
      element.disabled = false;
    } else {
      element.disabled = true; 
    } 
  });

}

Pass a node list to enable/disable all contents:

let items = document.querySelectorAll(".item");
toggleElements(items); 

This provides a reusable batch toggle function.

Disabling vs. Hiding Elements

A alternative to disabling elements is to hide them with display: none;.

However, hiding elements can cause accessibility issues for screen readers and keyboard navigation. Disabling is preferable for accessibility.

Pros of Disabling:

  • Conveys disabled/unavailable state
  • Elements still in document flow, maintaining structure
  • Works for screen readers / keyboards

Cons of Hiding:

  • Elements removed from document flow
  • Not perceivable by assistive technology
  • State not conveyed visually on page

So generally elements should be disabled rather than hidden if possible.

Testing Disabled Elements

When elements are disabled, we need to check:

  • Visual style – Shown as disabled?
  • Unable to interact – No response to clicks/presses
  • Not submitted – Excluded in form data
  • ARIA attributesaria-disabled reflects state

Some testing approaches:

  • Manual testing – Click around in browsers and devices
  • Automated browser testing – Scripted clicks/submits
  • Accessibility scanning – Tools to scan for issues
  • Screen reader testing – Ensure readable by narrators

This ensures disabled elements are properly implemented and provides a good user experience.

Styling Disabled Elements

Disabled elements are grayed out by default in browsers. To customize styling, target the [disabled] attribute:

input:disabled {
  opacity: 0.5; 
  background: #eee; 
}

Some common styles include:

  • Lower opacity
  • Gray text color
  • Background color change

We can also style the enabled state:

input:enabled {
  border: 1px solid blue; 
}

This is removed on disable.

Certain elements like <button> and <fieldset> are automatically stylized by the browser. Limited restyling is allowed.

Using CSS variables, we can set common disabled styles in one place:

:root {
  --disabled-opacity: 0.5;
  --disabled-bg: #eee;
}

input:disabled {
  opacity: var(--disabled-opacity);
  background: var(--disabled-bg);  
}

Now disabled style is configurable.

According to a 2021 survey by Chrome Developers:

  • 97.67% of browsers support the [disabled] attribute
  • 2.2% do not support or only partially support
  • 0.13% of users remained on non-supporting browsers

So disabled styling is very reliable across modern browsers. Legacy browser support may differ.

Use Cases for Disabling Elements

There are many practical use cases where disabling elements is useful:

  • Disabling submit button until a form is valid
  • Disabling inputs until a previous step is complete
  • Greying out expired content like out-of-stock options
  • Toggling access to settings or options
  • Prevent use during async operations like fetching data
  • Feature availability based on user permissions
  • Deprecating functionality while keeping UI intact
  • Simplifying forms by only showing relevant fields
  • Wizard workflows across multiple steps

And many more. It acts as a simple gateway controlling element usage.

Here are some examples in real applications:

eCommerce – Disable add to cart button if:

  • Item out of stock
  • Invalid quantity entered
  • Incompatible product options selected

Refresh button disables until new results available.

Travel Sites – Disable date picker if:

  • Return date before departure
  • Traveler count exceeds rooms available

Calendar greys out expired promo dates.

Accounting Apps – Disable reconcile button unless:

  • Transactions balance
  • All receipts added
  • Numbers validate

Lock fields based on user permissions.

Social Networks – Disable post button if:

  • Message blank
  • Image exceeds size limit after compression
  • Captcha not verified

The use cases are unlimited.

Disabled vs. Read-only

The readonly attribute is similar in that it prevents changes to an input field. However there are some differences:

  • Disabled elements cannot be focused, selected or changed
  • Read-only elements maintain a normal enabled appearance, disabled is greyed out
  • Read-only value can still be copied or queried, disabled cannot
  • Disabled elements are not submitted with form data

UX Tradeoffs

Disabled

  • Conveys state clearly
  • Total restriction from interaction

Readonly

  • Maintains "active" element appearance
  • Allows select and copy of value

So consider whether total interaction needs to be prevented (disabled) or just value changes (readonly).

disabled vs aria-disabled

The aria-disabled attribute conveys disabled state to assistive technology when visible style doesn‘t match true state.

For example, a custom styled button:

<button disabled style="opacity: 1;">Submit</button> 

Looks enabled but isn‘t. We can add:

<button disabled style="opacity: 1;" aria-disabled="true">Submit</button>

Now screen readers will announce disabled correctly.

Keep visual style and accessible state aligned when feasible. ARIA augments when styles are customized.

Framework Implementations

Disabled functionality can be added to elements in frameworks like React, Angular and Vue as well:

React – Set disabled on elements like:

<button disabled={isDisabled}>Submit</button>

<input 
  disabled={formInvalid}
/>

Toggle state dynamically via props.

Angular – Use directive:

<input
  [disabled]="!formValid"
>

Bind to a component property.

Vue – Use data binding:

<button :disabled="submitting">
  Submit
</button>

Disables when submitting is true.

All frameworks support simple data binding for disabled state.

Server-side Implementation

When an initial disabled state needs to be sent from the server, add the attribute to server-rendered elements:

// Node.js Express backend

let formDisabled = true;

res.render(‘page‘, {
  formDisabled 
});
<!-- EJS template -->

<form disabled="<%= formDisabled %>">

  ... elements

</form>

This renders the form disabled from the start.

Django, Rails, PHP etc can render disabled from the backend as well.

In Summary

The disabled attribute provides an easy way to toggle element interactivity in HTML forms and interfaces. Using JavaScript, we can set this attribute dynamically based on any conditions or logic checks needed.

Combined with CSS custom styling and event handlers, we can create robust interfaces that display availability clearly and prevent mistakes or confusion. Setting disabled with JavaScript is a valuable tool for any frontend developer working on interactive sites.

Similar Posts