A new range of CSS pseudo-classes, known as the UI element states pseudo-classes, augments the extra functionality provided to forms by HTML5. These pseudo-classes let you style form elements based on their current interaction or validation state. The names of the pseudo-classes are really quite descriptive, and I imagine their meanings are clear to you, but just in case you’ve had a hard day and aren’t thinking straight, I’ll briefly explain them.
Form fields that are required (that is, have the required attribute set to true) can be styled with the :required pseudo-class, the opposite of which is :optional. You could, for example, give a dark border to required fields and a lighter border to optional ones:
input:required { border-color: black; }
input:optional { border-color: gray; }
The :valid and :invalid selectors are applied to elements based on their current validation state; :valid is used to apply styles to a valid form field, and :invalid to an invalid form field. That being the case, you may want to style the text of each input element in a different color based on its state: green for valid and red for invalid:
input:valid { color: green; }
input:invalid { color: red; }The latest CSS Selectors specification proposes a :user-error pseudo-class, similar to :invalid but applying only when a user has entered data that doesn’t match the required pattern in a field. At the time of writing, this pseudo-class has not been implemented in any browsers.
You can style form elements that have the disabled attribute applied by using the :disabled pseudo-class and, conversely, :enabled for those that have the enabled attribute. Likewise, a form element that has the readonly attribute set to true can be styled using :read-only, the opposite of which is :read-write.
radio and checkbox input types have some dedicated pseudo-classes: :indeterminate, which is when the user has neither checked nor unchecked the input, and :checked for when the user has checked the input. Curiously, no matching unchecked state exists; for this, you must use the negation selector:
input[type='checkbox']:not(:checked) { … }
For number and range inputs, you can use the :in-range and :out-of-range pseudo-classes, which apply if a value is in or out of the acceptable range—either 0 to 1 or a custom range set with max and min. If using on-screen controls, the user can’t exceed these limits, so the :out-of-range selector is unlikely to be used frequently.