Open SebastianZ opened 7 years ago
@SebastianZ Could you give some specific use cases, other than those covered by :user-invalid
? :)
@fantasai
Example (copied over from a recent duplicate of this issue):
input {
font-weight:normal;
}
input:modified {
font-weight:bold;
}
The above would highlight modified inputs with bold font.
I do not see it less useful than :checked
or :default
.
Oooh what a fun idea! Here's a quick demo of what using :modified
in CSS stylesheets might feel like by using el.value !== el.defaultValue
logic in JavaScript with a made-up [--modified]
selector in CSS that we can grab onto to implement the functionality: https://codepen.io/tomhodgins/pen/YdKveq
input[--modified] {
background: lime;
}
It's kind of fun, and does fill a current gap with [value=""]
and <input>
elements between the value
and the dirty value.
Given the above linked dirty value, IMHO the best name for this pseudo-class would be :dirty
.
The HTML Live Standard defines the dirty flag as
input
andtextarea
elements have a dirty value flag. This is used to track the interaction between the value and default value. If it is false, value mirrors the default value. If it is true, the default value is ignored.
while select
elements have the concept of dirtiness on their option
descendants:
The dirtiness of an
option
element is a boolean state, initially false. It controls whether adding or removing theselected
content attribute has any effect.
In this case dirtiness should bubble up from the option
elements to their parent select
element.
This would be really useful for creating Material-style inputs that move the label of the input above it. Most implementations I've seen either use JavaScript or take advantage of the required
attribute along with the :valid
selector, but obviously this isn't ideal.
š for :dirty (aka different from what has been submitted by the http response)
... and :modified would NOT be the same.
Modified could mean the same as unix "touched" which could mean the value would be the same but you touched it.
As there was a lot of positive feedback and possible use cases mentioned, I set this as Agenda+.
Sebastian
With :placeholder-shown
, :checked
, :indeterminate
, etc. I'm not sure what's the appeal for this. But I think the bigger issue I have with this, is what the "default" state is.
With
:placeholder-shown
,:checked
,:indeterminate
, etc. I'm not sure what's the appeal for this. But I think the bigger issue I have with this, is what the "default" state is.
There are cases when you want to mark/highlight the input fields that were modified since page load. While this is easy to do for checkboxes/radio buttons (e.g. input[checked]:not(:checked) {...}
and input:not([checked]):checked {...}
), there isn't such a "straightforward" solution in the case of text inputs, textareas or selects.
In the context of :dirty
, "default" would mean the value the input field had when the page was loaded (it might be empty or not). It is a good point, however, that in the case of SPAs there should be a way to "mark" a new value as default.
Wouldn't this be equivalent to :is(:user-valid, :user-invalid)
or somesuch?
Wouldn't this be equivalent to
:is(:user-valid, :user-invalid)
or somesuch?
Would you like to shortly explain how this would work?
https://drafts.csswg.org/selectors-4/#user-pseudos says:
The :user-invalid and the :user-valid pseudo-classes represent an element with incorrect or correct input, respectively, but only after the user has significantly interacted with it.
So :is(:user-valid, :user-invalid)
should cover all elements (both correct and incorrect) that the user has interacted with. So it's not exactly a != default
, but it seems to address the relevant use-cases which are more on the line of "things the user has interacted with" rather than the specific "it's not the default value".
Thanks! On a quick read I failed to see that :is(:user-valid, :user-invalid)
was an actual selector and not an enumeration of the :is(:user-valid)
and :is(:user-invalid)
selectors.
You are right that :is(:user-valid, :user-invalid)
covers all "significantly interacted with" elements, but there is at least one drawback which makes it incompatible with :dirty
:
https://drafts.csswg.org/selectors-4/#user-pseudos also says:
For example, the input in the following document fragment would match '':invalid'' as soon as the page is loaded (because it the initial value violates the max-constraint), but it won't match '':user-invalid'' until the user significantly interacts with the element, or attempts to submit the form it's part of.
<form> <label> Volume: <input name='vol' type=number min=0 max=10 value=11> </label> ... </form>
Basically the
:is(:user-valid, :user-invalid)
would kick in on form submit even if there was no interaction with the elements.
This being said, there probably is a combination of :user-valid
, :user-invalid
, :valid
, :invalid
that would do the job for each of the most common real-life use-cases, but I would still prefer the more straightforward :dirty
š
The CSS Working Group just discussed [selectors-4] Issue 11: Introduce pseudo-class matching when user changed the value of an input
.
I'm really not a fan of the name :dirty
. It seems very inconsistent with the kinds of names in CSS. It feels like it carries a politically problematic judgement. And it does not convey the meaning of the term ā itās most important job.
seems like this would be useful information to expose beyond just through styles. i'd be concerned if a page exposed a bunch of visually changed fields that indicated "these fields have changed", but there is no programmatic exposure of such for people who can't perceive the style changes. Existing pseudo-class styling like :placeholder-shown
, :invalid
, :user-valid
, :empty
, etc., seem like they cover a lot of use cases and are associated with a programmatically exposed state - but just "this was changed from one valid value to another", how might that be relayed?
Sorry that I missed the call! Good points were brought up there! So it obviously needs to be precisely defined what actions cause this pseudo-class to match.
As stated in my initial comment, as a user I'd expect it to match whenever I interacted with the form control and changed the value it had when the page loaded.
I am leaning towards counting autofill to that, as long as the user has chosen the autofill option.
Also, we need to consider how this works in context of single-page applications. In that regard, is the state reset - i.e. the pseudo-class does not match (anymore) - when the value is changed programmatically? I'd say yes.
That's also a reason why :is(:user-valid, :user-invalid)
isn't sufficient.
One more question is, what should happen if the user changes the value back to the value that was initially set? I'm unsure about that but I tend to think that the pseudo-class should not match anymore in that case.
Regarding the name, I prefer one that makes it clear that there was some user interaction. This could simply be :user-changed
, or :edited
. Therefore, I'd exclude :changed
as that sounds like user interaction isn't necessary, :dirty
because of the reasons @jensimmons mentioned, :user-dirtied
for the same reasons, and :user-interacted
because "interacted" doesn't mean changed.
Sebastian
So wanted to add my 2 cents: I just ran into a scenario where I have a FACE web component (Form Associated Custom Element) that is required
. I want to change the styling of the component when :invalid
, but only after the user has interacted with the component.
:host(:invalid:user-interacted) {
border-color: red;
}
Btw, I am more familiar with the term :touched
instead of :user-interacted
(Angular & angular.js use the term "touched" for example). But perhaps touched can be confusing: it implies a user has touched (using a finger?) the component.
Btw, I am more familiar with the term
:touched
instead of:user-interacted
(Angular & angular.js use the term "touched" for example). But perhaps touched can be confusing: it implies a user has touched (using a finger?) the component.
There are probably many people out there that understand the concept of :touched
, though I'd still rule it out for the reason you provided.
Sebastian
:invalid:user-interacted
Isn't this usecase already covered by :user-invalid? And it's twin, :user-valid.
@jensimmons Yes, the more I read about it, the more I think :user-invalid
is better suited. One question I still have though: what about if you haven't interacted with the form element, but you've called form.requestSubmit()
. How would you style the invalid form element after that? Does :user-invalid
still apply in that case? (:user-interacted
wouldn't either afaict).
What some in this issue seem to argue for is rather the :blank selector. To create the Material style inputs with labels that are first positioned inside the input but then animate away, what youāre interested in is if the input is blank or not. If the default value is non-empty you also want to move the label.
Developers currently need to use :placeholder-shown in combination with a placeholder attribute with whitespace , which is not intuitive and is one of the few remaining reasons why we need JS for our inputs
Does :user-invalid still apply in that case?
if a form attempts to be submitted but a user hasn't filled out required fields, then i don't see why that wouldn't be considered user-invalid. They did not meet all requirements for form submission.
We need both :dirty
and :touched
. Currently :user-invalid
does not trigger when I focus a required field and blur it. This is suboptimal when just tabbing through a form ā user should be notified in this case that they missed out on a required value. Combination of those selectors would make it possible.
Angular defines the following:
State | Description |
---|---|
pristine |
A control isĀ pristineĀ if the user has not yet changed the value in the UI. |
dirty |
A control isĀ dirtyĀ if the user has changed the value in the UI. |
touched |
True if the control is marked asĀ touched. A control is markedĀ touchedĀ once the user has triggered aĀ blurĀ event on it. |
untouched |
True if the control has not been marked as touched. A control isĀ untouchedĀ if the user has not yet triggered aĀ blurĀ event on it. |
These terms also appear in popular libraries such as React Hook Form, see its useFormState
hook.
These all seems like reasonable pseudos to add to CSS.
Regarding the relation to user-valid
/user-invalid
:
pristine
/dirty
pair triggers much earliertouched
/untouched
pair triggers much laterAlso note that an input can be both touched
and pristine
in case the user has edited the value, but then changed it back to its original value.
If user-invalid has suboptimal behavior we should fix that, imo
If user-invalid has suboptimal behavior we should fix that, imo
I'm trying here: https://issues.chromium.org/issues/365802576 https://bugs.webkit.org/show_bug.cgi?id=279503
Haven't filed one for Firefox
Having native CSS selectors for controls states would allow better flexibility though, as you can see Chromium guy who implemented it argues that current behavior is correct and in accordance with the specs. Current behavior is unacceptable per our design guidelines, which is the same as how Angular does it ā show invalid controls after user visited them, not edited them.
Having native CSS selectors for controls states would allow better flexibility though, as you can see Chromium guy who implemented it argues that current behavior is correct and in accordance with the specs.
That is true. But the html spec could be changed with agreement from vendors and tests.
Current behavior is unacceptable per our design guidelines, which is the same as how Angular does it ā show invalid controls after user visited them, not edited them.
That's how Firefox used to do it iirc, before I changed it to follow the current spec.
The current spec only says 3 things:
I believe focusing and leaving an empty required input is exactly "appropriate for highlighting an error to the user" š I would even go as far as to say focusing and leaving any invalid input should highlight it for user, but I can see how this could be up for a debate so it would be great if we could personalize this to our liking with new selectors.
Back in 2014 it was suggested to add a pseudo-class matching when a user changed the value of an element. This topic was also already discussed earlier by the CSSWG.
I want to pick up that discussion again. The idea previously was to check whether the current value differs from the default value, expressed in JavaScript syntax, where
el.value !== el.defaultValue
,el.checked !== el.defaultChecked
, currently selected options different from default selected options, etc., depending on the type of input.Suggested names so far are
:changed
,:edited
,:dirty
,:user-dirtied
and:user-interacted
.This would make
:user-invalid
redundant, as it could be expressed by:changed:invalid
.Sebastian