Skip to content

[selectors] pseudo selector to match forms ValidityState #1525

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jimmywarting opened this issue Jun 13, 2017 · 8 comments
Open

[selectors] pseudo selector to match forms ValidityState #1525

jimmywarting opened this issue Jun 13, 2017 · 8 comments

Comments

@jimmywarting
Copy link

jimmywarting commented Jun 13, 2017

The Problem

When I did put a pattern to one of my form elment, it yields a tooltip saying "Enter a correct pattern"
The browser don't do a good job at displaying the correct pattern to use. So i need a way to inform them how the field should be written (look like)

<input 
  type="text"
  name="username"
  minlength="2"
  maxlength="20"
  required
  pattern="^[a-zA-Z][a-zA-Z0-9-_\.]{1,20}$"
/>

The solution

I would want it to behave a little like angular´s ngMessage, see demo

Say you got custom errors like this:

<input ...>
<div class="required">Username is required</div>
<div class="minlength">Username is too short</div>
<div class="maxlength">Username is too long</div>
<div class="pattern">Use only letters and numbers</div>

Now to style the right error message green or red, show or hide. I would want to use the same properties that exist on the constraints object input.validity (ValidityState)

ValidityState {
  badInput, patternMismatch, rangeOverflow, rangeUnderflow
  stepMismatch, tooLong, tooShort, typeMismatch, valueMissing
}
input:valueMissing ~ .required {display: block}
input:tooShort ~ .minlength {display: block}
input:tooLong ~ .maxlength {display: block}
input:patternMismatch ~ .pattern {display: block}
@fantasai fantasai added the selectors-4 Current Work label Jun 15, 2017
@SebastianZ
Copy link
Contributor

This is covered by the :invalid pseudo-class.

Sebastian

@jimmywarting
Copy link
Author

jimmywarting commented Jun 16, 2017

the :invalid is too general.

@SebastianZ
Copy link
Contributor

SebastianZ commented Jun 16, 2017

I see. And you're right, there doesn't seem to be more fine-grained matching of invalidity except the :out-of-range pseudo-class.

Note that CSS uses hyphen-separated syntax, not camel case. So, your proposal should rather look like this:

input:value-missing ~ .required { display: block; }
input:too-short ~ .minlength { display: block; }
input:too-long ~ .maxlength { display: block; }
input:pattern-mismatch ~ .pattern { display: block; }

Another way would be to allow parameters for the :invalid pseudo-class. That would group the different error types. I.e. this could then look like:

input:invalid(value-missing) ~ .required { display: block; }
input:invalid(too-short) ~ .minlength { display: block; }
input:invalid(too-long) ~ .maxlength { display: block; }
input:invalid(pattern-mismatch) ~ .pattern { display: block; }
input:invalid(out-of-range) ~ .outofrange { display: block; }

which would allow to match different types of errors by allowing to provide multiple keywords:

input:invalid(too-short, too-long) ~ .invalidlength { display: block; }

Furthermore, for empty inputs there is already issue #1283. So empty inputs requiring a value could then also be matched via input:required:empty. Though an explicit way to check whether a required field is missing the value is probably nicer and more consistent to the other proposed pseudo-classes.

Sebastian

@jimmywarting
Copy link
Author

jimmywarting commented Jun 16, 2017

Like the idea! Which we had came up with parameters for the :invalid pseudo-class before we introduced :out-of-range, maybe that would not have existed if we came up with this before.

It seems like this idea of parameters is also better feature wise if we decide to add new validity properties in the feature...

@jimmywarting
Copy link
Author

Just for the shake of it i wrote a jQuery.expr

$.extend($.expr[':'], {
  validity: (node, i, args) => 
    args[3]
    .replace(/-([a-z])/g, g => g[1].toUpperCase())
    .split(',')
    .some(prop => node.validity[prop.trim()])
})
$('input:validity(value-missing)').css('color', 'red')

@fantasai fantasai added selectors-5 and removed selectors-4 Current Work labels Jan 1, 2018
@lukewarlow
Copy link
Member

I think the above proposals of either making invalid functional (along with user-invalid) or adding new pseudo classes is a good idea and is a step towards improving styling of form control errors based on validation state.

:value-missing is probably covered by the existing proposed :blank psuedo combined with :required but could be nice to include for completeness. Instead of invalid(out-of-range) we could potentially do below-range and above-range to offer even more granularity?

@alexnozer
Copy link

alexnozer commented Mar 27, 2025

I find this suggestion useful. Currently, we have the :valid/:invalid and :user-valid/:user-invalid selectors. However, they are too generic and only indicate whether the value is valid or invalid, without providing further details. There are also :in-range/:out-of-range selectors, which specify whether the value falls within the defined range. However, there are no corresponding selectors for the pattern, minlength/maxlength, type and other attributes. It would be useful to introduce new selectors for a one-to-one correspondence with the ValidityState properties.

A set of selectors might look as follows (presented in the table):

HTML attribute ValididtyState CSS invalid selector CSS valid selector
required valueMissing :value-missing :value-exists
min rangeUnderflow :range-underflow and also match current :out-of-range :in-range
max rangeOverflow :range-overflow and also match current :out-of-range :in-range
minlength tooShort :too-short :optimal-length
maxlength tooLong :too-long :optimal-length
type typeMismatch :type-mismatch :type-match
step stepMismatch :step-mismatch :step-match
pattern patternMismatch :pattern-mismatch :pattern-match

A combination of the :not() pseudo-class and CSS invalid selectors can be used as an alternative to CSS valid selectors (e.g., :not(:pattern-mismatch) instead of :pattern-match).

A set of these selectors would enable the addition of hidden error messages that can be displayed without the need for JavaScript. This approach can be useful for basic form validation and progressive enhancement.

@Crissov
Copy link
Contributor

Crissov commented Mar 27, 2025

The special cases of :out-of-range should probably have similar names, e.g. :below-range and :above-range, or they should be aligned with the proposed string classes, i.e. :too-low/:too-small and :too-high/:too-large, or those should be aligned, e.g. :below-length and :above-length.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants