It’s weird to me that after I urged everyone not to disable form controls, a bunch of them decided that making them read-only was somehow better. But here we are.
HTML
The readonly
attribute is only allowed on text fields (<input>
and <textarea>
).
The WHATWG HTML specification for devs argues that making other controls (buttons, checkboxen) read-only has no useful distinction
from being disabled. Other than being focusable, of course.
Focus
Read-only fields and controls are in the tab order. Without an obvious cue, it’s unclear to users why they cannot edit the field. However, with an apparent style it’s still unclear why they cannot edit the field.
Of course, there are some browser inconsistencies. Firefox (132 as of this writing) on Windows and Android won’t let a read-only date, date-time, or time input take focus. It’s functionally treated as disabled, and has the sad gray disabled text as well.
Styles
There is no default style for read-only text fields. The browsers assign none and CSS has never offered one (eg: CSS Basic User Interface Module). It’s up to you to come up with one and have it make sense to users. CSS Selectors Level 4 Working Draft offers a :read-only
pseudo-class selector. Previously authors had to (may still have to) rely on an attribute selector using [readonly]
. Remember that WCAG contrast requirements apply to read-only controls, so you can’t get away with sad gray-on-gray action.
Until Material Design launched its poorly-researched field styles, I had found that a simple bottom border was not awful, but really only for trained users. I touch on this in my post Under-Engineered Text Boxen.
As noted above, Firefox on Windows and Android sets the values of date, date-time, and time inputs in sad gray text. I’ve done no investigation into why.
Chrome on Android, not to be outdone by Firefox with the sad gray text, also sets the values for date, date-time, and time inputs in grayed text, but goes further by doing the same to the month and week inputs. They are focusable, however.
Editable?
Because HTML read-only text fields participate in form submission, it’s easy to subvert them using browser devtools. More than once I have gotten around a problematic form (and at least one login) by removing readonly
with devtools and letting my autocomplete or password manager handle the rest. This presumes the developer honors HTML forms and hasn’t wired up some bloated JavaScript golem to do the work.
ARIA
For the case of the <div>
roled-up with ARIA to become a widget or problematic form control aria-readonly
functionally does nothing. Except maybe (but not always) tell a screen reader user the field is read-only. The author still has to script it disallow input (or not script it to be functional, I guess?).
However, unlike HTML, aria-readonly
is allowed on the roles checkbox
, combobox
, grid
, gridcell
, listbox
, radiogroup
, slider
, spinbutton
, and textbox
. This doesn’t mean users will understand it in those contexts, so it’s not an invitation to read-only your unnecessary grids or confounding listboxen. This also doesn’t mean it will be exposed to screen reader users.
Screen Readers
With no default nor industry-wide visual design language, the only users who consistently stand a reasonable chance of knowing a control is read-only (on any site) are screen reader users. Because read-only is a property (readonly
and aria-readonly
), it gets exposed. Sometimes.
JAWS
In JAWS 2024 with Chrome 131 the text, email, number, password, search, telephone, and URL inputs announce as read-only along with the textarea. Note that this is a sub-set of fields that allow readonly
.
The HTML text input and textarea announce as read-only with aria-readonly="true"
.
Of the ARIA widgets, only the checkbox, spinbutton, and textbox roles report their aria-readonly="true"
, which is also a sub-set of roles that allow aria-readonly
.
NVDA
In NVDA 2024.4 with Firefox 132 the text, email, month, password, search, telephone, URL, and week inputs announce as read-only along with the textarea. Note that this is a sub-set of fields that allow readonly
. Also note the date, date-time, and time inputs still do not get focus.
The HTML text input and textarea do not announce as read-only with aria-readonly="true"
.
Of the ARIA widgets, only the checkbox and textbox roles report their aria-readonly="true"
, which is also a sub-set of roles that allow aria-readonly
.
VoiceOver / macOS
In VoiceOver on macOS 15.1.1 with Safari 18.1.1 the text, email, month, number, search, telephone, URL, and week inputs announce as selectable along with the textarea. Note VoiceOver does not say “read-only” and it only announces “selectable” after the field value, selectedness, name, field type, and validity.
The HTML text input and textarea do not announce as read-only with aria-readonly="true"
.
Of the ARIA widgets, only the textbox role reported its aria-readonly="true"
, which is also a sub-set of roles that allow aria-readonly
. It announced it by saying I was on selectable text.
Note that this deviates from VoiceOver / Safari on iPadOS.
TalkBack
Using TalkBack 15.1 with Chrome 131 the text, email, number, password, search, telephone, and URL inputs announce as disabled along with the textarea. Note that this is a sub-set of fields that allow readonly
. Also note that TalkBack announced the fields as “disabled,” not “read-only.”
The HTML text input and textarea announce as disabled with aria-readonly="true"
. Which means they also announce the wrong state.
Of the ARIA widgets, the checkbox, combobox, listbox, radiogroup, slider, spinbutton, and textbox roles report their aria-readonly="true"
as “disabled”. TalkBack / Chrome honors all the roles I tested, but does so by reporting the wrong state.
VoiceOver / iPadOS
Using VoiceOver on iPadOS 18.1.1 with Safari the text, email, number, password, search, telephone, and URL inputs announce as read-only along with the textarea. Note that this is a sub-set of fields that allow readonly
.
The HTML text input and textarea do not announce as read-only with aria-readonly="true"
.
Of the ARIA widgets, only the textbox role reported its aria-readonly="true"
, which is also a sub-set of roles that allow aria-readonly
.
Note that this deviates from VoiceOver / Safari on macOS.
Demo
I made a CodePen demo (and a debug version). It only sets basic text styles and focus styles for the ARIA widgets.
The ARIA widgets are non-functional. They exist solely to test exposure to the accessibility APIs, so they have the minimum properties, states, and values to be recognized.
The HTML Nu Checker (HTML validator) is linked so you can see the errors the validator offers. They give more detail than the HTML spec does on which input types can be read-only.
See the Pen Untitled by Adrian Roselli (@aardrian) on CodePen.
Verdict
In short, if you think read-only controls are a hassle to style and script and properly expose, imagine how much of a hassle they are to use. Probably avoid them.