IMask Credit Card Input with Brand Detection — Free JS Snippet

IMask Credit Card Input with Brand Detection · Forms · Plain HTML, CSS & JS · Live preview

CategoryForms

What's included

Features

Dynamic mask switching between 4-4-4-4, 4-6-5 and 4-6-4 layouts as digits arrive
Brand detection from leading-digit patterns for Visa, Mastercard, Amex, Discover and Diners
Luhn checksum validation shown only once the number is complete
MM/YY expiry with a MaskedRange month block and expired-card detection
Security-code length follows the brand (4 for Amex, 3 otherwise)
Live card preview with brand-specific colours and mirrored name, number and expiry
Autocomplete tokens (cc-number, cc-exp, cc-csc) for browser autofill
One-click test numbers for every supported brand

About this UI Snippet

IMask Credit Card Input with Brand Detection — HTML, CSS & JavaScript

Screenshot of the IMask Credit Card Input with Brand Detection snippet rendered live

A card number field looks like a solved problem until you try to format it. Visa and Mastercard group digits as 4-4-4-4. American Express is 4-6-5. Diners Club is 4-6-4. A single fixed mask is wrong for at least one of them, and you cannot know which applies until the user has typed the first digits. IMask's dynamic masks are built for this: you supply an array of masks and a dispatch function that picks one every time the value changes.

The dispatch function here strips the current text and the newly typed characters down to digits, then tests them against each brand's leading-digit pattern — 4 for Visa, 51-55 and 2221-2720 for Mastercard, 34 and 37 for Amex, and so on. The first match wins, with a generic 16-digit mask as the fallback. Because it runs on every keystroke, the grouping reshapes itself mid-typing: start a number with 3 and 7 and the field reflows into the Amex layout. The detected brand also drives the card preview colour and the security-code length, since Amex uses a four-digit CID while everything else uses three.

Format is not validity. The 16 digits of a random number will fill the mask happily, so the field also runs the Luhn checksum — double every second digit from the right, subtract 9 from any result above 9, and require the sum to be divisible by 10. It catches almost all single-digit typos and adjacent transpositions before a request ever reaches a payment provider. The message only appears once the mask is complete, so people are not told their half-typed number is wrong.

Expiry uses a pattern mask with a MaskedRange block for the month, restricting it to 01-12 as you type so "15/28" is impossible to enter, and a comparison against today's date flags an expired card. The four test-number buttons load well-known example numbers that pass the checksum, so you can watch every brand without inventing digits. None of this transmits or stores anything; in a real checkout use your payment provider's hosted fields so raw card numbers never touch your own servers.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant like Claude to add a card-flip animation that shows the CVC on the back, support UnionPay and JCB ranges, or connect the form to a payment provider's hosted fields.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a credit card entry form with IMask 7 loaded from a CDN.

Requirements:
- Use a dynamic mask array with a dispatch function that detects Visa, Mastercard, Amex, Discover and Diners from leading digits and switches between 4-4-4-4, 4-6-5 and 4-6-4 layouts.
- Validate the completed number with the Luhn checksum and show a message only when the mask is complete.
- Add an MM/YY expiry mask using MaskedRange blocks (month 1-12) and flag expired dates.
- Change the security-code mask between 3 and 4 digits depending on the detected brand.
- Show a live card preview whose colour follows the brand and mirrors the number, name and expiry, plus buttons that load valid test numbers.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

Requires
<div class="cc-wrap">
  <div class="cc-card" id="ccCard" data-brand="unknown" aria-hidden="true">
    <div class="cc-brand" id="ccBrand">CARD</div>
    <div class="cc-chip"></div>
    <div class="cc-num" id="ccPreviewNum">#### #### #### ####</div>
    <div class="cc-row"><span id="ccPreviewName">FULL NAME</span><span id="ccPreviewExp">MM/YY</span></div>
  </div>

  <form class="cc-form" id="ccForm" novalidate>
    <label>Card number
      <input id="ccNumber" inputmode="numeric" autocomplete="cc-number" placeholder="1234 5678 9012 3456">
      <small id="ccNumMsg"></small>
    </label>
    <label>Name on card
      <input id="ccName" autocomplete="cc-name" placeholder="Ada Lovelace">
    </label>
    <div class="cc-two">
      <label>Expiry
        <input id="ccExp" inputmode="numeric" autocomplete="cc-exp" placeholder="MM/YY">
        <small id="ccExpMsg"></small>
      </label>
      <label><span id="ccCvcLabel">CVC</span>
        <input id="ccCvc" inputmode="numeric" autocomplete="cc-csc" placeholder="123">
      </label>
    </div>
    <div class="cc-test">Test numbers:
      <button type="button" data-n="4242 4242 4242 4242">Visa</button>
      <button type="button" data-n="5555 5555 5555 4444">Mastercard</button>
      <button type="button" data-n="3782 822463 10005">Amex</button>
      <button type="button" data-n="6011 1111 1111 1117">Discover</button>
    </div>
  </form>
</div>

Step by step

How to Use

  1. 1
    Type a card numberStart with a 4 for Visa, 5 for Mastercard, or 3 then 7 for American Express. The grouping and card colour change as you type.
  2. 2
    Load a test numberClick a brand button to fill a well-known example number that passes the checksum.
  3. 3
    Break the checksumChange the last digit of a full number. The field flags that the number fails validation.
  4. 4
    Enter an expiryType "1" then "5". The month is capped at 12. An expired date shows a warning.
  5. 5
    Check the security codeSwitch to an Amex number and the code field asks for four digits instead of three.

Real-world uses

Common Use Cases

Checkout and subscription forms
Collect payment details with instant feedback. Pair with the currency input for an amount field.
SHOP
Saved payment methods
Let customers add a card with a preview that confirms the brand before they submit.
Design system input patterns
A reference for masked, validated inputs that show format and validity separately.
Learning dynamic masks and Luhn
See how dispatch, regular expressions and a checksum combine into a production-quality field.

Got questions?

Frequently Asked Questions

A dispatch function tests the digits typed so far against each brand's leading-digit regular expression and returns the matching mask, falling back to a generic one.

A checksum used by card numbers: double every second digit from the right, subtract 9 from results over 9, sum everything and check divisibility by 10. It catches most typing mistakes.

No. It only means the number is well-formed. Only your payment provider can confirm the card exists and has funds.

Use this pattern for the interface only. In production, collect card data with your payment provider's hosted fields so it never reaches your servers.

American Express cards use a four-digit code on the front, while other brands use three digits on the back.

Add an entry to BRANDS with its mask, security-code length and leading-digit regular expression; the dispatch function picks it up automatically.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from IMask, so in a framework project install it with npm install imask (or react-imask / vue-imask / angular-imask) instead of the CDN tag, create it in useEffect / onMounted / ngAfterViewInit, and release it with destroy() when the component unmounts.