HTML5 Delay: Invalid Pseudo-Class Before First Event

I recently discovered that the pseudo-class of the :invalid class applies to required form elements as soon as the page loads. For example, if you have this code:

 <style> input:invalid { background-color: pink; color: white; } input:valid { background-color: white; color: black; } </style> … <input name="foo" required /> 

Then your page will be loaded with a blank pink input element. The validation built into HTML5 is great, but I don’t think most users expect the form to be validated before they can enter any values ​​at all. Is there a way to delay the application of the pseudo-class until the first event affecting this element (form of sending, blurring, changing, no matter what is appropriate)? Is it possible to do this without JavaScript?

+54
html5 validation usability
Oct 27 '11 at 6:43
source share
13 answers

http://www.alistapart.com/articles/forward-thinking-form-validation/

Since we only want to note that the field is invalid when it has focus, we use the focus pseudo-class to invoke the invalid style. (Naturally, marking all required fields as invalid from the very beginning will be a poor design choice.)

Following this logic, your code will look something like this:

 <style> input:focus:required:invalid {background-color: pink; color: white;} input:required:valid {background-color: white; color: black; } <style> 

Created a fiddle here: http://jsfiddle.net/tbERP/

As you might have guessed, and as you will see from the violin, this method only shows the style of validation when the element has focus. As soon as you move the focus, the stylization is discarded regardless of whether it is valid or not. Not perfect by any means.

+36
Oct 27 '11 at 19:38
source share

This is not possible in pure CSS, but can be done using JavaScript. This is a jQuery example :

 // use $.fn.one here to fire the event only once. $(':required').one('blur keydown', function() { console.log('touched', this); $(this).addClass('touched'); }); 
 /** * All required inputs initially are yellow. */ :required { background-color: lightyellow; } /** * If a required input has been touched and is valid, it should be white. */ .touched:required:valid { background-color: white; } /** * If a required input has been touched and is invalid, it should be pink. */ .touched:required:invalid { background-color: pink; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p> <label> Name: <input type="text" required> *required </label> </p> <p> <label>Age: <input type="text"> </label> </p> 
+20
Jun 28 '13 at 16:25
source share

These answers are out of date. Now you can do this by checking the pseudo-class using CSS.

 input:not(:placeholder-shown):invalid { background-color: salmon; } form:invalid button { background-color: salmon; pointer-events: none; } 
 <form> <input type="email" placeholder="me@example.com" required> <button type="submit">Submit</button> </form> 

It starts with a normal background and turns pink when you enter an incomplete email address into it.

+17
Jan 08 '18 at 3:52
source share

I created a small pad to handle this in my codebase. I just start with my <form/> element that has the novalidate property along with the data-validate-on="blur" attribute. This observes the first event of this type. This way you can use your own selectors :invalid css to style the form.

 $(function () { $('[data-validate-on]').each(function () { var $form = $(this); var event_name = $form.data('validate-on'); $form.one(event_name, ':input', function (event) { $form.removeAttr('novalidate'); }); }); }); 
+3
Mar 17 '16 at 19:53
source share

Mozilla takes care of this with its own pseudo-class : -moz-ui-invalid, which applies only to forms after they interact. MDN does not recommend using this because of a lack of support. However, you can change it for Firefox.

On the horizon there is a level 4 specification for : a user-invalid specification that will offer similar behavior.

Sorry if this does not help, but I hope this gives some context.

+3
Jun 29 '18 at 22:51
source share

When using HTML5 form validation, try using a browser to detect invalid views / fields, rather than reinventing the wheel.

Listen for the invalid event to add an invalid form to the form. With the "invalid" class added, you can go to town by creating a form using CSS3 :pseudo selectors.

For example:

 // where myformid is the ID of your form var myForm = document.forms.myformid; var checkCustomValidity = function(field, msg) { if('setCustomValidity' in field) { field.setCustomValidity(msg); } else { field.validationMessage = msg; } }; var validateForm = function() { // here, we're testing the field with an ID of 'name' checkCustomValidity(myForm.name, ''); if(myForm.name.value.length < 4) { checkCustomValidity( // alerts fields error message response myForm.name, 'Please enter a valid Full Name, here.' ); } }; /* here, we are handling your question above, by adding an invalid class to the form if it returns invalid. Below, you'll notice our attached listener for a form state of invalid */ var styleInvalidForm = function() { myForm.className = myForm.className += ' invalid'; } myForm.addEventListener('input', validateForm, false); myForm.addEventListener('keyup', validateForm, false); myForm.addEventListener('invalid', styleInvalidForm, true); 

Now just draw your form as you see fit, based on the β€œinvalid” class that we hooked up.

For example:

 form.invalid input:invalid, form.invalid textarea:invalid { background: rgba(255, 0, 0, .05); border-color: #ff6d6d; -webkit-box-shadow: 0 0 6px rgba(255, 0, 0, .35); box-shadow: 0 0 6px rgba(255, 0, 0, .35); } 
+2
Oct 26 '13 at 17:56 on
source share

There is an html5 invalid event that fires form elements before the submit event for each element that does not pass checkValidity. You can use this event to apply the class to the surrounding form and display: invalid styles only after this event.

  $("form input, form select, form textarea").on("invalid", function() { $(this).closest('form').addClass('invalid'); }); 

Your CSS will look something like this:

 :invalid { box-shadow: none; } .invalid input:invalid, .invalid textarea:invalid, .invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; } 

The first line removes the default style, so form elements look neutral when the page loads. As soon as an invalid event fires (when the user tries to submit the form), the elements are clearly displayed as invalid.

+2
Aug 29 '15 at 21:20
source share

You can make only elements that have a specific class and are required are pink. Add an event handler to every element you need that this class adds when you leave the element.

Something like:

 <style> input.touched:invalid { background-color: pink; color: white; } input.touched:valid { background-color: white; color: black; } </style> <script> document.addEventListener('DOMContentLoaded', function() { var required = document.querySelectorAll('input:required'); for (var i = 0; i < required.length; ++i) { (function(elem) { function removeClass(name) { if (elem.classList) elem.classList.remove(name); else elem.className = elem.className.replace( RegExp('(^|\\s)\\s*' + name + '(?:\\s+|$)'), function (match, leading) {return leading;} ); } function addClass(name) { removeClass(name); if (elem.classList) elem.classList.add(name); else elem.className += ' ' + name; } // If you require a class, and you use JS to add it, you end up // not showing pink at all if JS is disabled. // One workaround is to have the class on all your elements anyway, // and remove it when you set up proper validation. // The main problem with that is that without JS, you see what you're // already seeing, and stuff looks hideous. // Unfortunately, you kinda have to pick one or the other. // Let non-blank elements stay "touched", if they are already, // so other stuff can make the element :invalid if need be if (elem.value == '') addClass('touched'); elem.addEventListener('blur', function() { addClass('touched'); }); // Oh, and when the form submits, they need to know about everything if (elem.form) { elem.form.addEventListener('submit', function() { addClass('touched'); }); }; })(required[i]); } }); </script> 

And, of course, it will not work the same as in IE8 or lower, because (a) DOMContentLoaded is relatively new and was not standard when IE8 came out, (b) IE8 uses attachEvent , not DOM-standard addEventListener and (c ) IE8 will not care about :required anyway, as it technically does not support HTML 5.

+1
Apr 04 '13 at 14:33
source share

A good way is to abstract :invalid, :valid with CSS classes and then some JavaScript to check if the input field is focused or not.

CSS

 input.dirty:invalid{ color: red; } input.dirty:valid{ color: green; } 

JS:

 // Function to add class to target element function makeDirty(e){ e.target.classList.toggle('dirty'); } // get form inputs var inputs = document.forms[0].elements; // bind events to all inputs for(let input of inputs){ input.addEventListener('invalid', makeDirty); input.addEventListener('blur', makeDirty); input.addEventListener('valid', makeDirty); } 

Demo

+1
Sep 28 '17 at 14:20
source share

This is kzh version of VanillaJS answer (without jQuery)

 { let f = function() { this.classList.add('touched') } document .querySelectorAll('input') .forEach((e) => { e.addEventListener('blur', f, false) e.addEventListener('keydown', f, false) }) } 
 /** * All required inputs initially are yellow. */ :required { background-color: lightyellow; } /** * If a required input has been touched and is valid, it should be white. */ .touched:required:valid { background-color: white; } /** * If a required input has been touched and is invalid, it should be pink. */ .touched:required:invalid { background-color: pink; } 
 <p><label> Name: <input type="text" required> *required </label></p> <p><label>Age: <input type="text"> </label></p> 
+1
Mar 06 '19 at 12:51
source share

Here is my method for avoiding the default styling of any unfocused input as invalid, you just need to add a simple js onFocus command to allow the web page to identify focused and unfocused inputs so that all the input is not displayed in an invalid style in the first place.

 <style> input.focused:required:invalid { background-color: pink; color: white; } input:valid { background-color: white; color: black; } </style> … <input name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required /> 

Try it yourself below:

 input.focused:required:invalid { background-color: pink; color: white; } input:required:valid { background-color: darkseagreen; color: black; } 
 <label>At least 1 charater:</label><br /> <input type="text" name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required /> 
0
Sep 10 '18 at 12:39
source share

I cannot comment, but using @Carl is a very useful answer regarding using: not (: placeholder-show). As mentioned in another comment, it will still display an invalid state if you DO NOT have a placeholder (as some form designs require).

To solve this problem, just add an empty placeholder, like so

 <input type="text" name="username" placeholder=" " required> 

Then your CSS, something like

 :not(:placeholder-shown):invalid{ background-color: #ff000038; } 

Worked for me!

0
Mar 14 '19 at 18:55
source share

Based on the idea of Agouseh , you can have a bit of javascript to tell when the submit button was pressed, and so that a check is displayed at that time.

Javascript will add a class (e.g. submit-focussed ) to the form field when the submit button is focused or clicked, which will then allow CSS to style the invalid input.

This follows from the best practice of showing validation feedback after the user has completed filling out the fields, as according to the study there is no additional benefit to show this during the process.

 document .querySelector('input[type=submit]') .onfocus = function() { this .closest('form') .classList .add('submit-focussed'); }; 
 form.submit-focussed input:invalid { border: thin solid red; } 
 <form> <label>Email <input type="email" required="" /></label> <input type="submit" /> </form> 

jQuery alternative

 (function($) { $('input[type=submit]').on('focus', function() { $(this) .parent('form') .addClass('submit-focussed'); }); })(jQuery); /* WordPress compatible */ 
0
May 04 '19 at 12:02
source share



All Articles