Educational guide to form state selectors
State belongs to the control and the browser
Connect attributes, properties, constraints, and user actions without simulating native states.
Mental model
Some states come from initial HTML; others change through properties or after relevant interaction.
:default / :checkedInitial does not mean current
:default preserves the choice declared by HTML; :checked reflects which radio, checkbox, or option is selected now.
:valid / :user-validImmediate or post-interaction validity
:valid and :invalid reflect constraints now; :user-valid and :user-invalid wait for browser-determined interaction.
indeterminateThere is no indeterminate attribute
For a checkbox, indeterminate is an HTMLInputElement property and must be set with JavaScript.
Availability
Compare whether a control participates in interaction and whether its value can change.
:enabled
Enabled user-interface controls.
Specificity(0, 1, 0)
:enabled
Behavior
- It depends on whether the element supports the disabled state.
- A readonly field remains enabled.
Examples
input:enabledMatches: <input name="active" />
<input name="locked" disabled />Common mistakes
- It does not mean the value is editable.
- It does not apply to every element without disabled.
:disabled
Disabled user-interface controls.
Specificity(0, 1, 0)
:disabled
Behavior
- A disabled fieldset can pass the state to its controls.
- Disabled controls normally do not participate in submission.
Examples
button:disabledMatches: <button disabled>Unavailable</button>
<button>Continue</button>Common mistakes
- It is not equivalent to aria-disabled.
- Do not use it only to change appearance.
:read-only
Elements whose content cannot be altered by the user.
Specificity(0, 1, 0)
:read-only
Behavior
- readonly keeps a control focusable and submittable.
- Its applicability is broader than the readonly attribute.
Examples
input:read-onlyMatches: <input value="Fixed" readonly />
<input value="Editable" />Common mistakes
- It is not equivalent to disabled.
- It does not prevent JavaScript from changing the value.
:read-write
Elements whose content can be altered by the user.
Specificity(0, 1, 0)
:read-write
Behavior
- It includes applicable editable fields and contenteditable hosts.
- The state depends on editability, not focus.
Examples
textarea:read-writeMatches: <textarea>Editable</textarea>
<textarea readonly>Fixed</textarea>Common mistakes
- It does not mean the control is :valid.
- A disabled input is not editable.
:placeholder-shown
Fields currently displaying their placeholder.
Specificity(0, 1, 0)
:placeholder-shown
Behavior
- It stops matching when the control has a value.
- It observes field state, not the text pseudo-element.
Examples
input:placeholder-shownMatches: <input placeholder="Name" />
<input placeholder="Name" value="Ada" />Common mistakes
- It is not equivalent to an empty field for every control.
- Do not confuse it with ::placeholder.
Support and compatibility
See the dedicated Baseline status for :placeholder-shown.
Choices
Distinguish default, selected, and indeterminate values.
:default
Options or buttons representing the initial choice.
Specificity(0, 1, 0)
:default
Behavior
- It may keep matching after the current selection changes.
- It derives from the default state declared by HTML.
Examples
input:defaultMatches: <input type="radio" name="plan" checked />
<input type="radio" name="plan" />Common mistakes
- It is not equivalent to :checked.
- It does not select every recommended value.
Support and compatibility
See the dedicated Baseline status for :default.
:checked
Currently selected radios, checkboxes, and options.
Specificity(0, 1, 0)
:checked
Behavior
- It changes through real user interaction.
- For radios, checking one unchecks another in the group.
Examples
input:checkedMatches: <input type="checkbox" checked />
<input type="checkbox" />Common mistakes
- It does not necessarily preserve the initial choice.
- It does not cover mixed state.
:indeterminate
Controls in neither an affirmative nor negative state.
Specificity(0, 1, 0)
:indeterminate
Behavior
- For checkboxes it is activated through the indeterminate property.
- It can also apply to radio groups without a choice and progress without value.
Examples
input:indeterminateMatches: <input type="checkbox" data-indeterminate />
<script>checkbox.indeterminate = true;</script>Common mistakes
- There is no indeterminate HTML attribute.
- It is not equivalent to unchecked.
Support and compatibility
See the Baseline status and applicability of :indeterminate.
Validation
Observe requirements and validity before and after interaction.
:required
Validatable controls that require a value.
Specificity(0, 1, 0)
:required
Behavior
- It comes from the required attribute when applicable.
- It can combine with validity states.
Examples
input:requiredMatches: <input required />
<input />Common mistakes
- Not every control type supports required.
- A visual asterisk does not create the state.
:optional
Validatable controls that are not required.
Specificity(0, 1, 0)
:optional
Behavior
- It is the opposite of :required among applicable controls.
- An empty optional field is usually valid.
Examples
input:optional<input required />
Matches: <input />Common mistakes
- It does not match every element without required.
- Optional does not mean irrelevant.
:valid
Controls satisfying their native constraints.
Specificity(0, 1, 0)
:valid
Behavior
- It may match from initial page load.
- It updates while the value changes.
Examples
input:validMatches: <input type="email" value="ada@example.com" required />
<input type="email" value="ada@" required />Common mistakes
- It does not wait for the user to leave the field.
- Native validity does not replace every business rule.
:invalid
Controls failing a native constraint.
Specificity(0, 1, 0)
:invalid
Behavior
- It may match before any interaction.
- A form may also be invalid when it contains an invalid control.
Examples
input:invalid<input type="email" value="ada@example.com" required />
Matches: <input type="email" value="ada@" required />Common mistakes
- Avoid aggressive error feedback from this initial state alone.
- It is not equivalent to aria-invalid.
:user-valid
Valid controls after relevant user interaction.
Specificity(0, 1, 0)
:user-valid
Behavior
- The browser decides when the user committed the value.
- It stops matching if the value becomes invalid again.
Examples
input:user-validMatches: <input type="email" value="ada@example.com" required />
<!-- matches after relevant user interaction -->Common mistakes
- It is not an application-controlled touched class.
- It does not replace accessible feedback when needed.
Support and compatibility
It is widely available; activation timing belongs to the browser.
:user-invalid
Invalid controls after relevant user interaction.
Specificity(0, 1, 0)
:user-invalid
Behavior
- A submission attempt can activate it and focus the first error.
- It can delay the visual signal compared with :invalid.
Examples
input:user-invalidMatches: <input type="email" value="ada@" required />
<!-- matches after relevant user interaction -->Common mistakes
- Do not force it on initial load.
- CSS alone does not synchronize aria-invalid.
Support and compatibility
It is widely available; pair styling with accessible feedback.
Ranges
Compare the same min and max with values inside and outside the interval.
:in-range
Controls with a value between min and max.
Specificity(0, 1, 0)
:in-range
Behavior
- It only applies to controls supporting range limits.
- The value must still satisfy other constraints.
Examples
input:in-rangeMatches: <input type="number" min="1" max="10" value="5" />
<input type="number" min="1" max="10" value="14" />Common mistakes
- It does not compare text lengths.
- Being in range does not guarantee complete validity.
:out-of-range
Controls with a value below min or above max.
Specificity(0, 1, 0)
:out-of-range
Behavior
- It updates when the number or date changes.
- It identifies one specific cause of invalidity.
Examples
input:out-of-range<input type="number" min="1" max="10" value="5" />
Matches: <input type="number" min="1" max="10" value="14" />Common mistakes
- A malformed value is not necessarily out-of-range.
- It does not apply without relevant limits.