The :read-only pseudo-class matches elements the user cannot edit. On text fields that usually means the HTML readonly attribute. It is the complement of :read-write — equivalent to :not(:read-write).
Common use: style confirmation fields (name, address) so they look like fixed text while still submitting with the form.
Baseline — widely available.
Supported across modern browsers (MDN: widely available since July 2020). Prefer scoped selectors such as input:read-only — a bare :read-only also matches many non-form elements.
Same pattern as MDN’s shipping-details review form.
Edge Cases & Pitfalls
Scope carefully — :read-only is broader than “has readonly=”.
scope
Matches more than form fields
Buttons, selects, and normal paragraphs are not :read-write, so they match :read-only. Prefer input:read-only / textarea:read-only.
vs disabled
Not the same as :disabled
Read-only can be focused and is submitted. Disabled is skipped on submit. Use :disabled when the control must be fully inactive.
a11y
Keep labels and contrast
Muted styles still need readable contrast. Pair with a clear label so users know the value is intentional, not broken.
contenteditable
Works beyond forms
A plain <p> matches :read-only; contenteditable content matches :read-write. Useful for rich-text demos — unexpected if you style globally.
Compatibility
Browser Support
:read-only is a browser CSS pseudo-class. Node.js, Deno, and Bun do not apply it.
✓ Baseline · Widely available
:read-only
Widely available across modern browsers (MDN notes broad support from mid-2020). Pair with :read-write for form UX. Internet Explorer had incomplete / prefixed support historically.
97%Widely available
Google ChromeSupported
Full support
Mozilla FirefoxSupported
Full support
Apple SafariSupported
Full support
Microsoft EdgeSupported
Full support
OperaSupported
Full support
Samsung InternetSupported
Full support
Internet ExplorerPartial
Legacy / incomplete
:read-onlyBaseline · Widely available
Bottom line: Safe for modern form styling. Scope to input/textarea. This is not a JavaScript runtime API.
Remember
Key Takeaways
Role: style elements the user cannot edit (often readonly fields).
vs disabled: read-only still focuses and submits.
Start simple:input:read-only { background: …; }.
Scope selectors — bare :read-only hits many non-form nodes.
One line::read-only paints locked (but submittable) fields — mute them, don’t confuse them with disabled.
Frequently Asked Questions
It matches elements the user cannot edit. For inputs and textareas that usually means the HTML readonly attribute. It also matches anything that is not :read-write.
A read-only control can still be focused and its value is submitted with the form. A disabled control is not editable, is skipped on submit, and often looks fully inactive.
Yes. Elements where the readonly attribute has no effect (buttons, most non-form content) are also matched, because they are not :read-write. Scope your selector (e.g. input:read-only) when you only want form fields.
Often yes. Style confirmation fields with :read-only and editable fields with :read-write for a clear contrast in the same form.
No. It is a browser CSS pseudo-class. Node.js, Deno, and Bun do not apply it.