Practical guide
Disabled vs Read-Only Controls: Which Text Needs Contrast?
Read-only information is not automatically inactive. Distinguish actual HTML behavior from gray styling, apply contrast exceptions narrowly, and keep reasons for unavailable actions readable.
Decide what the control does before styling it gray
Read-only and disabled describe different behavior. A read-only field is not automatically covered by the inactive-control contrast exception. The HTML specification says a read-only control can still function, while a disabled control generally does not function as a control until enabled.
Start with the component’s actual job. Is a value still information the reader needs? Is a control unavailable for interaction? Or has the designer merely used gray to make something look secondary? A gray appearance does not answer those questions.
WCAG’s text and non-text contrast criteria have specific exceptions for inactive components. Apply them to the relevant actual inactive component, not to every pale word near it or every field the user cannot edit. Keep information and instructions readable where those exceptions do not apply.
HTML separates editing from disabling
For applicable text inputs, readonly is a Boolean attribute controlling whether the user can edit the value. When it is specified, the input is not mutable. The specification nevertheless distinguishes this from disabling because a read-only control can still function.
readonly is not a general-purpose state for every widget. The input specification explains that it applies to text controls rather than checkboxes and buttons, where the same editing distinction is not useful.
disabled concerns unavailable form controls and has defined effects on interaction. The form-control specification, for example, requires a disabled control to suppress click events queued from user interaction, and excludes it from constraint validation.
Do not turn those statements into a universal claim about copying or selecting text in every disabled control. The HTML specification explicitly leaves other disabled-user-interaction behavior, including text selection and copying, undefined by that standard. Inspect the actual platform when that behavior matters to the reader.
Four similar-looking screens can require different decisions
| Situation | What to establish | Text decision |
|---|---|---|
| A booking reference is displayed in a read-only text field. | The value remains useful information; editing alone is prevented. | Do not claim an inactive exemption merely from readonly. Keep the value readable. |
| A submit button is actually disabled until required input is supplied. | It is an inactive component in the current state. | The relevant inactive-component exception can apply; optional stronger styling may still help usability. |
| A normal link is gray but still operable. | It remains an active link. | Gray styling supplies no inactive exemption. |
| A paragraph explains why the submit action is unavailable. | The paragraph is information beside the button, not the inactive button itself. | Check its ordinary text/background pair. |
These scenarios are invented teaching examples. They do not report the behavior of a particular product. Their purpose is to prevent one visual token called “disabled gray” from being applied to unrelated text jobs.
Keep a fixed value readable on a soft booking surface
Suppose a booking summary uses cream #F6F1E7. Sage #A3B18A text on that cream gives 2.024777:1. Calling the reference “read-only” does not improve that ratio or establish an exemption for useful information.
An original optional text extension, deep olive #384332, gives 9.248358:1 on the same cream. It is an added UI text choice, not one of the existing five swatches in the sage palette. Keep that addition explicit in the usage record.
| Text / surface | Ratio | Application |
|---|---|---|
| Sage #A3B18A / cream #F6F1E7 | 2.024777:1 | Below ordinary-text contrast; use sage for a suitable decorative role instead. |
| Deep olive #384332 / cream #F6F1E7 | 9.248358:1 | Meets 4.5:1 for the fixed reference and explanation in this example. |
A border, lock icon or visible “Cannot edit here” note can explain a fixed value without making the words faint. If you add an icon, its meaning and relevant contrast need their own assessment; the passing text pair does not verify the icon.
Explain an unavailable action beside the control
For a genuinely unavailable action, separate the button appearance from the reason. “Choose a pickup time before continuing” is useful information. Put it where the reader can find it, keep it readable and make it consistent with the actual form state.
The inactive-component exception is a minimum-requirement boundary, not a recommendation to make disabled text as faint as possible. You can choose clearer disabled styling while preserving the distinction from an available action. Test the result in the real interface rather than relying on a universal gray.
When the action becomes available, recalculate any text and needed component cues in the enabled state. A style that was exempt while inactive does not carry that exemption into an active button.
Do not rely on color alone to communicate the reason or a status the reader must understand. Visible wording or another suitable visible cue should carry the meaning. Keyboard behavior and accessible states are additional implementation work, beyond this color decision.
Record the exception and the remaining checks
- Identify the actual element, state and user action.
- Confirm whether it is inactive or merely non-editable.
- List information still needed: fixed values, field names, hints and explanatory text.
- Record which specific component uses an exception and why.
- Check active text and required visual cues in every state that becomes available.
- Inspect keyboard navigation, phone wrapping and actual behavior before marking implementation complete.
A useful record says “This button is disabled while the required choice is missing; the adjacent explanation remains ordinary readable text.” It should not say “All gray text is exempt.”
Use the placeholder and hint guide for active input text, and wellness brand colors for the broader booking application. This page owns the disabled-versus-read-only boundary; it does not replace a complete form implementation review.
Sources and further reading
- Understanding Success Criterion 1.4.3: Contrast (Minimum) | WAI | W3CInactive-component text exception; ordinary text and placeholders remain within text contrast when applicable.
- Understanding Success Criterion 1.4.11: Non-text Contrast | WAI | W3CInactive controls are unavailable for user interaction; exception concerns actual inactive components.
- HTML StandardInput §4.10.5.3.3: readonly stops editing but controls can still function; only applicable text controls; copying/selecting disabled text is not defined universally.
- HTML StandardForm-control infrastructure §4.10.19.5: actual disabled-control behavior, click suppression and constraint-validation exclusion.
- Understanding Success Criterion 1.4.1: Use of Color | WAI | W3CProvide visible meaning beyond hue for status/instructions.