Form validation is a critical aspect of creating robust and user-friendly web applications. For years, JavaScript has been the go-to solution for validating forms, but with advancements in CSS, it’s now possible to achieve client-side form validation using purely HTML attributes and CSS. Thanks to powerful selectors like :valid, :invalid, :user-valid, and :user-invalid, and the new :has() pseudo-class, CSS is now capable of handling many common validation scenarios.
In this guide, we’ll explore how to validate forms using only HTML and CSS, discuss the various pseudo-classes involved, and walk through a real-world example that will show you how to create forms that provide feedback on user input—all without a single line of JavaScript!
Why Use CSS for Form Validation?
Traditionally, form validation has been handled using JavaScript. JavaScript allows for robust, dynamic validation of form inputs before the data is sent to the server. While JavaScript is a great tool for validation, it introduces several complexities, such as adding event listeners, ensuring compatibility across browsers, and handling accessibility concerns. With CSS validation, we can avoid many of these pitfalls.
Here’s why CSS form validation is a game-changer:
- Simplicity: No need to write custom JavaScript for simple validation tasks.
- Less overhead: CSS-based validation reduces the amount of JavaScript code on your page, which can improve performance.
- Native browser support: CSS validation leverages the built-in validation rules of HTML5 form elements, ensuring compatibility across most modern browsers.
Now, let’s dive into how you can implement form validation using just CSS.
HTML5 Input Attributes for Validation
Before we get into the CSS rules, it’s essential to understand that HTML5 has introduced several attributes to simplify form validation. These attributes provide out-of-the-box validation without any need for JavaScript. The most important ones are:
required
: Ensures that the user cannot submit the form without filling out the field.type
: Defines the input type, such as email, number, url, etc., each having its own validation rules.pattern
: Specifies a regular expression that the input must match to be considered valid.minlength
andmaxlength
: Define the minimum and maximum number of characters for the input.
For example, an email input with basic HTML validation might look like this:
<form>
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
</form>
With just this markup, the browser automatically ensures the input matches the required email format and prevents form submission if it’s empty or incorrect.
CSS Pseudo-Classes for Form Validation
Once you’ve set up your HTML form with validation attributes, you can style the form using CSS pseudo-classes that react to the validation state. The key pseudo-classes we’ll use are:
:valid
: Targets form elements that have passed validation (e.g., an email input with a correctly formatted email).:invalid
: Targets form elements that fail validation (e.g., an empty required field).:user-valid
: Targets form elements that have passed validation but only after the user has interacted with the field.:user-invalid
: Similar to :invalid, but only applies after user interaction.
Example of Basic CSS Validation Styles:
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
input:user-valid {
box-shadow: 0 0 5px green;
}
input:user-invalid {
box-shadow: 0 0 5px red;
}
With these rules, you can create a visual feedback system for your form inputs. A field will turn green if valid and red if invalid, providing immediate feedback to the user.
A Real-World Example with CSS Form Validation
Let’s walk through a simple form with validation using only CSS. This example is based on the image provided (which we’ll include shortly). We’ll use an input field, a select
dropdown, and a textarea
, and we’ll style them based on their validation states.
The HTML:
<form>
<label for="input">Input</label>
<input type="text" id="input" required minlength="4" />
<label for="select">Select</label>
<select id="select" required>
<option value="">Choose an option</option>
<option value="one">One</option>
<option value="two">Two</option>
</select>
<label for="textarea">Textarea</label>
<textarea id="textarea" required minlength="4"></textarea>
</form>
In this form, we’ve used:
- An input field that requires a minimum of 4 characters.
- A select dropdown with a required option.
- A textarea that also requires a minimum of 4 characters.
The CSS:
input,
select,
textarea {
border: 2px solid gray;
padding: 8px;
margin: 10px 0;
}
input:valid,
select:valid,
textarea:valid {
border-color: green;
}
input:invalid,
select:invalid,
textarea:invalid {
border-color: red;
}
input:user-valid,
select:user-valid,
textarea:user-valid {
box-shadow: 0 0 5px green;
}
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
box-shadow: 0 0 5px red;
}
In this CSS, we’ve added styles for the validation states:
- When a field is valid, the border turns green.
- When it’s invalid, the border turns red.
- Once the user has interacted with the field, additional visual cues like box shadows are applied to valid or invalid fields.
Using the :has() Pseudo-Class for Complex Validation
The :has() pseudo-class in CSS allows you to apply styles based on the presence of specific elements or content within an element. This feature is relatively new, but it’s extremely powerful.
For example, if you want to highlight a form group when any of its input fields are invalid, you can use :has()
like this:
form:has(input:invalid) {
border: 2px solid red;
}
This applies a red border around the entire form if any input field within it is invalid. :has() enables more complex validation styling that was previously only possible with JavaScript.
Conclusion
CSS form validation is a powerful tool that eliminates the need for JavaScript in many common form validation scenarios. By leveraging HTML5 validation attributes and CSS pseudo-classes like :valid
, :invalid
, :user-valid
, and :user-invalid
, you can create a seamless, lightweight validation experience for your users. The new :has()
selector adds even more flexibility, enabling complex styling based on validation states.
While CSS-based validation may not completely replace JavaScript for all use cases (e.g., validating fields dynamically or handling asynchronous validation), it’s a perfect solution for most simple to moderate form validation needs.
To see this in action, feel free to check out the CodePen example to experiment with the code yourself!
Happy coding!