HTML & CSS for a One-Time Password Input

You know those One Time Password inputs? Typically 4 or 6 numbers, something like:

Well I came across an article by Phuoc Nguyen about them called Build an OTP input field. I’d say all-in-all, Phuoc did a good job. The design and user experience was considered, like using the arrow keys to move between the inputs and handling “paste”. I’d say accessibility too but I feel like this is complicated enough of an interaction I can’t personally vouch for that.

But I’m also also like — damn — that’s complicated. That’s a lot of JavaScript code. Why is this so hard? And what would happen without JavaScript here? Seems like it would be a pretty gnarly experience.

And then I was like… why can’t this just be one input? The rectangles behind the numbers is just theater. Just a bit of trendy decoration. It’s just a styling concern, not a semantic, usability, or any other concern.

So I was like… I’m just gonna make those rectangles background-images and see if that works. So I built a demo, but it had a flaw: as you typed the last character, the value would kinda slide one direction and look bad. You can see it here.

But I posed the challenge in our ShopTalk Discord and others had some ideas. Josh Collingsworth had an idea where you could cover up some area at the end and prevent the movement issue (the yellow block would be white or whatever covers up properly). Alex Fimion did it a smidge cleaner by covering the last bit with background-image instead of a pseudo-element. Here’s that:

Is that better than the 4-inputs approach?

I’m giving an only-slightly-hesitant thumbs up 👍. My hesitation is that in order for this to look right, there is a lot of “magic number” usage. That is, numbers that are just visually tweaked by hand to make it all work, and based on finicky things like font metrics (which might change over time and with different fonts) rather than hard foundational layout.

So let’s call this a pretty good take. I think when you consider the HTML used alone you can see using a one-input approach feels best:

<input
  required
  type="text"
  autocomplete="one-time-code"
  inputmode="numeric"
  maxlength="4"
  pattern="\d{4}"
>Code language: HTML, XML (xml)

In fact, if I started having problems with the look of the “rectangles behind the numbers” approach, I’d just make it a big ol’ single input without the individual rectangles. Like I said, I feel those are just something of a design trend anyway.


I just got access to Vercel’s v0.dev and it really wants to use multiple inputs. It somehow doesn’t surprise me that it wants to use the JavaScript-heavy approach, even though it doesn’t actually provide that JavaScript so what you get is a bunch of number-inputs (with spinners you don’t need) and none of the JavaScript that is required to make it actually work.

A refinement asking for one field worked decently though.

🤘

CodePen

I work on CodePen! I'd highly suggest you have a PRO account on CodePen, as it buys you private Pens, media uploads, realtime collaboration, and more.

Get CodePen PRO

5 responses to “HTML & CSS for a One-Time Password Input”

  1. Josh Kramer says:

    Another disadvantage of this technique – if the OTP code is generated by a password manager like 1Password, the inserted password manager UI is in the wrong spot.

    https://imgur.com/GKBT4Or

  2. Anshu Meena says:

    Your approach to simplifying the OTP input is interesting! Going for a single input indeed makes things cleaner and less complex. It’s great for a simpler HTML structure and improved accessibility. The background-image trick is clever, but be mindful of potential hiccups with font changes. Overall, a solid attempt at balancing simplicity and functionality.

  3. Kyle Johnson says:

    My vote is to just use a single field, no boxes. Users should be able to paste the code and it should work 100% of the time. Trying to do individual inputs has too many issues to account for. Also, even with the background image, what are we solving? Your example is 4 numbers, my three banks all use 6 numbers, I think that is short enough that the user doesn’t need boxes. If someone has data that shows having boxes increases usability, then great, but this feels like just a design trend.

  4. Tobi says:

    Nice solutions, but do users — not us developers — actually care about these boxes? I am on team big ol’ single input.

    input[autocomplete=one-time-code] {
    width: 9ch; /* roughly */
    text-align: center;
    letter-spacing: .5ch;
    }

    Thank you, web platform.

  5. Kerry Johnson says:

    @TOBI Users do not care, however it’s got a distinct and patterned-enough look to remind users that this is a OTP and not a password field like some users might assume without looking harder.

    @ChrisCoyier I also tried your method before some time ago. One downside was that the input was an all or nothing for errors (I couldn’t just highlight one square in red). I forget what I was needing this for to require this stipulation. Still, a little bit of JS sprinkled on top could help with this, I’d take it over orchestrating between multiple input interactions.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to Top ⬆️