Segmenting Fields
I’ve come across a handful of forms recently that required me to enter a value that might have segments, such as phone numbers, social security numbers, credit card numbers, or other identification values. They each behaved like this:
Go ahead and try to enter a number, perhaps an example invalid phone number of 108-295-4726
. This input is not logged or sent anywhere, I’m trying to prove a point, and I don’t care what you might enter, but it is important that you pick a number and try to enter it correctly. And, ideally, make a mistake or two.
On first encounter, you might not notice the problems, which is how I suspect these forms got out into the wild. The above inputs have a number of properties:
-
Autocomplete is
"off"
, which may or may not prevent your browser or a password manager from filling it for you. -
The field is segmented according to the localized formatting of the
+1
country code: 3-digit area code, 3-digit exchange prefix, and 4-digit number. -
In an attempt to be helpful, the field segments automatically focus the next segment when its input has reached the specified length.
-
You can’t paste a value in and have it bridge the field segments correctly.
These are the intended behaviors of the field, but they also have some unintended behaviors:
-
You cannot use backspace to traverse backwards to a previous segment to correct a mistake.
-
Because the field captures
keyup
events to handle its forward to the next field when full logic, you cannot use the standard focus the previous field keyboard shortcutshift-tab
to focus the field; doing so will focus the field, but the misguided logic will then place the focus immedately back on the next field. -
If you click on the field to correct your mistakes, using the arrow keys to navigate within the field to the proper position will also result in focus being shifted to the next unfinished field.
In short, correcting mistakes requires selecting the correct field with the pointer input device (mouse, trackpad, finger) and using backspace
or delete
as the first keystroke to reduce the length of the field’s content.
This is a problem.
I’ve seen variations on this pattern that will select the field’s content when clicked on, or capturing the click/focus events and applying the same shift focus to the next field when full logic, effectively preventing you from correcting mistakes as well.
There are a number of other things wrong with this simple form as well, but complicating the correction of mistakes is the primary issue.
I’ve encountered variations on this over a dozen times while interacting with government websites, banks, and others over the previous months.
In addition to phone numbers, I’ve also seen the patterns above used to input Social Security Numbers, Employer Identification Numbers, Credit Card Numbers, and other numbers with common conventions for segmenting.
I can hear the meetings at large companies now: What if they enter 108-295-4726
or 108 295 4726
or (108) 295.4726
, how is the computer supposed to validate that?
I’m sure the creators of these forms are well-intentioned — it’s easy to make mistakes when entering long strings of characters, and providing a single input such as which might allow for input that doesn’t conform to the expected pattern — nevermind that they still allow for entering invalid values.
A better pattern to work with user input is input masking. In addition to making it easier to work with localized formats, it keeps the input in one field, which allows for semantic input type attributes such as type="tel"
, and better supports autocomplete.
It still feels janky, though:
-
When you focus it, the field isn’t empty, it’s filled with masked characters. Focusing with a pointer device will put the cursor where you point, but typing will overwrite the first mask character and move the cursor.
-
The pound characters aren’t the same width as the numbers in the font I’m using, the text will shift around a bit.
Depending on your font, it might be possible to fix this through fiddling with
font-variant
css settings; but it’s not the default and#
isn’t considered a numeric character for the purposes of lining figures.
But it’s good enough for most purposes, and it doesn’t get in the way of people fixing their mistakes, so it’s an improvement. A little goes a long way, but if you’re going to enforce a pattern, just make sure it’s clear what the pattern is at all times.
In this example, both the required
and pattern
attributes on the input element are set. The pattern is conveyed via the placeholder, which disappears the instant you start typing in the field. If you were to type 108 295 4726
, the field would still be invalid (indicated by the red border).
But it won’t tell you why it’s invalid until you try to submit the form (via the “validate” button), which then gives a vague message telling you to Match the requested format. Dear reader, if you entered something in that field and then read this paragraph, could you recall what that format is? You’re left to guess at what the form wants. That’s much worse than janky example above.
It’s better to leave the segment characters open and optional, as in this example. The form user can separate the segments of digits with any non-digit character, or no character, and it will still pass validation. The form processor can reformat the input as needed, and a little bit of extra work from the programmer makes the interaction just a bit less painless.