CSS :optional Pseudo-Class
The CSS :optional pseudo-class selects form controls that do not require a value before a form can be submitted. It is commonly used with <input>, <select>, and <textarea> elements to distinguish optional fields from required fields.
:optional Syntax
selector:optional {
property: value;
}
The :optional pseudo-class matches form controls that support the required attribute but are not currently required.
Basic Example
input:optional {
border-color: #006699;
}
Selects optional input controls, such as a text field without the required attribute.
Select Example
select:optional {
background-color: #eaf6fc;
}
Styles a select control when the user is not required to make a selection.
Textarea Example
textarea:optional {
border-style: dashed;
}
Applies a dashed border to an optional textarea.
No Parentheses
The :optional pseudo-class does not accept arguments and is written without parentheses.
How :optional Works
The browser determines whether a form control supports the required state and whether it is currently required. A supported control matches :optional when it is not required.
HTML Example
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="company">Company:</label>
<input type="text" id="company" name="company">
</form>
CSS Example
input:optional {
background-color: #eaf6fc;
}
The Company field matches because it is not required. The Name field does not match because it has the required attribute.
Optional Does Not Mean Empty
An optional field matches :optional whether it contains a value or is empty.
Required State
A supported control with the required attribute matches :required instead of :optional.
Independent of User Interaction
The optional state is determined by the control's requirements, not by whether the user has focused, edited, or submitted the field.
Optional Input Fields
Many input types support the required attribute and can match :optional when that attribute is absent.
Optional Text Field
<label for="nickname">Nickname (optional):</label>
<input type="text" id="nickname" name="nickname">
input[type="text"]:optional {
border-color: #006699;
}
The nickname field matches because it is not required.
Optional Email Field
<label for="email">Alternate Email (optional):</label>
<input type="email" id="email" name="email">
input[type="email"]:optional {
background-color: #eaf6fc;
}
The email field is optional, but a nonempty value must still follow the email input type's validation rules.
Optional Date Field
<label for="date">Preferred Date (optional):</label>
<input type="date" id="date" name="date">
The date field matches :optional because the user is not required to choose a date.
Optional Checkbox
<label>
<input type="checkbox" name="updates">
Receive updates
</label>
The checkbox matches :optional because checking it is not required.
Input Types That Do Not Support Required
Some input types, including hidden, range, color, and button-related types, do not support the required state and therefore do not match :optional.
Select and Textarea Elements
The :optional pseudo-class also applies to <select> and <textarea> elements when they are not required.
Optional Select
<label for="layout">Preferred Layout (optional):</label>
<select id="layout" name="layout">
<option value="">No preference</option>
<option value="grid">Grid</option>
<option value="flexbox">Flexbox</option>
</select>
select:optional {
border-color: #006699;
}
The select control matches because choosing a specific layout is not required.
Optional Textarea
<label for="comments">Additional Comments (optional):</label>
<textarea id="comments" name="comments"></textarea>
textarea:optional {
background-color: #eaf6fc;
}
The textarea matches because the user may leave it empty.
Required Comparison
<textarea id="message" name="message" required></textarea>
This textarea matches :required rather than :optional.
Optional State and Values
Adding a value to a select or textarea does not change whether it matches :optional.
The Required Attribute
The HTML required attribute determines whether supported form controls must have a value or satisfy a required selection condition.
Required Field
<input type="text" name="username" required>
This field matches :required because the required attribute is present.
Optional Field
<input type="text" name="nickname">
This field matches :optional because it does not have the required attribute.
Boolean Attribute
<input type="text" name="username" required="false">
The field is still required. The required attribute is Boolean, so its presence makes the control required regardless of the string assigned to it.
Changing the Required State
const field = document.querySelector("#company");
field.required = true;
Setting the required property to true changes a supported optional field into a required field. The browser updates its pseudo-class matching automatically.
Removing the Requirement
field.required = false;
Removing the requirement makes the field match :optional again.
Optional Fields and Validation
An optional field does not require a value, but values entered into it may still need to satisfy other validation rules.
Optional Email Validation
<input type="email" name="alternate-email">
The field can be left empty. If the user enters a value, the browser checks whether it follows the expected email format.
Optional Pattern Validation
<input type="text" name="code" pattern="[A-Z]{3}">
The field may be empty, but a nonempty value must contain exactly three uppercase letters to satisfy the pattern.
Optional Field Can Be Invalid
input:optional:invalid {
border-color: #c0392b;
}
This rule selects optional inputs that currently fail a validation constraint.
Optional and Valid
input:optional:valid {
border-color: #2e7d32;
}
An empty optional email field can match both :optional and :valid, provided no other validation constraint makes it invalid.
Required vs. Validity
The :optional and :required pseudo-classes describe whether a value is required. The :valid and :invalid pseudo-classes describe whether the control satisfies its validation constraints.
Styling Optional Field Labels
The :optional pseudo-class matches the form control, not its associated label. CSS can use structural selectors to style labels based on the optional state of nearby controls.
Using :has()
<div class="form-field">
<label for="company">Company</label>
<input type="text" id="company" name="company">
</div>
.form-field:has(input:optional) label {
color: #006699;
}
The label receives blue text when its form-field container includes an optional input.
Adding an Optional Indicator
.form-field:has(input:optional) label::after {
content: " (optional)";
color: #666;
font-size: 0.875rem;
}
Adds a visual optional indicator after the label text.
Explicit HTML Labels
<label for="company">Company (optional)</label>
Including the optional indicator directly in the HTML is generally more reliable for accessibility than relying only on CSS-generated content.
Form Structure Matters
Selectors such as :has() depend on the HTML structure. Keep each label and its control in a predictable container when using parent-based styling.
Related Pseudo-Classes
Several form-related pseudo-classes describe required states, validation, and user interaction.
Comparison
| Pseudo-Class | Matching Behavior |
|---|---|
:optional | Matches form controls that support the required state but are not required. |
:required | Matches form controls that are required. |
:valid | Matches controls that satisfy their validation constraints. |
:invalid | Matches controls that fail their validation constraints. |
:user-valid | Matches valid controls after the relevant user interaction conditions are met. |
:user-invalid | Matches invalid controls after the relevant user interaction conditions are met. |
:placeholder-shown | Matches supported inputs or textareas while placeholder text is displayed. |
:read-only | Matches elements that are not user-editable. |
Optional vs. Required
input:optional {
border-color: #006699;
}
input:required {
border-color: #c0392b;
}
These rules distinguish optional and required input controls.
Optional vs. Valid
input:optional:valid {
background-color: #eaf6fc;
}
input:optional:invalid {
background-color: #fdecea;
}
An optional field can match either validity state depending on its current value and validation constraints.
:optional Specificity
The :optional pseudo-class contributes a specificity of 0-1-0, like other standard pseudo-classes.
Specificity Examples
| Selector | Specificity |
|---|---|
:optional | 0-1-0 |
input:optional | 0-1-1 |
.field:optional | 0-2-0 |
form input:optional | 0-1-2 |
.form-field > input:optional | 0-2-1 |
input:optional:invalid | 0-2-1 |
#contact input:optional | 1-1-1 |
Specificity Example
input {
border-color: #ccc;
}
input:optional {
border-color: #006699;
}
When both rules match and other cascade factors are equal, the :optional rule takes precedence because it has greater specificity.
Combined Pseudo-Classes
input:optional:invalid {
border-color: #c0392b;
}
Combining :optional with :invalid increases specificity because both pseudo-classes contribute to the selector.
Practical Uses
The :optional pseudo-class helps distinguish optional form controls without adding extra classes to the HTML.
Optional Field Background
input:optional {
background-color: #eaf6fc;
}
Applies a light blue background to optional input controls.
Optional Textarea Border
textarea:optional {
border: 1px dashed #006699;
}
Uses a dashed border to distinguish optional textareas.
Optional Select Control
select:optional {
border-color: #006699;
}
Styles select controls that do not require a selection.
Optional Field Indicator
.form-field:has(> input:optional) label::after {
content: " (optional)";
color: #666;
}
Adds a visual indicator to a label when its field is optional.
Optional Invalid Fields
input:optional:user-invalid {
border-color: #c0392b;
}
Highlights an optional field when it has an invalid value and the user-interaction conditions for :user-invalid are met.
Limitations
The :optional pseudo-class describes a form control's required state, not its value, visibility, or overall validity.
Not All Inputs Are Eligible
Input types that do not support the required state, such as hidden, range, color, and button-related types, do not match :optional.
Optional Does Not Mean Valid
An optional field can be invalid if a nonempty value violates a validation constraint.
Optional Does Not Mean Empty
Entering a value does not stop a field from matching :optional.
No Automatic Label Styling
The pseudo-class selects the control itself. Labels require separate selectors or explicit HTML indicators.
Disabled Controls
A disabled control can still match :optional or :required according to its required state, even though disabled controls are not validated or submitted.
Read-Only Controls
Read-only controls may be excluded from constraint validation. Their required-state behavior should not be confused with whether users can edit them.
CSS Does Not Set Requirements
Applying :optional styles does not make a field optional. The HTML attributes and form-control behavior determine whether a value is required.
Best Practices
- Use
:optionalto style form controls that support the required state but are not required. - Combine it with
input,select, ortextareato target specific controls. - Use
:requiredfor required controls rather than relying only on visual styling. - Identify optional fields clearly in their labels or accompanying instructions.
- Do not rely on color alone to distinguish required and optional fields.
- Remember that optional fields can still fail validation when users enter invalid values.
- Use
:user-invalidwhen validation feedback should depend on user interaction. - Do not assume all input types support
:optional. - Keep form labels associated with their controls using
forandid. - Test forms with empty values, valid values, and invalid values.
:optional Example
This example compares required and optional form fields. The Name field is required and receives a standard gray background. The Company and Comments fields are optional and receive a light blue background and blue border.
HTML
<form class="optional-demo">
<label for="demo-name">Name (required)</label>
<input type="text" id="demo-name" name="name" required>
<label for="demo-company">Company (optional)</label>
<input type="text" id="demo-company" name="company">
<label for="demo-comments">Comments (optional)</label>
<textarea id="demo-comments" name="comments" rows="3"></textarea>
</form>
CSS
.optional-demo label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.optional-demo input,
.optional-demo textarea {
display: block;
width: 100%;
box-sizing: border-box;
padding: 10px;
margin-bottom: 12px;
border: 2px solid #ccc;
background-color: #f5f5f5;
}
.optional-demo :optional {
border-color: #006699;
background-color: #eaf6fc;
}
Browser Result
Note: The Company and Comments fields match :optional because they are not required. The Name field does not match because it has the required attribute.
Browser Support
Baseline: Widely available. The :optional pseudo-class is supported in modern versions of Chrome, Edge, Firefox, Safari, and other major browsers. It is part of the established CSS form-state selectors.
For current compatibility information, visit Can I Use? .
Specifications
The :optional pseudo-class is defined in CSS Selectors Level 4 as a form-state pseudo-class. It matches form controls that support the required state but are not required.
