
📱 Маска телефона для input на JavaScript: 4 способа с кодом
Пользователь вбивает телефон как попало: кто-то с восьмёрки, кто-то с +7, кто-то слитно, кто-то с пробелами после каждой пары цифр. В базу уходит мешанина. Менеджер тратит время на обзвон, а половина номеров, битая. Знакомая картина для любого, кто ставил форму обратной связи на сайт.
Маска ввода закрывает проблему целиком: пользователь физически не может ввести номер в неверном формате. Набирает цифры, они сами подставляются в нужные места, скобки и дефисы появляются автоматически. Никаких ошибок, никакого раздражения.
Ниже, четыре способа добавить маску телефона в input: от нативного HTML5 без единой строчки JavaScript до готовой библиотеки с флагами всех стран. С кодом, который можно скопировать и вставить в свой проект.
💡 Быстрый обзор:
- Простейшая маска через атрибут
patternиtype="tel", ни строчки JavaScript, работает в любом браузере - Нужны флаги стран и международный формат, ставьте
intl-tel-input, самое популярное решение на GitHub - Нужна одна библиотека для телефонов, дат, карт и любых других масок, берите
IMask.js - Хотите написать маску руками и не тянуть зависимостей, чистый JavaScript справится за 30 строк
Что такое маска ввода и почему она важнее валидации
Маска ввода, или input mask, это строка-шаблон, которая управляет тем, что видит и может набрать пользователь в поле формы. В отличие от валидации, которая проверяет данные после отправки и показывает ошибку, маска работает прямо во время ввода: не даёт напечатать букву там, где должна быть цифра, и сама расставляет скобки, дефисы и пробелы.
Разница принципиальная. Валидация говорит «вы ошиблись», пользователь уже раздражён и может уйти. Маска ведёт за руку: ошибка просто невозможна. Для телефона это критично, потому что форматов записи десятки. Только российский номер можно написать как +7 999 123-45-67, как 8(999)1234567 или как +7(999)123-45-67 и это лишь три варианта из множества. Без маски каждый пользователь изобретает свой формат, и база превращается в свалку.
Способ 1: HTML5, type="tel" и pattern
Самый лёгкий путь: обойтись без JavaScript вообще. Современные браузеры поддерживают type="tel" и атрибут pattern, который проверяет ввод по регулярному выражению при отправке формы.
Добавьте поле в разметку. Код вставляется в любой HTML-шаблон: Contact Form 7, нативную форму WordPress или кастомную вёрстку.
1 <input 2 type="tel" 3 id="phone" 4 name="phone" 5 pattern="\+7\s?[\(]?\d{3}[\)]?\s?\d{3}[\-]?\d{2}[\-]?\d{2}" 6 placeholder="+7 (999) 123-45-67" 7 title="Введите номер в формате +7 (999) 123-45-67" 8 required 9 >
Разберём, что здесь происходит. type="tel" на мобильных устройствах показывает цифровую клавиатуру вместо обычной, вводить телефон сразу удобнее. pattern задаёт регулярное выражение, которое разрешает несколько вариантов: с пробелами и без, со скобками вокруг кода оператора и без них. title показывает подсказку при наведении, а required не даст отправить форму с пустым полем.
Плюс подхода: ноль зависимостей, работает в любом браузере. Для простого лендинга этого хватает.
Но это не настоящая маска. Скобки и дефисы не появляются автоматически, пользователь должен набрать их сам. pattern срабатывает только при отправке формы. Если нужно форматирование прямо во время ввода, переходите к следующим способам.
Способ 2: intl-tel-input, международный формат с флагами стран
intl-tel-input, самая популярная JavaScript-библиотека для ввода телефонов. Даёт поле с выпадающим списком флагов стран, автоформатированием под национальный шаблон и валидацией номера. По состоянию на июнь 2026 библиотека насчитывает более 7 800 звёзд на GitHub, актуальная версия, 29.
Подключите библиотеку через npm (npm i intl-tel-input) или CDN. Код ниже, для vanilla JavaScript; есть также готовые компоненты для React, Vue, Angular и Svelte.
1 <!-- В <head> страницы --> 2 <link 3 rel="stylesheet" 4 href="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/css/intlTelInput.css" 5 > 6 <script src="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/intlTelInput.min.js"></script>
Сам input и инициализация, в том месте шаблона, где нужно поле. Для WordPress-темы добавьте скрипт через wp_enqueue_script в functions.php, а разметку, в нужный шаблон.
1 <input type="tel" id="phone"> 2 3 <script> 4 const input = document.querySelector("#phone"); 5 const iti = intlTelInput(input, { 6 initialCountry: "ru", 7 separateDialCode: true, 8 utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/utils.js" 9 }); 10 </script>
initialCountry: "ru" ставит российский флаг по умолчанию. separateDialCode: true выносит код страны за пределы поля ввода: пользователь меняет флаг, код подставляется сам. utilsScript подгружает утилиты форматирования, без них библиотека работает, но номера не форматируются под маску выбранной страны.
Объект, который возвращает intlTelInput(), даёт несколько полезных методов. iti.getNumber() отдаёт номер в международном формате E.164, iti.isValidNumber() проверяет корректность, iti.setNumber("9991234567") программно устанавливает значение. Для Contact Form 7 понадобится кастомный скрипт: находите поле .wpcf7-tel и вешаете на него intlTelInput.
Плюс: полноценное международное решение, автоформат, флаги, валидация, интеграции с фреймворками. Минус: библиотека весит около 40 КБ (gzip), и для простого лендинга с одним полем это перебор.
Способ 3: IMask.js, универсальная маска без jQuery
IMask.js, зрелая библиотека масок на чистом JavaScript: ни jQuery, ни других зависимостей. Поддерживает маски для телефонов, дат, чисел, валют и динамические шаблоны. Удобна, когда на одном сайте нужны разные типы масок: телефон в форме обратной связи, дата в календаре и сумма в калькуляторе. Актуальная версия, 7.1.
Установите через npm (npm i imask) или подключите CDN:
1 <script src="https://unpkg.com/imask"></script>
Маска телефона в три строки. Код можно разместить в <script> в футере или в отдельном JS-файле темы.
1 const phoneInput = document.getElementById('phone'); 2 const maskOptions = { 3 mask: '+{7} (000) 000-00-00' 4 }; 5 IMask(phoneInput, maskOptions);
Синтаксис маски: +{7}, фиксированный префикс, не редактируется пользователем. 0, любая цифра от 0 до 9. Можно усложнить: сделать код оператора опциональным или динамически менять маску при смене страны через параметр dispatch.
IMask возвращает объект с доступом к сырому значению: maskRef.unmaskedValue отдаст чистые цифры 79991234567, именно то, что нужно сохранять в базу. Метод maskRef.value вернёт форматированную строку для отображения. Классическая проблема решена: на бэкенд летят цифры, а пользователь видит красивый номер.
Плюс: одна библиотека на все случаи, чистые значения из коробки, нет зависимостей. Минус: для одного телефонного поля проще взять intl-tel-input с флагами, IMask раскрывается на формах с тремя-пятью разными типами полей.
Способ 4: чистый JavaScript, маска своими руками
Если не хотите тянуть библиотеку ради одного поля, напишите маску на чистом JavaScript. Код ниже обрабатывает каждое нажатие и автоматически вставляет скобки и дефисы по мере ввода цифр.
Скрипт размещается в том же шаблоне, где находится поле ввода, или подключается отдельным файлом. Для WordPress, через wp_enqueue_script с флагом true (в футере).
1 document.getElementById('phone').addEventListener('input', function (e) { 2 let value = e.target.value.replace(/\D/g, ''); 3 4 if (value.length > 11) { 5 value = value.slice(0, 11); 6 } 7 8 let formatted = '+7 ('; 9 if (value.length > 1) formatted += value.slice(1, 4); 10 if (value.length > 4) formatted += ') ' + value.slice(4, 7); 11 if (value.length > 7) formatted += '-' + value.slice(7, 9); 12 if (value.length > 9) formatted += '-' + value.slice(9, 11); 13 14 e.target.value = formatted; 15 });
Событие input срабатывает при каждом изменении поля, вставка из буфера, автоисправление, удаление. Первая строка replace(/\D/g, '') вырезает всё, кроме цифр: буквы и спецсимволы исчезают мгновенно. Затем скрипт отсекает лишние цифры (российский номер, 11 знаков с кодом страны) и собирает отформатированную строку: код страны +7, три цифры кода оператора в скобках, три цифры номера, две, две, через дефисы.
Перед использованием на реальном сайте добавьте две доработки. Первая: при удалении цифр в середине номера курсор может прыгать в конец поля, сохраняйте позицию каретки через selectionStart и восстанавливайте после форматирования. Вторая: для номеров других стран (Беларусь, 12 цифр, Казахстан, 11 цифр с другим кодом) логика усложняется, и тогда intl-tel-input полностью оправдан.
Плюс: 30 строк, полный контроль, ни одного килобайта зависимостей. Минус: маска заточена под один формат, для мультистрановых проектов код распухнет.
⁉️🤔 Частые вопросы
Чем маска лучше простой валидации?
Валидация срабатывает после отправки формы: пользователь видит ошибку и возвращается исправлять. Маска работает во время ввода, неверный формат физически невозможен. Меньше раздражения, меньше отказов от отправки. Для телефона это критично: ошибки в номере, одна из самых частых причин, по которым пользователи бросают форму.
Как сохранять в базу чистые цифры без скобок и дефисов?
Все библиотеки из статьи отдают сырое значение: у
intl-tel-inputметодgetNumber()возвращает+79991234567, уIMask.jsсвойствоunmaskedValue,79991234567. Перед отправкой на сервер берите чистое значение и сохраняйте его. Форматированную строку показывайте только в интерфейсе. В WordPress-формах добавьте скрытое поле<input type="hidden" name="phone_raw">и заполняйте его через JavaScript перед отправкой.
Работает ли маска на мобильных устройствах?
Да, все четыре способа корректно работают на iOS и Android.
type="tel"вызывает цифровую клавиатуру, это удобно. На старых Android (версии ниже 6) событиеinputможет вести себя иначе при автозамене, протестируйте на реальных устройствах.intl-tel-inputиIMask.jsтестируются разработчиками на мобильных браузерах и проблем не создают.
Можно ли использовать маску в Contact Form 7?
CF7 генерирует поля с классами
.wpcf7-tel. Напишите скрипт, который находит это поле по селектору и вешает на негоintl-tel-inputилиIMask. При отправке формы CF7 берёт значение напрямую из поля, библиотека должна успеть отформатировать его до этого. Если используете чистые значения, перехватите событиеwpcf7submitи подмените данные в скрытом поле.
Что делать с номерами разных стран на одном сайте?
Берите
intl-tel-input: пользователь выбирает флаг, маска автоматически переключается под формат выбранной страны. Для геотаргетинга можно задатьinitialCountry: "auto", библиотека определит страну по IP через внешний сервис. Если стран две-три и бюджет на зависимости минимален, напишите две маски на чистом JavaScript и переключайте их радиокнопкой «Россия / Казахстан» над полем.
Какой способ выбрать под вашу задачу
Выбор сводится к трём вопросам: сколько полей на сайте, нужны ли флаги стран и насколько критичен размер бандла.
Одна простая форма на лендинге, начните с HTML5 pattern. Быстро, без JavaScript, на мобильных клавиатура переключается на цифровую. Сайт принимает международные номера, intl-tel-input закроет вопрос целиком: флаги, автоформат, валидация. Для интернет-магазина или SaaS это стандарт.
Несколько разных масок на сайте (телефон, дата, сумма, карта), IMask.js даст один API под все поля и не тянет jQuery. Делаете пет-проект и хотите полный контроль, 30 строк на чистом JavaScript решат задачу для российских номеров без единой зависимости.
Проверьте работу маски на живом сайте: вбейте номер с буквами, вставьте из буфера, попробуйте стереть пару цифр в середине. Поле должно вести себя предсказуемо в любом сценарии. Какой способ выбрали для своего проекта, напишите в комментариях.



