Mostly CSS and HTML Form Validation

Published
Last updated

There's almost a way to do entire CSS validation with a form. It takes just a few lines of javascript to get it working though. Basically, we'll be creating a form which does not validate with HTML by default. By doing this, we can have both HTML and JS validation living side-by-side.

Disabling HTML form validation

A form can be overwritten to not validate a couple ways. The first way is to add a novalidate attribute to the form element itself.

<form novalidate>
    /* Form inputs here */
</form>

The second way is to specify a formnovalidate attribute on the form submit button.

<form>
    /* Form inputs here */
    <button type="submit" formnovalidate>Submit</button>
</form>

If we do not include these, by default HTML validation on the forms will trigger, and thus any JS validation we want to trigger first would never be allowed to do so. The secret then is to programmatically call the validation process to trigger on a submit handler.

Triggering HTML form validation

We can trigger form validation again by using the reportValidity api on the form element.

form.addEventListener("submit", function(){
    // I perform my JS validation here

    if ( !this.reportValidity() ) { // I'll trigger HTML validation again
        e.preventDefault();
    } else {
        console.log('Form is valid!');
    }
});

Throwing in CSS validation

CSS has a lot of states that can be used on an input itself. Here are a few of the most useful ones.

/* If my CSS is valid, based on any HTML pattern or required attribute - this will show. */
input:valid {}

/* If my CSS is invalid, based on any HTML pattern or required attribute - this will show. */
input:invalid {}

 /* I'll show when the form element has a required attribute: <input required /> */
input:required {}

/* Any form element that does not have a required attribute. */
input:optional {} 

/* This is a good way of telling if an input is empty. The input will NEED a placeholder attibute though, and it needs to at least have an empty space <input placeholder=" " />. Sadly, it has limited browser support at the moment: https://developer.mozilla.org/en-US/docs/Web/CSS/:placeholder-shown */
input:placeholder-shown {} 

If we combine all this together, we get some sweet form magic. I love that it's not JS heavy and we can do some cool validation with using mostly just HTML and CSS.

See the Pen HTML Form validation with (mostly) CSS by Neal Fennimore (@nealfennimore) on CodePen.