Buttons are a crucial user interface element in web development. At times, you may need to disable a button to restrict user access to certain actions. For example, disabling the submit button until the user fills out all required form fields.
CSS provides several powerful properties to disable buttons and indicate their inactive state. In this comprehensive guide, we‘ll explore common techniques for disabling buttons with CSS.
HTML Button Basics
First, let‘s review how to create a basic button in HTML:
<button type="button">Click Me</button>
The <button> element defines a clickable button. The type="button" attribute explicitly defines this as a button for clicking versus a submit button.
By default, this will appear as a standard clickable button:

Now let‘s see how to disable this button with CSS.
Disabling Pointer Interactions
The primary way to disable a button is by removing pointer interactions. This makes the button unclickable, preventing any actions.
The pointer-events CSS property controls whether an element can be the target of mouse/touch events. Setting it to none disables clicking:
button {
pointer-events: none;
}
The button will appear inactive but visually unchanged:

This method fully disables pointer interactions. However, this alone doesn‘t indicate that the button is inactive. Next we‘ll add visual styles.
Changing Visual Styles
In addition to disabling pointer events, visual styling helps indicate a button‘s inactive state.
Common styling approaches include:
- Lowering opacity – Makes the button appear faded
- Changing background colors – Using darker or gray colors
- Text styling changes – Lighter or gray text colors
Some examples:
/* Faded styling */
button {
opacity: 0.5;
pointer-events: none;
}
/* Gray colors */
button {
background-color: lightgray;
color: gray;
pointer-events: none;
}
These additional styles help communicate that the buttons can‘t be clicked:

Styling provides a purely visual indicator. Somewhat confusingly, there is also a native disabled attribute which visually indicates and disables buttons.
The disabled Attribute
Buttons have a built-in Boolean disabled attribute that both disables and visually indicates an inactive state:
<button disabled>Disabled Button</button>
A disabled button appears inactive, changes opacity, and blocks interactions:

However, there are some downsides:
- Styling limited to the browser‘s default disabled appearance
- No way to conditionally enable/disable with JavaScript
- Not as well supported on some other elements like
<div>
As a result, using pointer and visual CSS styles is often more flexible.
Disabling Form Submit Buttons
A common use case for disabling buttons is to prevent submitting a form when invalid.
For example, we want to disable the Submit button until all required fields are filled out:
<form>
<input type="text" required>
<button type="submit">Submit</button>
</form>
To disable the button by default:
button[type="submit"] {
/* Styling */
opacity: 0.5;
/* Disable pointer */
pointer-events: none;
}
Then re-enable with JavaScript when valid:
// When form inputs valid
document.querySelector(‘button[type="submit"]‘)
.removeAttribute(‘style‘);
This gracefully degrades if the user has JavaScript disabled too.
Cursor Styles
Changing the mouse cursor provides another visual indicator.
The cursor CSS property controls the mouse cursor displayed when hovering:
button[disabled] {
cursor: not-allowed;
}
This sets the cursor to a "not allowed" indicator:

Some other disabled cursors include no-drop, wait, or progress.
Creating a Reusable .disabled Class
We can create a reusable .disabled class with these disabling styles:
.disabled {
opacity: 0.5;
pointer-events: none;
cursor: not-allowed;
}
Then apply it anywhere needed:
<button class="disabled">Disabled Button</button>
This centralizes styles to easily disable various elements.
We can toggle this dynamically by adding/removing this class with JavaScript.
Disabling Non-Button Elements
While we used a <button> for examples, these styles also apply to other elements like <div>, <a>, <input> and more.
For example, to visually disable links:
a.disabled {
opacity: 0.5;
pointer-events: none;
text-decoration: none;
color: gray;
}
Custom Styling and Icons
CSS provides endless options for custom styling disabled buttons:
- Overlays like stripes or color tints
- Icon indicators
- Animations like flashing
- Outline or border changes
Some examples:

We can also use SVG icons to indicate state. For example:
<!-- Disabled icon -->
<svg class="disabled-icon">
<use href="#disabled"/>
</svg>
<button>
<svg class="disabled-icon">
<use href="#disabled"/>
</svg>
Disabled Button
</button>
And toggle based on the .disabled class:
.disabled .disabled-icon {
display: inline-block;
}
This method keeps the icon and text label together within the button.
The sky‘s the limit for crafting disabled styles to suit your interface.
Specific Use Cases
Disabling buttons helps guide users in many contexts:
Shopping cart – Disable adding items to cart if quantity is 0 or item out of stock. Provides feedback on why action blocked.
Multi-step forms – Disable submit if required fields from an early step not completed yet. Prevent incorrect form flow.
Preview screens – Disable editing and export buttons during print preview. Avoid changing document during preview.
Loading states – Temporarily disabling buttons prevents repeat clicks while page loads. Better than hiding buttons entirely.
Think through workflows in your application to identity where disabling actions could improve UI behavior.
Comparison of Techniques
There are a few primary ways we‘ve disabled buttons with CSS:
pointer-events – Fully disables interactivity. Requires additional visual styling.
opacity – Visual-only indicator. Still clickable and focuses element.
disabled attribute – Native browser feature. Limited style control.
Removing class – Toggles state by adding/removing a .disabled class.
So which should you use?
The best approach combines pointer-events to disable clicks with visual opacity styles. Conditionally toggle these using a .disabled class and JavaScript.
This keeps buttons non-interactive while also clearly indicating the inactive state. The .disabled class centralizes styles for reusability and toggling logic.
Browser Support
The pointer-events property has excellent support in all modern browsers:

- Edge: 14+
- Firefox: 4.0+
- Chrome: 2+
- Safari: 6.1+
- Opera: 15+
Reaching over 95% of global usage. Complete support stretches back to IE 11 and Firefox 4.
Cursor styles have similar broad browser support. Visually disabled styling like opacity works across all browsers as well.
The disabled attribute itself is supported in all browsers too.
Thus most techniques for disabling buttons are viable for the vast majority of users. Always check CanIUse.com for precise details on any newer or less common CSS properties.
Accessibility Considerations
When disabling interactive elements, be mindful that:
- Screen reader users rely on visual context clues
- Disabled forms can be confusing if not designed clearly
- Use labels and ARIA attributes for added meaning
To improve accessibility:
- Clarify intent – "Submit Button Disabled"
- Announce state changes – "Button is now disabled"
- Follow keyboard focusability best practices
Testing with assistive devices helps ensure disabled interfaces aren‘t confusing.
New & Experimental Features
CSS is gaining new pseudo-classes to style disabled states independently from the attribute itself:
:disabled – Targets disabled elements
:enabled – Targets enabled elements
This helps consolidate disabled styles without toggling the actual disabled attribute:
/* Style but don‘t toggle */
button:disabled {
opacity: 0.5;
pointer-events: none;
}
Support is still emerging across browsers. Keep an eye out for wider adoption.
Additionally, the :focus-visible pseudo-class lets us style only keyboard-focused states. Useful for buttons toggled via JavaScript.
Support is similar to :disabled – requires prefixes in Webkit browsers. Future functionality to watch.
In Conclusion
Disabling buttons while retaining their appearance is crucial for guiding users.
The pointer-events property provides the key to preventing clicks and interactions. Visual style changes like opacity and cursor help indicate inactive state.
Options like the native disabled attribute or reusable .disabled classes simplify applying disabled styles.
Combining native HTML attributes, CSS pointer and visual styles gives immense flexibility. With some JavaScript toggling, it‘s simple to disable buttons under any conditions required.
There are also creative possibilities like custom graphic styles, animations, and SVG icons powered by CSS.
Now go disable some buttons! Feel free to reach out with any other disabling techniques you discover.


