Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Prevents interaction with form controls. Disabled elements are skipped by tab order, excluded from form submission, and grayed out by default.
The disabled attribute prevents all interaction with a form control. A disabled element cannot be focused, clicked, or edited. It is skipped by keyboard tab order and excluded from form submission data.
This is the strongest way to deactivate a form control. If you need the value to still submit with the form, use readonly instead.
Applies to: <input>, <select>, <textarea>, <button>, <fieldset>
| State | Focusable | Editable | Submitted | Tab Order |
|---|---|---|---|---|
disabled | No | No | No | Skipped |
readonly | Yes | No | Yes | Included |
inert | No | No | Yes (if in form) | Skipped |
| (normal) | Yes | Yes | Yes | Included |
<form class="stacked"> <label for="email">Email</label> <input type="email" id="email" value="[email protected]" disabled /> <label for="plan">Plan</label> <select id="plan" disabled> <option>Free</option> <option selected>Pro</option> </select> <button type="submit" disabled>Submit</button></form>
Adding disabled to a <fieldset> disables every form control inside it, regardless of nesting depth. This is the cleanest way to disable an entire section of a form with a single attribute.
<form class="stacked"> <fieldset disabled> <legend>Billing Address</legend> <label for="street">Street</label> <input type="text" id="street" value="123 Main St" /> <label for="city">City</label> <input type="text" id="city" value="Portland" /> <label for="state">State</label> <select id="state"> <option selected>Oregon</option> </select> </fieldset> <button type="submit">Continue</button></form>
The <legend> element inside a disabled fieldset remains interactive. Any form controls inside the <legend> are not disabled by the fieldset cascade. This is intentional — the legend is considered a label, not a form control.
Disabled controls are excluded from FormData entirely. Their name/value pairs are not sent to the server. This catches developers off guard when they disable a field to make it "read-only" and then wonder why the value is missing.
<form class="stacked"> <label for="username">Username</label> <input type="text" id="username" name="username" value="jdoe" disabled /> <label for="role">Role</label> <input type="text" id="role" name="role" value="Admin" /> <button type="submit">Save</button></form><!-- On submit, only "role=Admin" is sent. "username" is excluded. -->
If you need the value submitted but non-editable, use readonly or pair the disabled field with a <input type="hidden"> that carries the value.
Browsers apply a default dimmed appearance to disabled controls. Use the :disabled and :enabled pseudo-classes for custom styling.
/* Default browser styling dims disabled controls */input:disabled,select:disabled,textarea:disabled,button:disabled { opacity: 0.5; cursor: not-allowed;} /* Style the enabled state explicitly */button:enabled { cursor: pointer;} /* Target inputs within a disabled fieldset */fieldset:disabled input { background: var(--color-surface-raised); border-color: var(--color-border);}
A common pattern is disabling the submit button while an async request is in flight. This prevents double-submission.
const form = document.querySelector('#payment-form');const submitBtn = form.querySelector('button[type="submit"]'); // Disable while processingform.addEventListener('submit', (e) => { e.preventDefault(); submitBtn.disabled = true; submitBtn.textContent = 'Processing...'; fetch('/api/pay', { method: 'POST', body: new FormData(form) }) .then(() => { submitBtn.textContent = 'Done'; }) .catch(() => { submitBtn.disabled = false; submitBtn.textContent = 'Retry'; });});
inert or readonly over disabled, since disabled controls may be skipped entirely by assistive technology.disabled does not work on <a> elements. Links have no disabled state — use aria-disabled="true" with JavaScript to prevent navigation, or replace the link with a <span>.disabled does not work on <div> or other non-form elements. Use inert for that.:disabled styles with high-specificity selectors. Check your cascade if custom disabled styles are not applying.disabled attribute is a boolean attribute. Writing disabled="false" still disables the element — the attribute's presence alone activates it. Remove the attribute entirely to re-enable.readonly — non-editable but still focusable and submittedhidden / inert — hide or deactivate non-form content<fieldset> — group and disable controls together<button> element reference