0Support

Form states

Compare availability, editability, choices, requirements, validity, and ranges through real native-control states.

Read the guide

Ask AI

Form states

Response generated with openai/gpt-5.4-nano. AI can make mistakes. Always review the result.
Current selector.demo-control:enabled
Support unknownSpecificity—

Preparing the scenario and its results…

Matches controls that allow interaction and are not disabled.

Selector preview

HTML
<form class="form-state-demo" aria-label="Control availability and editability" novalidate>
  <label>Name
    <input class="demo-control text-control" name="name" placeholder="Enter your name" />
  </label>
  <label>Read-only identifier
    <input class="demo-control text-control" name="identifier" value="PROFILE-01" readonly />
  </label>
  <label>Notes
    <textarea class="demo-control text-control" name="notes" placeholder="Add a note"></textarea>
  </label>
  <button class="demo-control" type="button" disabled>Check form</button>
</form>
CSS
.demo-control:enabled {
  outline: 3px solid #f97316;
  outline-offset: 3px;
  background-color: color-mix(in oklch, #f97316 16%, transparent);
}
JS
// This scenario does not require JavaScript.

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.

Back to playground

Mental model

Some states come from initial HTML; others change through properties or after relevant interaction.

:default / :checked

Initial does not mean current

:default preserves the choice declared by HTML; :checked reflects which radio, checkbox, or option is selected now.

:valid / :user-valid

Immediate or post-interaction validity

:valid and :invalid reflect constraints now; :user-valid and :user-invalid wait for browser-determined interaction.

indeterminate

There 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)
Behavior
  • It depends on whether the element supports the disabled state.
  • A readonly field remains enabled.
Examples
SelectorSpecificity(0, 1, 1)
input:enabled
HTML
Matches: <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.
Read the full definitionOpens in a new tab

:disabled

Disabled user-interface controls.

Specificity(0, 1, 0)
Behavior
  • A disabled fieldset can pass the state to its controls.
  • Disabled controls normally do not participate in submission.
Examples
SelectorSpecificity(0, 1, 1)
button:disabled
HTML
Matches: <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 the full definitionOpens in a new tab

:read-only

Elements whose content cannot be altered by the user.

Specificity(0, 1, 0)
Behavior
  • readonly keeps a control focusable and submittable.
  • Its applicability is broader than the readonly attribute.
Examples
SelectorSpecificity(0, 1, 1)
input:read-only
HTML
Matches: <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 the full definitionOpens in a new tab

:read-write

Elements whose content can be altered by the user.

Specificity(0, 1, 0)
Behavior
  • It includes applicable editable fields and contenteditable hosts.
  • The state depends on editability, not focus.
Examples
SelectorSpecificity(0, 1, 1)
textarea:read-write
HTML
Matches: <textarea>Editable</textarea>
<textarea readonly>Fixed</textarea>
Common mistakes
  • It does not mean the control is :valid.
  • A disabled input is not editable.
Read the full definitionOpens in a new tab

:placeholder-shown

Fields currently displaying their placeholder.

Specificity(0, 1, 0)
Behavior
  • It stops matching when the control has a value.
  • It observes field state, not the text pseudo-element.
Examples
SelectorSpecificity(0, 1, 1)
input:placeholder-shown
HTML
Matches: <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.

Read the full definitionOpens in a new tab

Choices

Distinguish default, selected, and indeterminate values.

:default

Options or buttons representing the initial choice.

Specificity(0, 1, 0)
Behavior
  • It may keep matching after the current selection changes.
  • It derives from the default state declared by HTML.
Examples
SelectorSpecificity(0, 1, 1)
input:default
HTML
Matches: <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.

Read the full definitionOpens in a new tab

:checked

Currently selected radios, checkboxes, and options.

Specificity(0, 1, 0)
Behavior
  • It changes through real user interaction.
  • For radios, checking one unchecks another in the group.
Examples
SelectorSpecificity(0, 1, 1)
input:checked
HTML
Matches: <input type="checkbox" checked />
<input type="checkbox" />
Common mistakes
  • It does not necessarily preserve the initial choice.
  • It does not cover mixed state.
Read the full definitionOpens in a new tab

:indeterminate

Controls in neither an affirmative nor negative state.

Specificity(0, 1, 0)
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
SelectorSpecificity(0, 1, 1)
input:indeterminate
HTML
Matches: <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.

Read the full definitionOpens in a new tab

Validation

Observe requirements and validity before and after interaction.

:required

Validatable controls that require a value.

Specificity(0, 1, 0)
Behavior
  • It comes from the required attribute when applicable.
  • It can combine with validity states.
Examples
SelectorSpecificity(0, 1, 1)
input:required
HTML
Matches: <input required />
<input />
Common mistakes
  • Not every control type supports required.
  • A visual asterisk does not create the state.
Read the full definitionOpens in a new tab

:optional

Validatable controls that are not required.

Specificity(0, 1, 0)
Behavior
  • It is the opposite of :required among applicable controls.
  • An empty optional field is usually valid.
Examples
SelectorSpecificity(0, 1, 1)
input:optional
HTML
<input required />
Matches: <input />
Common mistakes
  • It does not match every element without required.
  • Optional does not mean irrelevant.
Read the full definitionOpens in a new tab

:valid

Controls satisfying their native constraints.

Specificity(0, 1, 0)
Behavior
  • It may match from initial page load.
  • It updates while the value changes.
Examples
SelectorSpecificity(0, 1, 1)
input:valid
HTML
Matches: <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.
Read the full definitionOpens in a new tab

:invalid

Controls failing a native constraint.

Specificity(0, 1, 0)
Behavior
  • It may match before any interaction.
  • A form may also be invalid when it contains an invalid control.
Examples
SelectorSpecificity(0, 1, 1)
input:invalid
HTML
<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.
Read the full definitionOpens in a new tab

:user-valid

Valid controls after relevant user interaction.

Specificity(0, 1, 0)
Behavior
  • The browser decides when the user committed the value.
  • It stops matching if the value becomes invalid again.
Examples
SelectorSpecificity(0, 1, 1)
input:user-valid
HTML
Matches: <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.

Read the full definitionOpens in a new tab

:user-invalid

Invalid controls after relevant user interaction.

Specificity(0, 1, 0)
Behavior
  • A submission attempt can activate it and focus the first error.
  • It can delay the visual signal compared with :invalid.
Examples
SelectorSpecificity(0, 1, 1)
input:user-invalid
HTML
Matches: <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.

Read the full definitionOpens in a new tab

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)
Behavior
  • It only applies to controls supporting range limits.
  • The value must still satisfy other constraints.
Examples
SelectorSpecificity(0, 1, 1)
input:in-range
HTML
Matches: <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.
Read the full definitionOpens in a new tab

:out-of-range

Controls with a value below min or above max.

Specificity(0, 1, 0)
Behavior
  • It updates when the number or date changes.
  • It identifies one specific cause of invalidity.
Examples
SelectorSpecificity(0, 1, 1)
input:out-of-range
HTML
<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.
Read the full definitionOpens in a new tab