LEARNING OBJECTIVES ⌵
- Differentiate between
readonlyanddisabledacross all 8 architectural behavior dimensions. - Understand the form submission lifecycle: why
disabledfields are omitted fromFormDatawhilereadonlyfields are transmitted. - Recognize which HTML input types support
readonlyversus which silently ignore it per the WHATWG spec. - Style locked form states using the
:disabled,:enabled,:read-only, and:read-writeCSS pseudo-classes.
📖 The Mental Model & Story (Intuitive Foundation)
Imagine walking into a history museum:
- The Museum Display Case (
readonly): Inside a clear glass display case sits a pristine historical manuscript. You can walk right up to the glass, read every word, shine your flashlight on it, take a photo with your phone, and copy the text down into your notebook. However, you cannot reach in with a pen and edit the ink. The document remains a valid, active part of the exhibit. - The Out-of-Order Vending Machine (
disabled): In the hallway, a vending machine has a large yellow tape strip across it reading "Out of Service". You cannot insert coins, pressing the buttons does nothing, the machine lights are off, and the inventory system completely ignores it during daily transactions.
+------------------------------------+ +------------------------------------+
| READONLY (Museum Glass) | | DISABLED (Out of Order) |
+------------------------------------+ +------------------------------------+
| - Focusable via Keyboard (Tab) | | - Skipped by Keyboard (No Tab) |
| - Text can be highlighted & copied | | - Text cannot be selected/copied |
| - Submits to server in FormData | | - OMITTED completely from FormData |
| - Participates in validation | | - Skipped by validation engine |
+------------------------------------+ +------------------------------------+
Choosing between readonly and disabled is a crucial architectural decision that impacts keyboard navigation, screen readers, and backend payload construction.
Technical Deep Dive & Specifications
The Comprehensive 8-Dimension Access Control Matrix
| Dimension | readonly State |
disabled State |
|---|---|---|
| 1. Primary Purpose | Value is locked/immutable, but remains relevant data | Control is inactive/irrelevant in current UI state |
2. Keyboard Focus (Tab) |
✅ Focusable (Users can Tab to it) | ❌ Non-Focusable (Browser skips it) |
| 3. Text Selection & Copy | ✅ Yes (Users can highlight & copy text) | ❌ No / Limited (Treated as inactive text) |
4. Form Submission (FormData) |
✅ Submitted (Name & value serialized) | ❌ Omitted (Ignored during submission) |
| 5. DOM Event Firing | ✅ Fires focus, blur, click, keydown |
❌ Suppresses mouse & keyboard events |
| 6. Constraint Validation | ✅ Evaluated by constraint validation | ❌ Barred from constraint validation |
| 7. Screen Reader Feedback | Read as "Read-only, edit text" | Read as "Dimmed / Disabled" |
| 8. Applicable Input Types | text, search, url, tel, email, password, date, number, <textarea> |
ALL form controls without exception |
EVALUATING LOCKED FORM FIELDS
|
Does the server need this field on submit?
/ \
Yes / \ No
/ \
v v
Should user be able to Use disabled
read, tab to, and copy it? (Omitted from submission)
/ \
Yes / \ No (Hidden token)
v v
Use readonly Use <input type="hidden">
(Submitted) (Submitted invisibly)
The Input Type Applicability Trap
A common trap is attempting to put readonly on checkboxes, radio buttons, or file pickers.
[!WARNING] According to the WHATWG specification, the
readonlyattribute has no effect ontype="checkbox",type="radio",type="file",type="range",type="color",type="button", or<select>!A checkbox with
readonlycan still be toggled by the user in standard browsers! To lock a checkbox or select menu, you must usedisabled(or prevent toggle via JavaScript).
CSS Styling: :read-only vs :disabled
Modern CSS provides clean pseudo-classes to style these states semantically:
/* Styling disabled inputs */
input:disabled {
background-color: #f1f5f9;
color: #94a3b8;
border-color: #cbd5e1;
cursor: not-allowed;
}
/* Styling readonly inputs */
input:read-only {
background-color: #f8fafc;
color: #334155;
border-color: #e2e8f0;
cursor: default;
}
/* Target standard editable inputs */
input:read-write {
background-color: #ffffff;
}
💻 Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Line 37 (
<input ... value="USR-99482-TX" readonly>): Marks the account identifier as non-editable while keeping it focusable via Tab and copyable to the clipboard. - Line 43 (
<input ... value="Inactive Data" disabled>): Completely disables the control, barring it from keyboard navigation and event handling. - Line 57–67 (
new FormData(form)): Inspects the browser's native submission dataset. Notice thatreadonly_valis included in the payload, whereasdisabled_valis excluded.
Expected Browser Render Output
Access Control Comparison
1. Editable Field
[ You can edit me ]
2. Readonly Field (readonly)
[ USR-99482-TX ]
3. Disabled Field (disabled)
[ Inactive Data ]
[ Inspect Form Payload ]
Serialized FormData Payload (Submitted to Server):
✓ editable_val = "You can edit me"
✓ readonly_val = "USR-99482-TX"
Notice that "disabled_val" was completely dropped from serialization!🏋️ Hands-On Exercise
🎯 The Challenge: Build a Customer Account Editor
Instructions:
- Create a user profile form with three fields:
- Account UUID: Must be locked so the user cannot edit it, but the user must be able to copy the UUID to clipboard, and it must be submitted with the form.
- Display Name: Fully editable text field.
- Save Changes Button: Initially
disabled.
- When the user changes their Display Name (making it different from initial value), dynamically enable the Save button (
saveBtn.disabled = false). - If the user clears their edit or restores the original name, disable the Save button again.
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Disabling Fields Expecting Them to Submit: Disabling an input (
disabled) prevents its name and value from being sent to the backend. If you want a user to see locked data that still submits, usereadonly. - Using
readonlyon Checkboxes or Radios: As per the HTML specification,readonlydoes not apply to<input type="checkbox">or<select>. Users can still toggle them. Usedisabled(or JavaScriptpreventDefault()) instead. - Making Everything
disabledand Destroying Keyboard Access: Disabled fields cannot receive focus via the Tab key. If a user needs to review or copy locked reference numbers (like order tracking IDs or license keys), usereadonlyso keyboard and screen reader users can navigate to them.
💡 Pro Tips
- Backend Validation of Locked Fields: Never trust incoming
readonlyvalues on the server. A malicious user can open DevTools, remove thereadonlyattribute in two seconds, and submit arbitrary payload strings. Always verify permissions on the server endpoint. - Semantic CSS with
:read-only: Target inputs with:read-onlyrather thaninput[readonly]in your stylesheets so you automatically catch non-editable inputs across different browser rendering engines.
📌 Key Takeaways
readonlylocks content while maintaining keyboard focus, clipboard copying, andFormDatasubmission.disableddeactivates the control, removing it from tab navigation, suppressing events, and omitting it fromFormData.readonlyapplies only to text-like inputs and<textarea>; it is ignored by checkboxes, radios, range sliders, and select menus.- Use
:read-onlyand:read-writeto create clean, semantic styling without brittle attribute selectors. - Client-side locked attributes are UX conveniences, not security boundaries; always validate on the server.
- --