Установка маски для поля телефона в форме
Чтобы пользователю было удобнее, добавим под полем номер телефона подсказку со счётчиком: сколько цифр введено и сколько осталось до полного 10-значного номера.
Ниже поля input для телефона вставим элемент <div> или <small> для подсказки.
HTML
<form action="" class="form">
<!-- Поле для имени пользователя -->
<input type="text" class="form__input" placeholder="Введите Имя" required>
<!-- Контейнер для телефонного поля и подсказки -->
<div class="phone-wrapper">
<!-- Поле ввода телефона с id для JavaScript -->
<input id="phone" type="tel" class="form__input" placeholder="+7(999) 888-77-66" required>
<!-- Элемент для вывода подсказок и счётчика -->
<small id="phone-help" class="phone-help"></small>
</div>
<!-- Кнопка отправки формы -->
<button type="submit" class="form__button">
Отправить
</button>
</form>Добавим CSS, чтобы:
- При фокусе на поле менялся цвет рамки.
- При невалидном номере (меньше 10 введённых цифр) поле подсвечивалось красным.
Здесь:
.form__input:focus— срабатывает автоматически при фокусе.form__input.error— будет применяться из JavaScript, если номер введён неверно.phone-wrapperдаёт отступ снизу.phone-help— серый текст подсказки
CSS
/* Базовая стилизация полей ввода */
.form__input {
padding: 8px 12px;
/* Внутренние отступы для комфортного ввода */
font-size: 16px;
/* Размер шрифта */
border: 2px solid #ccc;
/* Серая рамка по умолчанию */
border-radius: 4px;
/* Скругление углов */
outline: none;
/* Убираем стандартную подсветку браузера */
transition: border-color 0.2s;
/* Плавная анимация смены цвета рамки */
}
/* Подсветка рамки синим при фокусе */
.form__input:focus {
border-color: #007bff;
/* Оттенок синего */
}
/* Класс ошибки: красная рамка */
.form__input.error {
border-color: #dc3545;
/* Оттенок красного */
}
/* Обёртка для input и подсказки */
.phone-wrapper {
position: relative;
margin-bottom: 1.5em;
/* Отступ снизу между полями формы */
}
/* Стиль текста подсказки под полем */
.phone-help {
display: block;
margin-top: 4px;
font-size: 14px;
color: #666;
/* Тёмно-серый цвет */
}Основной скрипт
При каждом вводе будем:
- Извлекать только цифры из введённого значения
- Строить строку в формате
+7(XXX) XXX-XX-XX, подставляя цифры по порядку - Ограничивать ввод 10 цифрами (без кода страны)
Далее:
- Навесить обработчик
focusнаphoneInput, который:- Если
valueпусто, записывает'+7('
- Если
- Навесить обработчик
blurнаphoneInput, который:- Если после форматирования в поле осталось меньше трёх символов (то есть только префикс
+7(или вообще пусто), очищаетvalue
- Если после форматирования в поле осталось меньше трёх символов (то есть только префикс
Чтобы очистка учитывала только пользовательский ввод, нужно перед проверкой также убрать ведущую «7» (код страны) точно так же, как в formatPhone:
- Для
'+7('→raw = "7"→ после удаления кода страныraw = ""→raw.length === 0→ поле очистится - Если пользователь ввёл «+7(9» →
raw = "79"→ после удаления «7» →raw = "9"→raw.length === 1→ поле не очистится, поскольку есть хотя бы одна цифра
Валидация номера при отправке формы
Добавим обработчик submit на форму, который:
- Снимает класс
.errorс поля. - Проверяет, что после удаления всего, кроме цифр, и удаления ведущей «7» осталось ровно 10 цифр
- Если нет — отменяет отправку, добавляет
.errorи ставит фокус обратно
Логика подсчёта цифр номера в JavaScript
В уже существующий скрипт добавляем функцию updateHelp(), которая по phoneInput.value считает цифры (без кода страны) и выводит сообщение вида:
- «Введено 4 из 10 цифр»
- или «Осталось ввести 6 цифр»
Что получится:
- Пока поле пустое, подсказка «Введите номер телефона».
- При вводе цифр показывает прогресс.
- При заполнении всех 10 цифр – «Номер введён полностью».
JavaScript
// Находим элементы: поле телефона и блок подсказки
const phoneInput = document.getElementById('phone');
const help = document.getElementById('phone-help');
// Форматирует строку в маску +7(XXX) XXX-XX-XX
function formatPhone(value) {
// 1. Убираем все не-цифры
let raw = value.replace(/\D/g, '');
// 2. Если первым символом идёт '7' (код страны), удаляем его
if (raw.charAt(0) === '7') {
raw = raw.substring(1);
}
// 3. Берём первые 10 цифр пользовательского номера
const digits = raw.substring(0, 10);
const parts = [];
// 4. Добавляем префикс +7
parts.push('+7');
// 5. Открывающая скобка и первые 3 цифры
if (digits.length > 0) {
parts.push('(' + digits.substring(0, Math.min(3, digits.length)));
}
// 6. Закрываем скобку после 3 цифр
if (digits.length >= 3) {
parts[1] += ')';
}
// 7. Следующие 3 цифры с пробелом
if (digits.length > 3) {
parts.push(' ' + digits.substring(3, Math.min(6, digits.length)));
}
// 8. Две цифры и дефис
if (digits.length > 6) {
parts.push('-' + digits.substring(6, Math.min(8, digits.length)));
}
// 9. Последние две цифры и дефис
if (digits.length > 8) {
parts.push('-' + digits.substring(8, 10));
}
// Собираем все части в итоговую строку
return parts.join('');
}
// Обновляет текст подсказки под полем телефона
function updateHelp(value) {
// Убираем не-цифры
let raw = value.replace(/\D/g, '');
// Удаляем ведущую '7'
if (raw.charAt(0) === '7') {
raw = raw.substring(1);
}
const count = raw.length; // Сколько введено цифр
const remaining = 10 - count; // Сколько осталось
if (count === 0) {
help.textContent = 'Введите номер телефона';
} else if (count < 10) {
help.textContent = `Введено ${count} из 10 цифр. Осталось ${remaining}`;
} else {
help.textContent = 'Номер введён полностью';
}
}
// Обработчик ввода: форматируем и обновляем подсказку
phoneInput.addEventListener('input', (e) => {
const formatted = formatPhone(e.target.value);
e.target.value = formatted;
updateHelp(formatted);
// Перенос курсора в конец строки
const pos = e.target.value.length;
e.target.setSelectionRange(pos, pos);
});
phoneInput.addEventListener('focus', (e) => {
phoneInput.setSelectionRange(6, 6);
if (!e.target.value) {
e.target.value = '+7(';
updateHelp(e.target.value);
// Ставим курсор сразу после открывающей скобки
e.target.setSelectionRange(3, 3);
}
});
// Обработка Backspace для удаления цифр в скобках
phoneInput.addEventListener('keydown', (e) => {
if (e.key === 'Backspace') {
const start = phoneInput.selectionStart;
// Если каретка стоит сразу после ')', переносим её внутрь скобок
// Формат префикса: "+7(" — цифры начинаются с позиции 3
// Через formatPhone: ")." на позиции 4
if (start === 4) {
e.preventDefault(); // Отменяем обычный Backspace
// Перемещаем курсор внутрь скобок
phoneInput.setSelectionRange(3, 3);
// Удаляем символ перед новой позицией (цифру)
const before = phoneInput.value.slice(0, 3);
const after = phoneInput.value.slice(3);
// Убираем первый символ после позиции 3, затем форматируем
const newVal = before + after.substring(1);
phoneInput.value = formatPhone(newVal);
updateHelp(phoneInput.value);
// Ставим каретку обратно в позицию 3
phoneInput.setSelectionRange(3, 3);
}
}
});
// При потере фокуса: очищаем поле и подсказку, если нет цифр
phoneInput.addEventListener('blur', (e) => {
let raw = e.target.value.replace(/\D/g, '');
if (raw.charAt(0) === '7') {
raw = raw.substring(1);
}
if (raw.length === 0) {
e.target.value = '';
help.textContent = '';
}
});
// Валидация при отправке формы
const form = document.querySelector('.form');
form.addEventListener('submit', (e) => {
phoneInput.classList.remove('error'); // Снимаем класс ошибки
// Получаем только цифры без кода '7'
let raw = phoneInput.value.replace(/\D/g, '');
if (raw.charAt(0) === '7') {
raw = raw.substring(1);
}
// Если не 10 цифр — отменяем отправку и подсвечиваем поле
if (raw.length !== 10) {
e.preventDefault();
phoneInput.classList.add('error');
phoneInput.focus();
}
});
После добавления этого CSS и JavaScript тестируем форму:
- Клик по полю → рамка синяя
- Ввод меньше 10 цифр и отправка → поле красное, форма не уходит
- Ввод 10 цифр → форма успешно отправляется (или проходит валидация)
Есть некоторые ограничения при удалении (стирании) номера телефона, но это не критично. В противном случае лучше воспользоваться библиотекой inputmask.js:
HTML
Перейти к inputmask.js
<script src="https://unpkg.com/imask"></script>
<script>
IMask(phoneInput, {mask: '+{7}(000) 000-00-00'});
</script>