Quick note about HTML5 Form validity and browser differences

This post is more than 2 years old.

I was working with a reader on my blog post on HTML5 form validation when we ran into an interesting problem with different browsers.

The reader was using a query selector to get a list of all invalid form fields. As an example:

var invalid = $(":invalid");

This little snippet will return all fields that are currently invalid based on whatever validation rules may be in play. In Chrome, he noticed that he got 2 fields in his test form, which he expected. In Firefox though he got 3.

I created a very simple app up on JSBin to replicate this: (I don't normally embed JSBin stuff so hopefully this works!)

Note the use of the "input" event. To test my code, type a character into the field and then delete it. Chrome returns 1 when you empty the field and Firefox returns 2. Why?

I added a loop and console.dir to actually view the items matching the selector. Turns out that in Firefox, the form tag is marked invalid as well. To be honest, that feels more right to me. I haven't checked the spec yet to see who is right, but I can certainly see the logic of it.

So how would you fix it so you can get a real count of the fields? Simple - just make that selector a bit more specific: $("input:invalid"). Of course, this won't work with textareas or selects in play. You can also just loop through the results and ignore a match on the form tag.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Blaise posted on 12/19/2013 at 8:11 PM

You should be able to skip the loop with
$(":invalid").not("form")

Comment 2 by Raymond Camden posted on 12/19/2013 at 8:18 PM

Boom - perfect. Thanks Blaise. I always forget about not() in jQuery.

Comment 3 by Paul Rowe posted on 12/19/2013 at 10:31 PM

I think you would also be able to use $("form :input:invalid").

Comment 4 by Raymond Camden posted on 12/20/2013 at 1:08 AM

But that has the same issue I mentioned about select/textarea.

Comment 5 by Paul posted on 12/20/2013 at 1:16 AM

$('form :invalid')

Comment 6 by Raymond Camden posted on 12/20/2013 at 1:18 AM

@Paul: Did you try that to see if FF still returned the <form> tag?

Comment 7 by Šime Vidas posted on 12/20/2013 at 9:40 AM

This is the optimal method I think: $(":invalid", "#myForm"). Here, #myForm is provided as a context, which is what we want to do anyway in a real-world scenario: Find all invalid fields within form X.

Live demo: http://jsfiddle.net/RxLzM/1/ (tested in FF/Ch)

Comment 8 by Šime Vidas posted on 12/20/2013 at 9:44 AM

And the screenshot that confirms that the FORM element indeed matches :invalid in Firefox but not in Chrome: http://i.imgur.com/gdcO6i2.png

Comment 9 by Paul Rowe posted on 12/20/2013 at 9:54 AM

Note the colon in front of "input". $("form :input:invalid") will catch the textareas and selects as well. See http://api.jquery.com/input....

Comment 10 by Raymond Camden posted on 12/20/2013 at 5:50 PM

@Sime, Paul: Thanks guys. So is :invalid a jQuery-ism then?

Comment 11 by Raymond Camden posted on 12/20/2013 at 5:51 PM

Answered my own question:

http://api.jquery.com/input...

So happy when a blog post like this leads to new discoveries for me. :)

Comment 12 by Ty Whalin posted on 12/22/2013 at 2:01 AM

Nice tid bit Ray. I may try this out since I have been using a javascript textcounter for form validation. This can catch all fields instead of just one. But one more note to add. I thought the preventDefault(); was deprecated.

Comment 13 by Raymond Camden posted on 12/22/2013 at 2:24 AM

Are you using textcounter for textareas to specify a maxlength?

preventDefault() - not afail. I could be wrong.

Comment 14 by Ty Whalin posted on 12/22/2013 at 2:49 AM

Yep, Got it on my forms with the keyUp and KeyDown functions. You might check the jQuery documentation for the preventDefault(), but I am pretty sure it has been deprecated.

Comment 15 by Raymond Camden posted on 12/22/2013 at 2:56 AM

I'm not seeing that here: http://api.jquery.com/event....

Comment 16 by Ty Whalin posted on 12/22/2013 at 10:35 PM

I figured it out. It is showing it as deprecated in the Safari console. I knew I saw it somewhere. Since it is on jQuery's website, I must assume it is not deprecated. Thanks for the clarification.

Comment 17 by Dumitru "Mitic?" UNG posted on 12/24/2013 at 2:32 AM

This is documented FireFox behavior: https://developer.mozilla.o.... See apply to form in the bottom section.

But shouldn't we chalk this up as programmer's oversight? Think multiple forms pages: http://jsfiddle.net/RxLzM/12/

Most likely, you should be as specific as you can and you should be looking up invalid fields in the current form instead, e.g. $(e).closest("form").

Comment 18 by Raymond Camden posted on 12/24/2013 at 2:53 AM

Well, I suppose you could chalk it up to the programmers mistake, but I see it as something that could have tripped people up. I use the *heck* out of MDN, but I know this facet wasn't known to me either.

Comment 19 by Dumitru "Mitic?" UNG posted on 12/24/2013 at 3:20 AM

True. It is a browser difference.