Testing aria-readonly

aria-readonly indicates that a widget's value cannot be edited, but the widget itself is still fully operable, focusable, selectable, and copyable, unlike a disabled control. It is the ARIA equivalent of the native readonly attribute, for use on custom widgets that don't have a native readonly state of their own.

Example 1: native readonly, for comparison

A native input's own readonly attribute needs no ARIA at all, it's mapped to the accessibility tree automatically.

Expected result: the field should be announced as read-only. It should remain focusable, and its value should be selectable and copyable, but not editable.

HTML markup
<input type="text" value="ABC-123-XYZ" readonly>

Example 2: aria-readonly on a custom widget

This is a custom text field, built from a contenteditable element with role="textbox" rather than a native input. Since it has no native readonly attribute to rely on, aria-readonly is what communicates the same state.

Confirmation number
ABC-123-XYZ

Expected result: the field should be announced as read-only, the same as Example 1. It should remain focusable.

HTML markup
<div
  role="textbox"
  aria-labelledby="custom-readonly-label"
  aria-readonly="true"
  contenteditable="false"
  tabindex="0"
>ABC-123-XYZ</div>

Readonly is not the same as disabled. A read-only field stays focusable, its value can still be selected and copied, and for native form fields, it's still submitted with the form. A disabled field is removed from the tab order, its value typically cannot be selected, and it is excluded from form submission entirely. If a value should still be readable and copyable, but not editable, readonly is usually the correct choice, not disabled.

Note for testing: confirm with your standard browser and screen reader combinations that both examples are announced as read-only, and that the distinction from a disabled field (still focusable, still selectable) actually holds in practice.