w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.46k stars 657 forks source link

[selectors-4] Password reveal pseudo-element and pseudo-class #3934

Closed gregwhitworth closed 4 years ago

gregwhitworth commented 5 years ago

Hey everyone,

We've posted an explainer on our public site regarding a proposal to add an optional psuedo element to the <input type="password"> as well as a :revealed psuedo class. The explainer delves into the user and web research we've done as well as telemetry we've added that support the addition of this element and class.

The proposal is as follows (copied from the explainer for ease of discussion):

Proposal:

The goal of our below proposal is to enable two key aspects:

This proposal is to include this as part of CSS Selectors Level 4 with the addition of the following specification text:

The ::reveal pseudo-element

User agents may implement the reveal pseudo-element on inputs that have type=password. If the user agent does implement this pseudo-element the following rules must be followed:

Toggling between revealed and obscured

Allowing for ease of author adjustment

Showing, hiding password reveal element, obscuring the password

Following events would show a password reveal element:

Following events would prevent password reveal element from appearing:

Following events would obscure password and hide a reveal element:

Supported styles

Only the following CSS properties can be applied:

The :revealed pseudo-class

User agents that implement the ::reveal pseudo-element must also implement the :revealed pseudo-class on the password input. When a user invokes the ::reveal pseudo-element the pseudo-class should be applied to the password element. This will allow authors to provide different styles when the password is either revealed or not.

Example

Here is an example of an author that wants to show an eye image to reveal and a closed eye image to hide the password again.

<input type="password" />
<style>
input[type=password]:not(:revealed)::reveal {
    background-image: url(my-eye-image.png);
}
input[type=password]:revealed::reveal {
    background-image: url(my-eye-image-revealed.png);
}
</style>
jonjohnjohnson commented 5 years ago

@gregwhitworth did you mean this in the third line of your example?

input[type=password]:not(:revealed)::reveal
heycam commented 5 years ago

Without having looked at the proposal in much detail yet, my first thought is that there are other, similar widgets that are often embedded in <input>s, like an (x) button that clears the input. Is it worth trying to think of a general mechanism for allowing authors to place these widgets inside an <input>?

heycam commented 5 years ago

(Although I suppose a password revealing button does need access to some internals to actually do the password revealing, unlike the (x) button.)

Crissov commented 5 years ago

Indeed, sounds a lot like (interactive) ::marker. 😈

gregwhitworth commented 5 years ago

@heycam I'm fine with that - clear is something we've also considered and seen quite a bit of usage of -ms-clear across the web. Something I've seen in the past (can't recall where though) was ::action which would cover the individual input type interactions. For example one can imagine input type="search" also having something similar. At any rate, bike shedding the names is fine. I'm not sure if the psuedo classes should follow the same generalized statement because not all of them you'll want to adjust in the same manner as password. But as I said, feel free to bikeshed.

gregwhitworth commented 5 years ago

@jonjohnjohnson yep - good catch, wouldn't want to show the same icon in each state. Fixed :)

css-meeting-bot commented 5 years ago

The CSS Working Group just discussed Password reveal pseudo-element and pseudo-class, and agreed to the following:

The full IRC log of that discussion <heycam> Topic: Password reveal pseudo-element and pseudo-class
<heycam> https://github.com/w3c/csswg-drafts/issues/3934
<fantasai> github: https://github.com/w3c/csswg-drafts/issues/3934
<heycam> fantasai: Greg posted an issue where he wanted to ask for a pseudo-element
<heycam> dbaron: and pseudo clas
<heycam> fantasai: for when passwords have a show the password switch
<heycam> dbaron: [demos what the Windows UI looks like]
<heycam> dbaron: in many cases, users with good 30 char passwords, want to make sure they didn't make a typo
<heycam> ... Edge has this, and it's nice
<heycam> hober: sites work around this by writing terrible scripts to change input type=password
<heycam> emilio: that is a security issue
<heycam> hober: harder for password autofill to work
<fremy> q+
<heycam> jensimmons: is the proposal to create a pseudo to style the two states?
<heycam> AmeliaBR: the proposal is to style it if the UA provides it
<heycam> dbaron: two pieces. one piece is a pseudo class that matches the control as a whole, when the pw is revealed
<chris> Android also has this reveal-password button
<heycam> ... the other is a pseudo element, that matches the toggle thing, so you can use a different image for it
<florian> q+
<heycam> fantasai: my qn is, is it important to make this stylable?
<heycam> Rossen_: that's what we started with. back in IE 10, there was a demand for this, botth the x button on input type text, and the reveal on password
<tantek> the "x" button? is that the "clear field" button?
<heycam> ... and so there was a lot of web sites that started to fight with the pseudo. until they figured out how to use it
<heycam> ... at the time, it was a prefixed impl
<heycam> Rossen_: most sites ended up with two "x"s, or two reveal buttons
<fremy> @tantek: yes
<heycam> ... having a predictable way to turn it off, at least, is why we ended up with this being stlyable
<heycam> fantasai: I'm figuring there's a use case for having it. but is the use case strong for stylable?
<heycam> Rossen_: it's as much as making any other control stylable. should contrls be looking native? stylable?
<jensimmons> q+
<dbaron> (another thing that goes wrong when people use input type=text for things that are actually passwords is that mobile keyboards might try to remember the password for their autocompletion, whereas I think they're pretty good about not remembering things that go in password controls)
<heycam> fantasai: but it should be keying off the font?
<heycam> ... should use the same color and size as the text inside the box
<heycam> Rossen_: by default that's our Edge behavior
<heycam> ... not sure what every author will want
<heycam> ... they might want this google style button with a large eye
<myles_> q+
<fremy> q-
<tantek> "large eye" so is that asking for both dimensions and image customizability?
<heycam> una: every time I see form elements, I can see designers wanting to match brand styling
<heycam> ... makes sense to adjust the element with a pseudo. that's a common pattern, would be good to make it easier for developers
<Rossen_> q?
<AmeliaBR> q+
<Rossen_> ack florian
<heycam> florian: 2 points. I'm confused by the pseudo class, not so much with the pseudo element apart from hiding it
<heycam> ... just changing the color of it sounds weird
<fremy> @Chris__: (to answer your long-gone question, the Edge one used a push-to-reveal as well, but for screen readers, that wasn't possible, so we switched to push-to-toggle-reveal instead so that screen readers can switch to text input)
<fantasai> s/weird/weird if you don't know really what it is/
<heycam> ... second, we have from a year back, a resolution for something that hasn't made it into a spec, which is complementary to this
<heycam> ... opt in for a non-password field to look like a password field
<una> q+
<heycam> ... I think we resolved on something in CSS UI to opt in to the hidden display
<heycam> ... these two thins probably interact
<heycam> dbaron: one thing I missed saying is that the intent of the pseudo element that the things that are stylable are widht, height, background-image
<heycam> Rossen_: and it could have state
<heycam> ... if it's sticky, e.g.
<astearns> yeti peeking at your password UI: https://codepen.io/ankitashodhan/pen/mxxjpY
<Rossen_> q?
<Rossen_> ack jensimmons
<heycam> jensimmons: I agree with una that the use case is strong. replacing the eyeball with an icon that matches the styling of the site is one
<heycam> ... someone might want to put a red border around the input when pw is revealed
<heycam> ... I think CSSWG so far has been reluctant to allow styling of form controls
<heycam> ... but this is a newer one, and i think we're moving towards solving stylability
<Rossen_> ack myles_
<fremy> For people curious, here is when we standardized Apple's proposal:
<heycam> myles_: this idea of the reveal pw icon is a good one
<fremy> RESOLVED: input-security: auto|none in UI 4 and applies to input type=password only
<bkardell_> is it actually a newer control?
<fremy> https://github.com/w3c/csswg-drafts/issues/2495#issuecomment-380397331
<heycam> ... if sites start changing icons, maybe every site will have a different looking passwrod field
<heycam> ... which is harmful for web security
<heycam> ... trains users to type pw into sketchy things
<tantek> q?
<fantasai> myles: good proposal, but replacing image seems problematic
<tantek> But Google does it (changes the icon) so it must be ok right?
<heycam> myles_: on iOS it's a deliberate feature to make input type password look the same as system password entry fields
<fremy> q+ since I'm confused with what myles said
<fremy> q+
<heycam> chris: we don't allow style sheets to change the lock icon in the address bar
<fantasai> Florian^: if all password fields look the same, then users are used to typing into things that looke like that ... if they all look different, then they adapt to typing in the password into anything
<Rossen_> q?
<heycam> fremy: but you're already shipping input-security
<Rossen_> ack AmeliaBR
<fremy> q-
<heycam> AmeliaBR: heard a strong need for something not in the proposal, which is detecting whether the UA will be displaying a pw reveal
<heycam> ... or the clear field button
<heycam> ... argument for styling is more superfluous
<jensimmons> q+
<heycam> ... from usability perspective, having these things look different everywhere isn't necessarily good for users
<heycam> ... I was fighting recently with a site that was breaking the pw reveal button, because the focus kept getting lost
<heycam> ... could imagine all kinds of way s to make the button unusable
<Rossen_> q?
<tantek> "fussy designer could get rid of this usability feature" <-- this
<heycam> ... in general, CSS doesn't mandate good design, authors can shoot themselves in the foot, but when this is a very strong security / usability issue, not sure what the argument is
<florian> q+
<heycam> .. other thing was what Jen brought up; we have this much broader scope of exposing subcomponents of replaced elements, if we do this it should maybe be part of this much larger scope
<heycam> jensimmons: that wasn't my point
<heycam> una: I wanted to speak to AmeliaBR's point
<Rossen_> ack una
<heycam> ... I can see the perspective of wanting similar UX
<heycam> ... right now things look diff because people must reimpl them
<heycam> ... so I think it could help with unification
<heycam> ... having a standard for pw fields
<AmeliaBR> q+
<heycam> ... and could be overridden if the team wants to
<tantek> The pseudo-element does sound like a bit of a footgun, as it burdens webdevs with doing it in such a way that works across input fields on different desktop/mobile OSs/platforms etc. which is a lot more than they may expect they have to do
<heycam> ... to the second point, does this span any replaced element? what about telephone fields? maybe validating want to little check mark in there
<heycam> ... should we be thinking about form elements as a whole?
<heycam> fantasai: that's a good point that that exists
<Rossen_> q?
<heycam> ... placing that check mark and making sure it doesn't overlap the contents of the field. this doesn't solve that
<heycam> ... I would be curious to know, if we have this pw reveal implemented across all browsers, and waited a year, would there still be such a high demand for doing custom ones? or would it be adequate to just let the browser do it?
<heycam> una: I've seen very design system have different designs for these elements, so I think the demand iwll continue
<heycam> Rossen_: so eveyrthing else would look as designed, except hte icon?
<chris> q?
<heycam> fantasai: but these icons don't have a lot of presence
<heycam> una: looking at these 2 examples. the material design one. the second one was the Edge one
<heycam> ... can't really mix and match them
<Rossen_> q?
<Rossen_> ack dbaron
<heycam> dbaron: I had three comments. one, AmeliaBR asked how do you detect this
<dbaron> @supports selector(::reveal)
<heycam> ... one answer is that you could use @supports for this selector
<heycam> ... impls would only suppor this selector if they have a pw reveal mechanism
<heycam> TabAtkins: I don't like that assumption. then they'll have broken style rules
<heycam> AmeliaBR: that already hapepns with pseudos everywhere
<fantasai> ...
<fantasai> dbaron: Somewhat, but also today's impls don't support that pseudo
<florian> q?
<fantasai> dbaron: fremy pointed out that a year ago we agreed to add 'input-security' property that controls whether or not the password shows up
<fantasai> scribeNick: fantasI
<fantasai> dbaron: If that property has influence on whether the reveal pseudo-class matches
<fantasai> dbaron: then we can't do both
<fantasai> dbaron: You can't have a property that controls whether a selector matches
<fantasai> dbaron: This is not a problem for the pseudo-element, though
<fantasai> dbaron: We don't want to create cycles with input:reveal { input-security: ... }
<tantek> FYI: https://github.com/w3c/csswg-drafts/issues/2495
<heycam> ScribeNick: heycam
<heycam> florian: talking about this I said that we had introduced this prop, for arbitrary things, which is not what we resolved. we resolved none and auto, for make it able to turn it off on pw fields
<heycam> ... not to hide it on non-pws
<heycam> fantasai: that problem still applies
<heycam> ... just limited in scope to input
<Rossen_> ack florian
<heycam> dbaron: the 3rd comment is that there was a bunch of discussion baout WG's history of not styling form controls
<heycam> ... some of this is that there was an assumption that really form controls are a big problem to tackle, and there was a bunch of ongoing work that was supposed to help us tackle this problem, which at this point has taken 14 years longer than expected
<heycam> ... Web Components is a thing now
<heycam> ... part of the idea of the origin of WCs is to help us figure out how to expose styling of form cotnrols to the web
<heycam> ... we should at some point think about whta we can do that is still web compatible, we have more compat constraints now
<heycam> bkardell_: it would be helpful to work with people how make custom control libraries
<heycam> ... I want to be in control of these things, but not these things? it's not simple
<Rossen_> q?
<heycam> Rossen_: there will always be native controls
<tantek> Also FYI: https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-security
<Rossen_> ack jensimmons
<heycam> jensimmons: myles_ what you brought up was interesting, keeping UX consistent as a security concern, pulls it out of the rest of the form controls debate
<heycam> ... if we wanted to pull those concerns up, the web should get the pw off the web page, I wonder if the genie is already out of the bottle
<heycam> ... I don't have any answers, but there's something interesting there
<florian> q?
<heycam> ... solving passwords on the web ... not going to happen here
<florian> q+
<tantek> Does the CVV use-case apply here? (e.g. is that a use-case for -webkit-text-security ?)
<heycam> fantasai: I don't think Web Components is the answer to all of this
<bkardell_> my above comment was intended to say that there are orgs and frameworks providing custom elements to other people now, and they seem to have similar challenges as browsers now
<florian> q-
<heycam> jensimmons: we'll get to the form controls eventually, just ship these pseudos for passwords?
<Rossen_> ack AmeliaBR
<Rossen_> Zakim, close q
<Zakim> I don't understand 'close q', Rossen_
<heycam> AmeliaBR: is there any interest in browsers that don't have this feature, adding this feature?
<Rossen_> Zakim, close queue
<Zakim> ok, Rossen_, the speaker queue is closed
<heycam> ... is there any work being done on the HTML side to have this as a state of the input element, that is revealed on a DOM level? rather than just through CSS
<heycam> ... right now, I don't think there is any DOM level way to detect when someone toggles the reveal or not on their native input
<heycam> ... not sure whether it's a security concern, but it would expose info that's not already exposed
<heycam> ... which may be something to consider
<heycam> ... and the discussion maybe should happen at a DOM/HTML level
<heycam> ... on dbaron's concern about circularity, don't think it's an issue
<heycam> ... wouldn't want the revealed state to be based on a css property, but a state maintained by the input element which knows whether it's revealed or not
<heycam> ... and the UA sheet can say do something based on it
<heycam> ... but again that depends on the idea that the input element is able to maintain the state of whether it's in the reveal state, which is an HTML/DOM question
<heycam> myles_: when we discussed text-security a year ago, we spent a lot of time talkingabout the behavior of mobile browsers, where you press a key and it shows for 0.5s
<heycam> AmeliaBR: it's a state that exists only as long as you're pressing the key, vs on or off
<heycam> myles_: it's per character tho
<heycam> AmeliaBR: as you're typing? the char you just typed?
<heycam> myles_: yeah
<heycam> una: I liked AmeliaBR what you said about HTML
<heycam> ... reminds me of the media control state
<heycam> ... it lets them decide whether to show the widget
<heycam> AmeliaBR: so the author could make a custom control that toggles the pw reveal state?
<heycam> una: yes
<heycam> AmeliaBR: currently most impls switch the input type from pw to text, awkward for a11y
<heycam> ... bad for autofill
<heycam> ... if authors could impl a custom pw reveal without changing the fact that it's pw...
<heycam> florian: that's what we resolved 1yr ago, not that it was a DOM prop tho
<tantek> q?
<tantek> q+
<heycam> ... the details of whether it's showing only the last char, or the whole text, that's "auto"
<heycam> ... but only applies to input elements
<heycam> ... we didn't follow up on that, but we did resolve it
<heycam> AmeliaBR: that doesn't let the custom control allow you to turn the revealing on and off
<AmeliaBR> s/allow you to/detect whether the user agent can/
<heycam> florian: should we reopen that 1yr old question to see whether we should have it in HTML/DOM instead?
<heycam> tantek: I think we want this for cvv fields too
<heycam> ... so yes
<heycam> florian: the control we have didn't allow you to hide things. only reveal things which are hidden by default
<heycam> ... didn't want them to make normal text fields look like pw fields
<heycam> florian: the earlier resolution, we decided we only needed auto/none
<heycam> ... when WebKit brought this to the group, was to stop having non-pw fields for pw-ish purposes
<heycam> tantek: that sounds like denial of the use case
<heycam> florian: does sound like we should reopen that issue
<heycam> ... should we be able to hide things revealed by default, and whether it should be a DOM thing
<fremy> @myles @myles_ why did you mention this to me: // text-security was implemented in 2007, 12 years ago
<heycam> myles_: search fields often have a manifying glass image. if this will have an icon thing, it should use the same mechanism
<heycam> Rossen_: in Edge, it's the same mechanism. there's an action pseudo, for clear, search, reveal
<heycam> hober: can't resolve to add the pseudo class but also have input-security
<heycam> tantek: it's not optimal
<heycam> dbaron: needs to be clear what the two things do. it's still possible
<heycam> emilio: could have weird states with non-revealed text but still matching the pseudo
<heycam> fremy: [...] if the user clicks the button it would override what's set
<heycam> dbaron: does input-security control whether there's a reveal button or not?
<AmeliaBR> q?
<heycam> ... someone needs to write down a defn, to check whether the input-security is reasonable, the pseudo is reasonable, and whether they interact well or not
<heycam> AmeliaBR: I think we've brought up a number of issues, would be worth updating the explainer/proposal to hash out these details
<heycam> ... and generalizing to other action buttons. greg's not here, just throwing it back on him...
<heycam> jensimmons: from Greg's tweets sounds like he's diving into stylable controls
<heycam> tantek: 3 interrelated issues, resolving on one will make it harder to make sensible resolutions for the others
<heycam> florian: come back with a complete proposal
<heycam> tantek: hoping the "things that want a reveal button which are not pw fields" use case can be handled
<heycam> -- 15 min break --
<tantek> heycam++
gregwhitworth commented 5 years ago

Sorry for the delay on this, finally had a chance to sit down and parse it all out. If I understand this thread correctly, the request currently on me is to:

  1. Define what happens between the revealed psuedo-class & input-security
  2. Consider an over-arching and uniformed approach for styling form controls not necessarily this one alone
  3. HTML/DOM state for revealed

Is there anything else I'm missing? @litherum @fantasai @dbaron @AmeliaBR @bkardell @atanassov @frivoal @una @jensimmons @tantek @heycam @FremyCompany

therealglazou commented 4 years ago

Hello Greg. I have a few concerns I would like to share here. All of that comes from my experience as CTO of a company releasing a WebExtension containing a password manager. Disclaimer: I don't work there any more and my words represent my own opinion only.

The main issue with your proposal is the following one: as of today, "Show" buttons exposed on the Web in password fields are added through extra elements and these elements allow third-party tools - like password managers - to detect UI collisions with the UI thingies they want to add themselves to password fields. If we move to a pseudo-element added to <input type="password">, that will be extremely difficult for password managers to continue doing so. Furthermore, styling dynamic changes on that Show button is going to be tricky since pseudo-elements are always last in a selector, after pseudo-classes.

In short:

In my opinion, the requirements here should be the following ones:

  1. the solution should be generic enough to apply to all <input> representing a text field, including <input type="search"> and its omnipresent clickable mag-glass button.
  2. input field buttons should allow all possible behaviours: simple buttons, dropdown menu, on-hover tooltip, etc.
  3. it should be possible to add user-defined (JS-based) behaviours to an input field button
  4. ability to fully style input field buttons
  5. ability to add a localized tooltip to input field buttons
  6. ability to query the DOM to retrieve the position/geometry of input field buttons
  7. extensible solution allowing password managers to add their own input field buttons without UI collision with the existing ones (for instance added in reverse direction from the end edge of the input field)
  8. it should allow to get rid of existing solutions absolutely positioning a button inside a text field and tweaking the type attribute of the input field. On some web pages, it's even worse: the reveal button switches between two different elements, one <input type="password"> and another <input type="text">...
  9. A11Y is a must

More about a potential proposal later.

therealglazou commented 4 years ago

Hi again. I gave myself a bit more time to confront the requirements above to the ecosystem, and in particular to the design of the 100 most visited web sites of the world and the main WebExtensions available. After careful review, I don't think that the original proposal above based on :revealed and ::reveal is a desirable solution. Let me explain:

  1. the only opt-in/opt-out option is to use display: block or display: none on the ::reveal pseudo-element. That seems to me pretty hacky.
  2. it's going to be extremely hard to attach anything, and in particular a page-defined localized tooltip or a specific behaviour, to the pseudo-element.
  3. the behaviour of the reveal "button" will be browser-defined while I deeply think it should be user-defined.
  4. it's not extensible to other buttons/actions
  5. the burden on web sites and WebExtensions is a bit too high since the position of the reveal button will be extremely painful to detect

So I think a better option is to completely change the point of view and simplify the proposed solution:

With the above, web sites and extensions implementing a Show button in password fields will be able to drop their existing hacky code easily; web sites and extensions adding extra UI elements to text fields will be able to do so in a way that does not collide with existing UI (and that's a VERY big plus), getting rid of usually hacky and very expensive code; extensions willing to "disable" the Show button will be able to do it; the solution works for mag-glass in search fields, powerful dropdown menus in combos, etc.

Looking forward to reading your opinions.

gregwhitworth commented 4 years ago

@therealglazou Thank you so much for the feedback Daniel. As I noted on LinkedIn, we've been digging more and more into controls/components and we probably won't go the way in which we originally proposed as we want to ensure that every usecase is possible; as you noted above. I'm intrigued at the helpers solution you describe, but I don't quite follow it. Mind sharing some psuedo code?

therealglazou commented 4 years ago

  <head>
    <meta charset="UTF-8">
    <title>Input field helpers</title>
    <script>
      function ShowOrHide(aElement) {
        const id = aElement.id;
        // why don't we have a attribute selector for coma-separated lists?
        const field = document.querySelector("[helpers='" + id + "']")
                      || document.querySelector("[helpers^='" + id + ",']")
                      || document.querySelector("[helpers$='," + id + "']")
                      || document.querySelector("[helpers*='," + id + ",']");
        if (field) {
          field.revealed = !field.revealed;
          aElement.src = field.revealed ? "hide.png" : "show.png";
        }
      }
    </script>
  </head>
  <body>
    <input helpers="showButton"
           type="password">
    <input id="showButton"
           src="show.png"
           onclick="ShowOrHide(this)"
           type="image">

  </body>
</html>
FremyCompany commented 4 years ago

Daniel, I have the impression your design assumes this control won't be available by default on all inputs unless website authors really take care of adding it?

If that's the case, I would like that to be revised. I want my browser to have this reveal button by default, and it should work consistently on all websites (barred really good exceptions). I don't mind websites adding new behaviors to the fields, or disabling the default behavior if it doesn't suit them, but I don't want every website to have to be updated to continue to get the experience I have in Edge today.

therealglazou commented 4 years ago

@FremyCompany you must clearly not impose such a constraint to all web sites. Forcing a Show button on password fields can be a HUGE security issue in some high-security environments (defense, intelligence, etc.).

gregwhitworth commented 4 years ago

@therealglazou I don't buy that argument, if someone is in proximity to read your password then there are other issues. That said, they can simply hide it via the psuedo element. That said - as I noted above due to the constraints we're going to go back and revise this. I have an expectation that we'll still want to define an anatomy that has this in by default but it will be up to the UA if they want to expose it or not. That isn't a discussion for this WG however, I'll be closing this thread for now until I have an updated proposal.