New Nov 11, 2025

Simple One-Time Passcode Inputs

Company/Startup Blogs All from Cloud Four View Simple One-Time Passcode Inputs on cloudfour.com

If you’ve signed into an online service in the last decade, chances are you’ve been asked to fill a one-time passcode (“OTP”) field with a handful of digits from a text, email or authenticator app:

Screenshot of the Slack interface after attempting a sign-in and being asked for a verification code from email. The code entry is divided into separate steps per digit.
Slack’s OTP entry form

Despite the prevalence of this pattern, it seems to cause plenty of anxiety in otherwise level-headed web developers… especially if they’ve fixated on the current trend of segmenting the input to convey the passcode’s length (a new spin on the ol’ input mask).

Why else would so many tumble down the rabbit hole of building their own <input> replacement, stringing multiple <input> elements together, or burdening their project with yet another third-party dependency?

If you find yourself in a similar situation, I have good news! You can ship a fully functional OTP input today without any CSS hacks or JavaScript frameworks.

All you need is some HTML.

Basic Markup

A single <input> element: That’s where the OTP magic happens!

<input type="text"
  inputmode="numeric"
  autocomplete="one-time-code"
  maxlength="6">

Let’s break down each of its attributes:

We can opt into client-side validation by adding two more:

<input type="text"
  inputmode="numeric"
  autocomplete="one-time-code"
  maxlength="6"
  pattern="\d{6}"
  required>

pattern defines the code we expect, in this case exactly six ({6}) numeric digits (\d). required tells the browser this field must have a value that satisfies the pattern.

Example: In a Form

Now all our OTP-specific features are accounted for, but an input is meaningless without context. Let’s fix that by building out a full form with a heading, a label, a submit button and a support link in case something goes wrong:

<form action="…" method="post">
  <h2>Verify Account</h2>
  <label for="otp">
    Enter the 6-digit numeric code sent to +1 (555) 555-5555
  </label>
  <input type="text"
    id="otp"
    inputmode="numeric"
    autocomplete="one-time-code"
    maxlength="6"
    pattern="\d{6}"
    required>
  <button>
    Continue
  </button>
  <a href="…">
    Try another way…
  </a>
</form>

Note how the label specifies the intended length and format of the passcode. No input mask, icon or visual affordance can match the accessibility and clarity of straightforward text!

And with that, our OTP pattern is functionally complete!

Demo: With Styles

Since we’ve covered all the critical functionality in our HTML, we’re free to style our form however the project dictates.

In this example, I’ve chosen a large, monospaced font with some letter-spacing to keep every digit of the code distinct and readable. I’m also using the :invalid pseudo class to reduce the visual prominence of the <button> element until the code is valid:

Demo: Enhanced

Having a solid foundation in HTML and CSS alone doesn’t preclude us from leveraging JavaScript, too.

Here’s the same demo as before, but with a simple input mask web component to indicate remaining characters:

Because this builds atop existing patterns instead of replacing them outright, the code is tiny: Less than a kilobyte without any optimization or compression.

Takeaways


We’re Cloud Four

We solve complex responsive web design and development challenges for ecommerce, healthcare, fashion, B2B, SaaS, and nonprofit organizations.

See our work

Scroll to top