Table of Contents
Introduction
When it comes to validating the content of input fields on the frontend, things are much easier now than they they used to be. We can use the <^>:required<^>, <^>:optional<^>, <^>:valid<^> and <^>:invalid<^> pseudo-classes coupled with HTML5 form validation attributes like <^>required<^> or <^>pattern<^> to create very visually engaging results. These pseudo-classes work for <^>input<^>, <^>textarea<^> and <^>select<^> elements.
Input pseudo-classes
Here's an example of the pseudo-classes at work. Let's start with this HTML markup:
<form action="#">
<input type="text" placeholder="First Name" required>
<input type="email" placeholder="Email" required>
<input type="text" placeholder="Nickname">
<input type="text" placeholder="Favorite pizza topping">
</form>
And let's apply the following styles:
input {
border: 2px solid;
border-radius: 4px;
font-size: 1rem;
margin: 0.25rem;
min-width: 125px;
padding: 0.5rem;
transition: background-color 0.5s ease-out;
}
input:optional {
border-color: gray;
}
input:required {
border-color: black;
}
input:invalid {
border-color: red;
}
Here's the result:
[codepen alligatorio vYGeLYw]
—
In the demo above, <input type="email" is an HTML5 input type that tells browsers to expect an email address. Because we are also using the required attribute, modern browsers will only set the input to :valid when a valid email is entered.
Adding the :focus pseudo-class
Let's make things even more interesting by also styling according to the focus state and add a background image and color depending on the validity state and only when the input is in focus. We'll use the same HTML markup.
Here's our updated CSS:
input {
border: 2px solid;
border-radius: 4px;
font-size: 1rem;
margin: 0.25rem;
min-width: 125px;
padding: 0.5rem;
transition: border-color 0.5s ease-out;
}
input:optional {
border-color: gray;
}
input:required:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
input:required:focus:valid {
background: url("images/css-styling-form-input-validity-section-1.png") no-repeat 95% 50% lightgreen;
background-size: 25px;
}
input:focus:invalid {
background: url("images/css-styling-form-input-validity-section-1.png") no-repeat 95% 50% lightsalmon;
background-size: 25px;
}
There are two key changes in the above CSS:
input:required:validapplies a success state only to _required_ inputs. Because technically,optionalinputs are always valid.
input:focus:valid' and 'input:focus:invalidapply to inputs only when they are focused.
And here's the result:
[codepen alligatorio gOrGPxP]
—
You could be tempted to add content instead using <^>::before<^> or <^>::after<^> on the input, but unfortunately that's not possible on input elements. One trick would be to have a sibling <^>span<^> element that has content added depending on the validity of the input. Something like this:
input:focus:invalid + span::before { ... }.