Маски для кредитных карт

Кредитные карты в пользовательских интерфейсах почти всегда требуют строгого форматирования ввода, поскольку номер карты должен соответствовать фиксированным отраслевым стандартам. Наиболее распространённая структура — последовательность цифр, разбитая на группы по 4 символа, либо специализированный формат 4–6–5 для отдельных платёжных систем. В JavaScript-библиотеках маскирования ввода, таких как Inputmask, эта задача решается через комбинацию шаблонов, правил и динамических масок.

Самый простой вариант реализации — фиксированный шаблон из 16 цифр, разделённых пробелами:

Inputmask("9999 9999 9999 9999").mask("#card");

В данном случае символ 9 обозначает обязательную цифру от 0 до 9. Пробелы являются статическими символами-разделителями и автоматически вставляются в соответствующих позициях.

Такой подход подходит для карт формата:

  • Visa
  • Mastercard
  • Discover (в большинстве случаев)
  • Мир (в классическом 16-значном варианте)

Особенности поведения маски

  • Пользователь вводит только цифры, разделение выполняется автоматически
  • Пробелы не удаляются при вводе
  • Курсор перескакивает через фиксированные символы
  • Вставка текста адаптируется к позиции маски

Структура определения символов Inputmask

Для понимания гибкости кредитных масок важно учитывать базовые правила Inputmask:

  • 9 — обязательная цифра
  • 0 — цифра или пробел (в зависимости от конфигурации)
  • # — цифровой символ с дополнительной логикой (расширяемый)
  • A — буквенный символ
  • * — буквенно-цифровой символ

Для кредитных карт практически всегда используется только 9, так как формат строго цифровой.

Маска для карт American Express (4–6–5)

Карты American Express отличаются длиной (15 цифр) и структурой группировки:

Inputmask("9999 999999 99999").mask("#card");

Здесь структура разбивается на:

  • 4 цифры
  • 6 цифр
  • 5 цифр

Особенность такого формата — отсутствие универсальности. Маска должна выбираться динамически в зависимости от типа карты.

Динамическое определение маски

В реальных интерфейсах маска не является фиксированной, поскольку разные платёжные системы используют разные форматы. Поэтому применяется переключение масок:

const cardMask = Inputmask({
  mask: [
    "9999 9999 9999 9999",
    "9999 999999 99999"
  ]
});

cardMask.mask("#card");

Inputmask автоматически выбирает подходящий вариант в зависимости от длины ввода и структуры.

Определение типа карты по BIN

BIN (Bank Identification Number) — первые 6 цифр номера карты. На основе BIN можно определить платёжную систему и применить соответствующую маску.

Пример логики:

function getCardMask(value) {
  const firstDigit = value.charAt(0);

  if (firstDigit === "3") {
    return "9999 999999 99999"; // AmEx
  }

  return "9999 9999 9999 9999";
}

Более точная реализация использует регулярные выражения:

  • Visa: ^4
  • Mastercard: ^5[1-5]
  • Amex: ^3[47]

Переключение маски на лету

Inputmask позволяет обновлять конфигурацию без пересоздания элемента:

const im = new Inputmask("9999 9999 9999 9999");
im.mask("#card");

document.querySelector("#card").addEventListener("input", (e) => {
  const value = e.target.value.replace(/\s/g, "");

  const newMask =
    value.startsWith("3") ? "9999 999999 99999"
    : "9999 9999 9999 9999";

  im.setOptions({ mask: newMask });
});

Такой подход обеспечивает адаптивное поведение интерфейса.

Плейсхолдеры и визуальная структура

Плейсхолдеры играют важную роль в восприятии структуры номера карты:

Inputmask("9999 9999 9999 9999", {
  placeholder: "____ ____ ____ ____"
}).mask("#card");

Плейсхолдер:

  • визуально задаёт формат
  • помогает пользователю понять структуру ввода
  • снижает количество ошибок

Контроль неполного ввода

Кредитные карты не должны считаться валидными при неполном вводе. Для этого используется параметр:

Inputmask("9999 9999 9999 9999", {
  clearIncomplete: true
}).mask("#card");

Поведение:

  • если ввод не завершён, значение очищается
  • предотвращается сохранение некорректных данных

Обработка завершения ввода

Для валидации используется событие завершения:

Inputmask("9999 9999 9999 9999", {
  oncomplete: function () {
    console.log("Номер карты введён полностью");
  }
}).mask("#card");

Это событие полезно для:

  • активации кнопки “Продолжить”
  • запуска проверки BIN
  • отправки данных на сервер

Маскирование и скрытие части номера

В интерфейсах отображения часто требуется скрывать часть номера карты, оставляя только последние 4 цифры:

Inputmask("9999 9999 9999 9999", {
  showMaskOnHover: false,
  showMaskOnFocus: false
}).mask("#card");

Однако для задач отображения сохранённых карт чаще используется отдельная логика форматирования:

function maskCard(value) {
  return value.replace(/\d(?=\d{4})/g, "*");
}

Результат:

**** **** **** 1234

Поддержка вставки (paste) и очистки

Inputmask автоматически обрабатывает вставку, но при работе с кредитными картами важно учитывать:

  • удаление пробелов
  • фильтрацию нецифровых символов
  • нормализацию длины

Пример подготовки данных:

function normalizeCardInput(value) {
  return value.replace(/\D/g, "").slice(0, 16);
}

Это позволяет избежать:

  • вставки букв
  • переполнения маски
  • некорректных символов из буфера обмена

Расширенные маски с функцией

Inputmask поддерживает функциональные маски, возвращающие шаблон динамически:

Inputmask({
  mask: function () {
    return "9999 9999 9999 9999";
  }
}).mask("#card");

Более сложный вариант:

Inputmask({
  mask: function (value) {
    if (value.startsWith("34") || value.startsWith("37")) {
      return "9999 999999 99999";
    }
    return "9999 9999 9999 9999";
  }
}).mask("#card");

Валидация по длине и структуре

Хотя маска контролирует формат, дополнительная проверка остаётся обязательной:

  • Visa/Mastercard: 16 цифр
  • Amex: 15 цифр

Пример:

function validateCard(value) {
  const digits = value.replace(/\D/g, "");

  if (digits.startsWith("3")) {
    return digits.length === 15;
  }

  return digits.length === 16;
}

Особенности UX при работе с кредитными масками

При проектировании ввода кредитной карты критичны следующие аспекты:

  • мгновенное форматирование без задержек
  • отсутствие “прыгающего” курсора
  • стабильная позиция разделителей
  • автоматическая адаптация под тип карты
  • корректная обработка вставки из менеджеров паролей

Inputmask обеспечивает эти свойства через внутренний механизм позиционирования и перерасчёта маски при каждом вводе символа.

Частые ошибки при реализации масок

Неправильная конфигурация часто приводит к проблемам:

  • использование * вместо 9 для цифр
  • фиксированная маска без учёта Amex
  • отсутствие обработки paste-событий
  • попытка хранить форматированное значение вместо “чистого”
  • конфликт нескольких масок без приоритета

Корректная архитектура предполагает разделение:

  • отображаемого значения (с пробелами)
  • внутреннего значения (только цифры)