Filling in a form is never delightful. It’s a tedious interruption in my flow. Just let me get past it with minimum cognitive load.
Would a normal person try to do that or would they just reload the page and start the whole form over again? Or would they just leave the website and never come back?
Many people just abandon their intended action when simple usability things are not right because your sales experience is sorta a "first impressions" thing (bit of a generalization but yea).
It had so many bugs when I tried it, and it has at least as many now.
For example: in the first demo, type the card number 1234567812345678. Works nice, eh? Now try again with 1233567... oh wait, let me go back and change that second "3" to a "4". And it's broken.
pulling up a numeric keyboard to enter a cc number is helpful, but also lacks a space key, making it hard to viaually verify a 4-4-4-4 pattern. yes, there's luhn, but that doesnt work until you're finished (same problem with formatting post-entry, eg onblur/onchange)
for entering a date, most numeric keypads lack /.
thankfully, phone entry is mostly covered with type=tel. which is numeric + symbols, so i end up using it as a hack for some other numeric types, as suggested on SO.
i would rather just type big numbers instead of fumble with symbols or tiny keys on a full keyboard for numeric inputs.
So much work is put into making various pointless design gimmicks recognize whether they're displayed on mobile vs. desktop. Why not recognize whether the user is on mobile (and thus likely has crappy keyboard), and conditionally enable those convenience factors?
Also, I feel this problem was solved 20+ years ago with CD-key entry boxes. You'd have a row of text boxes, 2-4 characters long each, but they behaved as if they were one large text field - the focus correctly jumped between the boxes as you wrote or erased stuff.
Unless you missed one character and then everything was misaligned and it wouldn't let you just insert one in the middle so you had to delete everything after that point and start over. Meanwhile, your pirate friends were already at level 10.
No, that's just the default iOS keyboard, meaning the problem is Apple. My Pixel's keyboard sensibly has a space button, as do most 3rd party keyboards on iOS.
to make the right one pop up in ios you have to do stuff like pattern=[0-9]*, but that becomes restrictive, too.
For example, if I want to type in the date "2017-03-30", but I accidentally type "2017-02-30", this library silently changes the day in addition to the month, leaving me with "2017-02-28". I suppose you could use this to illustrate how fallible humans are, but if your goal is to minimize errors, you simply can't autocorrect number fields. You must show error messages.
> no amount of clever prediction will put it back in the right place in all cases
If you're instead changing your argument to say that it's impossible to do _well_, that's a different argument which I also disagree with: most implementations of tab-completion definitely have more fans than opponents. Not to mention keyboard shortcuts like Cmd+I to bold, or Cmd+B to italicize. Or even OS features like copy/paste. Many features require modifying the contents of a textbox, and it's far from impossible to do well.
This here is implicit alteration of user input, and the real question is not whether it can be done correctly (in this case, I vote for "maaaybe in theory; impossible in practice"). The real question is why do it at all? It only confuses and irritates people, which makes them make more errors and also break their flow.
(Hell, it's not an issue if that's just one field on a random sign-up field of some fly-by-night shop. But those "brilliant" UX ideas tend to find their ways to software people use for work - say, managing listings in ecommerce shops. There, such ideas cause many people to lose a lot of time, and by extensions their employers to lose a ton of money.)
If you want to narrow it down to implicit alteration: Syntax highlighting is implicit alteration. And people love it.
So are a lot of WYSIWYG features, like Enter inserting a new paragraph or a new bullet point depending on context. Or tab completion itself, in the sense that it replaces the "insert tab" feature of the Tab key. Or URLs automatically transforming into links.
Explicitly with regards to Cleave.js-style auto-formatting, I personally like it (for the same reason I like syntax highlighting) and I assume many other users do too. Someone further downthread mentioned an AB test showed improved conversions:
That's only a change of formatting that's otherwise inaccessible to the user. Effects like colors and bold/italics aren't part of the code, users can't and won't try to insert them manually - they're an extra data channel, orthogonal to what users type in, and thus free for the application to use.
You want Cleave.js-style implicit? Think automatic autocorrect on Windows and MacOS. That one generates quite a lot of justified criticism - besides being a huge annoyance when dealing with proper names, brand names, peoples' names, addresses, etc., it can create life-threatening situations.
> Someone further downthread mentioned an AB test showed improved conversions:
They did, but I honestly don't buy it - not without knowing much more about the scope and methodology of the test in question (see my response somewhere in that thread for details). "A/B test told us that" is the new "I was only following orders".
 - https://twitter.com/slatestarcodex/status/944739157988974592...
What? I didn't change my argument, that's what I said in the original comment you replied to.
All of your examples are things that _don't_ happen while you're typing. If you want to dispute my statement that all formatting should happen on blur, fine; you can expand that to include any time the user isn't typing. The issue is when you format the text while the user is actively trying to enter it, you'll mess up the cursor position and easily get into a situation where you can't add or remove a character for some reason because the formatting considers whatever you're trying to type invalid. And you'll also notice that I explicitly said in my original comment that you can't get it right _all_ of the time, and those times when you do get it wrong prevent the user from completing their task because of a superfluous feature. This is terrible UX and once this happens to a user they will never trust your software again.
I originally thought you meant it was impossible to fix the cursor position after it was messed up. So I was just saying it _was_ possible:
(Which _can_ be done seamlessly while the user is typing.)
So everything since then felt like moving the goalposts. But I think in the end that was just a misinterpretation.
I mean, I do also disagree that it's impossible to do well, but in hindsight that's not really something I want to argue about further.
The implementation of the date field mask could be better.
It looks fantastic, but, for example, the YYYY/MM/DD field, I can't just write 19/2/23 or whatever (explicitly entering the delimiting slashes), I have to follow the prescribed format, 2019/02/23 (oh, ok thankfully 2 gets filled to 02 automatically).
Try 1/20 in the MM/YY field. Doesn't work.
It seems fairly simple to fix; when the user types a delimeter, trust them.
I think this is exactly the point: to guide users toward inputting data in a standard format.
But then why does 2019/2/24 get automatically expanded to 2019/02/24 (adding the leading zero to the month), but not 19/2/24? As I said, it should be a fairly simple change to respond to delimiters, and marshal the input into the required format without forcing the user to slavishly follow the exact prescription.
But if the intent is to do that, then it's a trend I do not agree with at all.
i've never seen a card that specified expiration month with a single digit. google images for "card expiration" does not bring up any examples either. a placeholder="MM/YY" should make it clear that both are needed.
While it's true that there's a leading 0 on the card itself, there's no reason not to just split on the / and convert both sides to integers.
I agree this is bad practice. I have similar code in an app I'm writing right now, I also didn't consider the usability issues or wierd delete cases. Gonna remove the code after reading this thread.
Falls under trying to be clever.
I think slightly increasing the space between groups of numbers might be acceptable? Anything that magically inserts characters seems to be problematic.
Invest all the effort into reliable, flexible and intelligent parsing of whatever the user types in. Even in 2019 I find web forms (banks excel at this) which complain about "invalid" characters instead of ignoring them.
Incidentally, this idea of "let's improve the standard user interface to make it easier for ORDINARY PEOPLE" is not limited to web forms. Browser URL fields are a playground for programmer creativity and I'm regularly baffled by their behavior: autoselecting the entire input, suggestions completing what I typed even though I never asked for it, and similar ideas.
I am currently using Cleave for a project where the customer unequivocally requested this kind of functionality. Specifically I need to implement phone masking, date masking (no calendar pickers except native mobile ones allowed), and number and currency validation and masking. Cleave was the least opinionated library of its kind that I found.
On top of that I want the form to not be stupid. Let me enter 555-555-5555 or 5555555555 for a phone number. Let me enter 1111222233334444 or 1111 2222 3333 4444 for a CC number. Let me enter 01/19 or 1/19 for an expiration date.
Trim whitespace on submission too. Don't force me to jump through hoops the code should be smart enough to deal with. Don't correct this kind of text in the field, correct it on submission. If something is ambiguous then add that to your validation message.
We are seeing this lib as users who get frustrated with marketing forms. There are other use-cases out there. I work with non-profits, where they may not have the budget for fancier validation, so this helps a lot.
It may be possible, but I have yet to see a perfect implementation.
Cleave.js is the top starred option
Edit: the #2 library, text-mask, doesn’t seem to have the issues with the date field
Phone numbers are something you dial into a phone. They are not a alphabetic ISO code and then some numbers. Country codes and international dialing codes are NOT 1:1. North Korea for example has two dialing codes but is one county. Many island nations share the US's +1. Staphones have their own dialing prefixes that don't correspond to an ISO country code. With all due respect, this code is a disaster and it is guaranteed to lead to problems when one of these many edge cases is hit.
cleave.Date(...), cleave.Phone(...), etc.
then each of those constructors could implement specific options that are relevant. As it is now, you could have an onCreditCardTypeChanged() method on a date input. And if you did it in a manner like I’m proposing, you’d be able to import just the specific formatters you need, allowing your module bundler to strip out the rest.
Personally I prefer my data entry to be a simple text field so that I can use backspace, or clipboard paste, or insert/delete from the middle normally.
Meanwhile, the UI can show its interpretation of what I entered just above the field. For example, if
I enter a date field 2/25, the software could show its interpretation (02/25/2019) as I type, allowing me to quit typing as soon as the interpretation is correct. Likewise with credit cards: it isn't a big problem hitting a space bar to separate, but that's my choice.
In other words, the beautiful formatting is good, but keep the input field and the eventual rendering of the field separate.
Are you expecting websites to show a giant pop-up menu of 2-letter country codes to users? Or are you expecting websites to hardcode one country, and reject phone numbers which don't match that pattern? And what about extensions?
For dates, most browsers support form type="date" and the like. That's going to be better than whatever you use here.
For credit cards, it's fine, because 16 decimal digits is a universal standard. For anything else, it's going to cause as many problems as it solves.
The credit card example gives us purely cosmetic changes and it makes sense to apply them in real-time so the user receives important feedback. The other type is the application of strict formatting, like in the date format example. It's really nice to infer 1992223 as 1992/02/23, but it robs some control from the user. As we're already inferring what the user is trying to say, we could show them 1992/2/23 to give them feedback and apply the transformation before sending the data, thus having the best of both worlds.
Also if you tell me the format is 00:00:00 then I'm going to type digit digit colon digit digit colon digit digit but instead you auto inserted the colon which means now my typing and correcting muscle memory is doesn't match. I typed 8 characters so it should take 8 key presses to backspace or 8 characters to go left.
Please don't use these on your site
One request I didn’t see: money formatting.
Probably for a good reason. Formatting currency should be handled by the i18n system, because that's what it is.
Take one thousand dollars in US currency, it can be displayed as:
$ 1 000,00
and more. And that's not even counting negative numbers which can change their display format based on the industry it's used in, let alone the language.
Then add in other currencies in different locales, often the currency symbol is after the currency, some locales use different spacing, some don't have a decimal to their currency in common usage, some use the same symbol for different currencies ($ could mean USD or CAD or more and in some cases that can be a big mistake) and a LOT more edge cases.
The only way to properly address this is to bring this as native HTML5 components. Then different UX paradigms, like desktop and mobile, can properly handle complex input.
This shows the shortcoming of web UI. You cannot properly address shortcomings of browsers on low enough layer. It is not an issue for native apps.
They are not just storing a hash, as that would prevent them from offering the data back to you to fill in passwords et al. And they are not just storing it locally * , I assume that is for your benefit as well, maybe if you switch computers?
* This I know from a popup on Vivaldi, which never informed me it is sending my passwords to Google for "safe"keeping, until I tried to change a password and it told me I need to login to my Google account....
Chrome is pretty clever these days with payment details and tries to help you keep a "wallet" so-to-speak which acts like an "autofill" feature. Do some searches around Web Payments, Payment Request API, W3C Payment Request, blah blah - let's just say it goes a lot deeper than basic autofill =)
Now for siphoning. That attack (as far as I know) wouldn't be allowed to happen. Chrome WILL NOT autofill your details or inject ANYTHING into the DOM until you've entered/verified your CVV. Due to security with how payments work there has to be some sort of a user interaction before any PAN is allowed to populate the DOM. This is to avoid his exact paranoia where a CC num gets entered automatically w/o a user's knowledge.
Since this is enforced by the browser I consider it to be pretty safe, and appreciate the feature in my day-to-day browsing activities =)
Back to the Cleave.js lib though - that thing is going to BARF on things like CC num autofill driven by browsers/etc. Trying to be super clever is just going to screw-up native browser capabilities.
However, I'm curious why its trending at the top of Hacker News. It's been around since 2016.
>The first (leading) digit of the IIN identifies the major industry of the card issuer.
4 and 5 stand for "Banking and financial".
>The leading six digits of the card number is the issuer identification number (IIN), sometimes referred to as the "bank identification number (BIN)".
There's a list of all 1000000 possible IINs/BINs, but it's not publicly available:
>The official "ISO Register of Issuer Identification Numbers", is not available to the general public. It is only available to institutions who hold IINs published in the Register, financial networks and processors. Institutions are required to sign a licensing agreement before they are given access to the Register. Several IINs are well known, especially those representing credit card issuers.
It's a bit like IP address blocks: there's is/was some logic to it, but to actually know which bank a IIN/BIN belongs to (after mergers, acquisitions etc) you have to look it up in the register.
Just look at the top features listed on their Github:
* CC number - doesn't actually support all PAN formats - 19 digits exist although extraordinary rare. NEVER try to do anything fancy with your CC details field because if people try to pay you and can't you've lost a customer.
* Phone number formatting - doesn't support all phone # formats. Leave this as flat text (non-numeric) or numeric for base telephone # and a text field for extension.
* Date formatting - use type="date" so you get native mobile support for date entry.
* Numeral formatting - use type="number" so you get native mobile support for numeric entry.
If you are a mod - feel free to delete this thread as many people in other parts of the post are echoing my sentiments, some with equally as harsh language (which you are not singling out).
That lib is technologically irresponsible to use and breaks user experience for a lot of people - I was trying to put a very clear warning out there and decided to be honest in my choice of words which many people have actually defended in this conversation.
We can't come close to reading all the comments on HN, so inevitably we miss ones that are as bad or worse as the ones we reply to. If you notice bad comments that haven't been moderated, please flag them (as described in https://news.ycombinator.com/newsfaq.html), since that helps bring them to our attention. You can also email links to firstname.lastname@example.org in egregious cases.
That's a pretty hostile and condescending way to talk about someone else's work. Your statement is also incorrect if applied as a general rule. I have personally administered A/B tests for this type of masking behavior on a sales funnel and observed an increase in conversation rates (specifically for credit card number masking) on our site.
Breaking up long numbers into smaller input fields CAN help with data-entry (think dyslexia etc.) but in the case of CC numbers that are of different formats (ie: VISA vs AMEX) there's no good way to "auto-format" it even if you knew the issuing PCN of the card before hand.
So - best practice generally is, ignore the dashes and let it be entered as a 10-19 digit numeric only field (or 13-19 if you're not worried about ancient cards). Just don't allow non 0-9 characters in the input via JS which is SUPER easy. Then, before submission, ensure it passes a mod-10 Luhn check to let someone know they fat-fingered it! Easy-peasy.
this is plainly wrong. you can swap the mask as soon as you know it's amex from the prefix. i know because we do it without any issues. it's 4-4-4-4 for visa/mast/disc and amex is 4-6-5. you have more than enough info by 4 digits to choose the correct mask in all cases.
edit: I want to add that this wasn't a scientific study, we did a lot of A/B tests so we felt pretty confident about it but I wouldn't claim that it's a general rule.
And before you link that "A/B Testing is Still Needed" HBR article - know that I 100% agree with it but on the premise of testing MULTIPLE solutions under the traditional "A/B testing" model. As far as you've posited in this conversation - you guys only tried one thing. You're also admitting it's not a "scientific study" so I assume you did nothing to minimize other changing variables/conditions in regards to the input masking.
TLDR: Input masking CC fields is probably a bad idea beyond filtering non-numeric/non-slash characters. I will make that generalization. I'm not convinced you've got a valid argument against that with your "A/B test" experience.
You're skeptical of people who test their business process and follow the data where it leads them rather than taking the advice of arrogant internet curmudgeons that try to puff up their opinions with flippant allusions to statistical significance and vague appeals to the authority of "board room" war stories? That doesn't speak very well for your own credibility.
> You're also admitting it's not a "scientific study" so I assume you did nothing to minimize other changing variables/conditions in regards to the input masking.
Well that assumption might make it easier for you to justify your haughty screed but it's also incorrect (you can apply that to your edits as well). Unlike you, I'm not arrogant enough to suggest that the insights I've gained in my own personal experiences are totally absolute and generalizable to every other business and circumstance.
> I'm not convinced you've got a valid argument against that with your "A/B test" experience.
That's the aspect you don't seem to be grasping; I have no reason to care about your opinion since it flies directly in the face of the data I've seen and you haven't provided any support besides your own feelings about why formatting credit numbers kills conversation rates. At best, both our experiences are anecdotal, the only difference is I'm not a dick about it.
If it was a 50% increase in signups over a set of 1000 cases, I’d be inclined to say it’s statistically significant.
Overall, seeing the UX crap produced by many data-driven companies (Google included), I have low trust in their methodology.
I would absolutely disagree with you here. It is a generally accepted "case" that additional validation barriers on conversion experiences cause users to drop off. I have seen this scientifically proven by hard numbers time and time again over my ecommerce career.
> That's a pretty hostile and condescending way to talk about someone else's work.
Sure, I'll take that criticism. I still think it's a horrible practice and would professionally advise anyone against implementing this.
I do love how we like to rip on the JS community when it's convenient for us (npm, every new framework ever, etc) but when I say a front-end lib is "hot-garbage trash" because it breaks something as simple as backspace it's over the line...
Presumably the introduction of validation barriers that don't guide the input to the intended form, then. How would the ability to type an arbitrary amount of numbers, or letters, in a credit card number field lead to higher conversion?
Sure - I'll bite. But I'm also going to point out that you're swinging to the other end of the extreme. Obviously no one in their right mind would just allow arbitrary input...
Clearly every CC number can be represented by numbers alone (by omitting the slashes). People are absolutely familiar with this and often will omit the dashes in their fields all together without any filtering of characters. Personally I key off of the "keydown" event on that field and e.preventDefault/return false on anything non-numeric. In the future, I hope the "inputmode" HTML attribute catches on with non-Chromium browsers - that would eliminate my need to do this.
After the number is entered, or (personal preference) before the form is posted, you do a simple Luhn check and show a dynamic error message RIGHT ABOVE the field saying "hey invalid CC num yo" - ideally you keep the "process" button and CC num field close to each other so this happens within the same document view without having to auto-scroll/anchor to the invalidated field.
Then, as always - ensure you have the capability to validate that data using the same rules on the back-end before it's allowed to be sent to your processor, or w/e.
There ya go - there's the "everyman's" approach to CC validation on the front-end.
It's not a validation, it's simply a mask - it does not block the user, only formats what they enter into the text field.
> I do love how we like to rip on the JS community when it's convenient for us (npm, every new framework ever, etc) but when I say a front-end lib is "hot-garbage trash" because it breaks something as simple as backspace it's over the line...
Personally, I think "ripping on the JS community" is always a waste of time; jQuery still works in 2019, if you think that's the best way to go, have at it, but even in those threads I think it's pretty rare to see someone openly regard others work with such disdain as "hot garbage".
The phone number field tries a lot of clever stuff, and when I went back and inserted digits near the start of the number it wiped half the entered digits, presumably because the temporary state didn't fit its idea of a valid phone number, so it cut off everything that was "wrong"
Changing the year in the date field destroys the months and days in some cases. Editing the month left it happily in a state with a day number of 0.
Same issues with the time fields.
I do work for GDS and while we offer a date picker for date fields in the app I work on, we also have three day/month/year fields, because date pickers are terrible for accessibility and we would fail assessment.
So is having one field that tries to magically parse what you mean into a date. Just let the user enter the numbers they want, and return a 400 when they post the form if the numbers don't make sense.
Imagine if you're blind and you try and enter a date into those `dd/mm/yyyy/` magic fields
Yep - I actually use strategy this and type="date" both depending on what the precision requirements are =)
I've always seen the "three-field" old-school method as the most bullet-proof approach for this. Plus, validation becomes super easy since you're just doing simple integers w/ranges.
> Imagine if you're blind and you try and enter a date into those `dd/mm/yyyy/` magic fields
100% - those things absolutely break down for screen reading tech/etc. That's also why I hate these sort of "input masking" libs... accessibility is a huge concern of mine.
> 19 digits exist although extraordinary rare.
this is an understatement. in 15 years and hundreds of thousands of transactions, i've never seen one.
> Phone number formatting - doesn't support all phone # formats.
depends on your customers. 99.99% of ours are US and CA. i would argue that a very large swath of businesses do not have wildly varied customers. we very rarely encounter anything other than 555-555-5555. but very frequently encounter 555555555 (one digit too short), cause customer wasnt required to add delimiters. yes, you can validate this post-entry, but still. post-entry errors are annoying, too.
> Date formatting - use type="date" so you get native mobile support for date entry.
unless you need MM/YY, right? [type=month] also sucks, btw.
> Numeral formatting - use type="number"
this allows symbols that aren't actually numeric to be entered in many cases.
i use a fork i made based on this: https://codepen.io/lagden/pen/XzLYJE
- it handles deleting from end in chrome and safari (i had to add a bit to make it work in Firefox, Edge, IE since they dont support ).
- it inserts a valid symbol even if you mistype a symbol instead of preventing entry.
- it's not perfect, and doesnt quite handle editing in the middle since it just assigns the input value. it also cannot do more complex stuff like optional chars. but it's good enough to be helpful 99% of the time and not horribly intrusive.
 e.inputType === 'deleteContentBackward'
On PANs - sure. However, I (personally) have seen odd-digit PANs but also deal with an industry that sees literally EVERY type of CC number you can imagine from all different areas of the world. Your experience (like mine) is anecdotal. But, here's the kicker - I HAVE to go with what VISA tells me to do because of their individual PCN integration requirements. If VISA is telling me "hey - it's a best practice to support all of our potential PAN formats even though 99% are going to be 16 digit" then I have to support that =)
On phone # formatting - sure. If your use case is the US and Canada things become MUCH more standardized for everything from banking data, to addresses, to (of course) phone numbers. However - I see foreign/odd phone # formats from the Americas constantly as not all the people who are here at this time have a local phone provider. (ie: travel).
I concede on number formatting - but I still use it because (IMO) it has the best/most-consistent mobile experience vs. custom libraries.
On date formatting - sure. "also sucks, btw" let's tell the users WHY it sucks because otherwise it's just trusting some random guy on the internet.
But yea - cool fork on codepen.
that's why i try not to make blanket statements without qualifications about my specific case. know your customer, and all. we also have a direct phone line prominently shown in our header, so for those who do encounter issues, they simply call in to finish their order and we're happy to sell them additional things and/or give them better pricing. it's one of those odd "worse is better" situations.
our product takes some planning before purchase and is not a commodity you can buy elsewhere (we mfg). those who start the checkout process are unlikely to leave if they encounter minor issues.
if you're strictly a reseller, with no sales phone support, or have a huge international market, then sure, a lot of what we can get away with could lose a chunk of buyers to competitors for someone else.
Just use normal HTML text entry. Showing validation errors is fine. Actually interfering with input is a huge UX mistake.
Well, it is called cLEAVE.
* "overzealous autocorrect"
* "this is everything I hate about 'modern' UI"
* "I hate this idea"
* "This is a weird API for what it’s trying to achieve"
* "...THEN select the country..my number gets deleted... I hate you now"
* "Cute, but it looks like it's trying too hard to be clever."
* "Couldn't find my country for the phone number (UK). Looked for EN and UK, eventually discovered it was GB. Hard!"
* "hot garbage trash" - wait whoops ... that's mine - seems to fit right in though!
It actually took me a few consecutive quotes before I even found a neutral sounding "should simply be solved by browsers imho" comment.
"Your response is assholish" is correct, and I will agree. However I have a visceral reaction against these anti-patterns. The web is suppose to be open, and the web is suppose to be usable by a diverse group of people (including those with disabilities). I don't care if someone built this in their "free-time", this is NOT a responsible front-end lib to use.
(And it's not about nothing, it's a perfectly valid, if strong worded, criticism about a library promoting bad UX, which is unfortunately popular, and thus inflicting UX suffering on many users on the Internet.)