Олег Марков
Поле email в HTML - input type email
Введение
Поле email в HTML на первый взгляд кажется простым элементом формы. Вы указываете тип поля как email, браузер что‑то проверяет, пользователь вводит адрес — и все работает. На практике у input type="email" есть много нюансов: встроенная валидация, разные варианты отображения на мобильных устройствах, вопросы доступности и особенности работы с JavaScript.
Здесь вы разберете, как правильно использовать поле email в HTML, какие ошибки оно может отлавливать, когда встроенной проверки недостаточно и как комбинировать HTML‑валидацию с собственной логикой на стороне клиента и сервера. Я покажу вам примеры разметки и сценарии, с которыми вы почти наверняка столкнетесь в реальных проектах.
Синтаксис и базовое использование
Базовый пример input type="email"
Давайте начнем с простейшего примера разметки поля email:
<form>
<!-- Метка для поля email -->
<label for="user-email">Ваш email</label>
<!-- Поле ввода email -->
<input
type="email" <!-- Сообщаем браузеру, что это поле для email -->
id="user-email" <!-- Связь с label и доступность -->
name="email" <!-- Имя поля при отправке формы -->
required <!-- Обязательное поле -->
placeholder="name@example.com" <!-- Подсказка для пользователя -->
>
<!-- Кнопка отправки формы -->
<button type="submit">Отправить</button>
</form>
Как видите, достаточно указать type="email", чтобы браузер включил базовую проверку формата адреса электронной почты. При этом:
- На десктопе пользователь увидит обычное текстовое поле.
- На мобильных устройствах зачастую появляется специальная клавиатура (с символом
@и точкой в удобных местах). - При попытке отправить форму с неверным форматом email браузер отобразит сообщение об ошибке (если валидация не отключена).
Что именно проверяет браузер
Важно понимать, что встроенная проверка формата email в браузере не идеальна, но она опирается на достаточно разумное приближение стандарта. Обычно браузер проверяет:
- Есть ли в строке хотя бы один символ до
@. - Есть ли символ
@. - Есть ли хотя бы один символ между
@и точкой в домене. - Есть ли хотя бы одна точка после
@. - Есть ли хотя бы один символ после последней точки в домене.
Например:
- Разрешено:
user@example.com - Разрешено:
user.name+tag@sub.domain.co.uk - Запрещено:
userexample.com(нет@) - Запрещено:
user@(нет домена) - Запрещено:
@example.com(нет имени пользователя) - Запрещено:
user@example(нет точки в домене)
При этом HTML‑валидация не проверяет, существует ли домен на самом деле, или реально ли можно отправить письмо на этот адрес. Это всегда задача серверной стороны.
Встроенная валидация и атрибуты
Обязательность поля — required
Если вы хотите, чтобы пользователь обязательно заполнил email, добавьте атрибут required.
<input
type="email"
name="email"
required <!-- Без заполнения поля форма не отправится -->
>
Браузер не позволит отправить форму, пока:
- Поле пустое.
- Формат не соответствует email.
Здесь вы получаете сразу две проверки одновременно: на заполненность и на корректность формата.
Разрешение нескольких адресов — multiple
Иногда необходимо дать пользователю возможность ввести сразу несколько email‑адресов, например при приглашении нескольких людей. В этом случае используйте атрибут multiple.
<input
type="email"
name="emails"
multiple <!-- Разрешаем несколько адресов -->
placeholder="user1@example.com, user2@example.com"
/>
Как это работает:
- Пользователь разделяет email‑адреса запятыми.
- Браузер проверяет каждый адрес на соответствие формату email.
- Если хотя бы один из адресов некорректен, форма не будет отправлена (при включенной проверке).
Пример валидного значения:
user1@example.com, user2@example.org, name+tag@domain.co
Максимальная и минимальная длина — maxlength и minlength
Вы можете ограничить длину введенного email:
<input
type="email"
name="email"
minlength="5" <!-- Минимум 5 символов -->
maxlength="50" <!-- Максимум 50 символов -->
required
>
Несколько замечаний:
minlengthучаствует в HTML‑валидации. Если ввод короче — форма не отправится.maxlengthограничивает длину ввода в самом поле (пользователь просто не сможет ввести больше символов).- В любом случае подобные ограничения обязательно нужно дублировать на сервере, чтобы защититься от обхода валидации.
Управление автозаполнением — autocomplete
Браузеры запоминают email‑адреса и могут подставлять их автоматически. Управлять этим можно через атрибут autocomplete.
<!-- Стандартное поле email для логина или регистрации -->
<input
type="email"
name="email"
autocomplete="email" <!-- Явно указываем, что это email пользователя -->
>
<!-- Например, альтернативный email для восстановления доступа -->
<input
type="email"
name="backup_email"
autocomplete="off" <!-- Отключаем автозаполнение -->
>
Наиболее полезное значение здесь — email. Оно помогает браузеру правильно распознавать поле и предлагать пользователю подходящие варианты.
Плейсхолдер — placeholder
Плейсхолдер часто используют для подсказки формата ввода:
<input
type="email"
name="email"
placeholder="name@example.com"
/>
Здесь важно не превращать placeholder в замену полноценной метки <label>. Метка нужна для доступности и для пользователей, которые не видят или не различают серый текст плейсхолдера. Лучше комбинировать:
<label for="email">Email</label>
<input
id="email"
type="email"
name="email"
placeholder="name@example.com"
/>
Пользовательские сообщения об ошибках
Стандартное сообщение браузера
Если вы просто используете type="email" и required, браузер сам покажет сообщение об ошибке. Однако:
- Текст сообщения зависит от браузера и языка интерфейса.
- Текст не всегда понятен или не соответствует тону вашего интерфейса.
- Иногда вам нужно более конкретное сообщение (например, различать «поле пустое» и «неверный формат»).
Установка собственного сообщения — setCustomValidity
Теперь покажу вам, как задать собственные сообщения при помощи JavaScript и метода setCustomValidity.
<form id="signup-form">
<label for="email">Email</label>
<input
id="email"
type="email"
name="email"
required
>
<button type="submit">Зарегистрироваться</button>
</form>
<script>
// Находим элементы формы и поля
const form = document.getElementById('signup-form');
const emailInput = document.getElementById('email');
// Сбрасываем сообщение об ошибке при вводе
emailInput.addEventListener('input', () => {
// Очищаем пользовательское сообщение
emailInput.setCustomValidity('');
// Перезапускаем проверку, чтобы убрать визуальное состояние ошибки
emailInput.checkValidity();
});
// Обрабатываем попытку отправки формы
form.addEventListener('submit', (event) => {
// Если поле не прошло встроенную валидацию
if (!emailInput.validity.valid) {
if (emailInput.validity.valueMissing) {
// Если поле пустое
emailInput.setCustomValidity('Пожалуйста, укажите ваш email');
} else if (emailInput.validity.typeMismatch) {
// Если формат не похож на email
emailInput.setCustomValidity('Введите email в формате name@example.com');
}
// Запрещаем отправку формы
event.preventDefault();
// Запускаем показ сообщения браузером
emailInput.reportValidity();
}
});
</script>
Обратите внимание на важные моменты:
- Сначала мы всегда сбрасываем пользовательское сообщение через
setCustomValidity(''), иначе старое сообщение будет «залипать». - Обращаемся к объекту
validity, чтобы понять, какая именно ошибка произошла (valueMissing,typeMismatchи другие флаги). - Для показа сообщения можно использовать
reportValidity(), который активирует стандартное всплывающее сообщение браузера.
Объект validity и его флаги
У каждого поля формы есть объект validity, который описывает состояние валидации. Для email полезны в основном такие свойства:
valueMissing— поле пустое, ноrequiredстоит.typeMismatch— значение не соответствует форматуtype="email".tooShort— введено меньше символов, чем указано вminlength.tooLong— введено больше символов, чем вmaxlength.valid— общее булево поле, которое показывает, все ли проверки пройдены.
Простой пример проверки без вывода кастомных сообщений:
if (emailInput.validity.valid) {
// Все ок - можно отправлять или обрабатывать
} else {
// Что-то не так - смотрим причины
}
Работа с несколькими email-адресами
Как пользователь должен вводить несколько адресов
Если вы указали атрибут multiple, пользователь должен перечислять адреса через запятую:
<input
type="email"
name="emails"
multiple
placeholder="user1@example.com, user2@example.com"
/>
Примеры:
- Валидно:
user1@example.com, user2@example.com - Валидно:
user1@example.com , user2@example.com(пробелы допустимы) - Невалидно:
user1@example.com; user2@example.com(точка с запятой не подходит)
Разбор значений в JavaScript
Теперь вы увидите, как превратить строку из поля в массив email‑адресов на JavaScript:
const input = document.querySelector('input[name="emails"]');
// Берем строку из поля
const raw = input.value;
// Разделяем по запятой и очищаем пробелы
const emails = raw
.split(',') // Получаем массив строк
.map(email => email.trim())// Убираем пробелы по краям
.filter(email => email); // Убираем пустые элементы
// Здесь emails - массив строк вида ['user1@example.com', 'user2@example.com']
Дополнительно вы можете пройтись по этому массиву и выполнить дополнительные проверки, если встроенной валидации вам недостаточно.
Поведение на мобильных устройствах
Специальная клавиатура
На смартфонах и планшетах input type="email" обычно открывает клавиатуру, в которой:
- Отображается быстрый доступ к символу
@. - Удобнее вводить точки и доменные имена.
- Иногда предлагаются подсказки из ранее введенных email‑адресов.
За счет этого пользователю проще и быстрее заполнять поле, особенно если это обязательный шаг (регистрация, вход).
Автозаполнение и менеджеры паролей
Поля email часто используются в паре с input type="password". Многие браузеры и менеджеры паролей ожидают увидеть определенные значения атрибутов, чтобы корректно предлагать автозаполнение.
Хорошая практика:
<input
type="email"
id="login-email"
name="email"
autocomplete="email" <!-- Подсказка для браузера и менеджеров паролей -->
>
<input
type="password"
id="login-password"
name="password"
autocomplete="current-password"
/>
Так вы помогаете экосистеме вокруг поля email работать стабильно и предсказуемо.
Доступность и правильная разметка
Связь label и input
Для удобства и доступности нужно связывать поле email с меткой <label>:
<label for="user-email">Email</label>
<input
type="email"
id="user-email" <!-- Должен совпадать с for у label -->
name="email"
>
Здесь происходит следующее:
- Клик по тексту «Email» фокусирует поле.
- Скринридеры читают метку вместе с полем.
- Пользователю проще понять, что это за поле, даже если плейсхолдер скрыт.
aria-describedby для подсказок и ошибок
Если у поля есть дополнительный текст (подсказка или сообщение об ошибке), полезно связать его с полем через aria-describedby.
<label for="email">Email</label>
<input
type="email"
id="email"
name="email"
aria-describedby="email-help email-error" <!-- Список ID с подсказкой и ошибкой -->
>
<p id="email-help">
Мы используем ваш email только для уведомлений о заказах.
</p>
<p id="email-error" class="error" hidden>
Некорректный формат email.
</p>
Когда вы показываете ошибку, просто уберите атрибут hidden или измените стиль:
// Пример показа ошибки
document.getElementById('email-error').hidden = false;
Скринридеры прочитают и подсказку, и сообщение об ошибке, что улучшит доступность формы.
HTML-валидация против серверной и кастомной логики
Ограничения HTML-валидации
HTML‑валидация удобна тем, что:
- Не требует JavaScript.
- Работает во всех современных браузерах.
- Быстро отрабатывает типичные ошибки формата.
Но у нее есть ограничения:
- Ее можно отключить или обойти (например, через инструменты разработчика).
- Она не знает, существует ли домен и реальный ли это email.
- Она плохо подходит для сложных правил (например, ограничения доменов).
Поэтому встроенную валидацию стоит рассматривать как первую линию защиты и удобство для пользователя, но не как окончательное решение.
Зачем нужна серверная проверка
На сервере вы можете:
- Проверить, что email не занят (при регистрации).
- Проверить, что такой email существует в базе (при входе).
- Ограничить адреса определенными доменами (например, только корпоративная почта).
- Отправить письмо с подтверждением и убедиться, что адрес активен.
Даже если поле указано как type="email", сервер должен проверять:
- Формат email.
- Дополнительные бизнес‑правила.
- Возможные атаки (например, очень длинные строки, внедрение спецсимволов и т. д.).
Комбинирование HTML, JavaScript и сервера
Распространенная стратегия:
На уровне HTML:
type="email",required,- возможно,
minlengthиmaxlength.
На уровне JavaScript:
- Дополнительные подсказки и пользовательские сообщения.
- Предварительная проверка формата или домена.
- Мгновенная обратная связь без перезагрузки страницы.
На стороне сервера:
- Повторная проверка формата.
- Проверка бизнес‑правил.
- Регистрация или вход только после успешной валидации.
Такой подход не перегружает пользователя, но при этом защищает приложение.
Примеры типичных сценариев
Регистрация с подтверждением email
Давайте разберем форму регистрации, в которой email — обязательное поле:
<form id="register-form">
<label for="reg-email">Email</label>
<input
id="reg-email"
type="email"
name="email"
required
autocomplete="email"
>
<label for="reg-password">Пароль</label>
<input
id="reg-password"
type="password"
name="password"
required
>
<button type="submit">Создать аккаунт</button>
</form>
<script>
const form = document.getElementById('register-form');
const emailInput = document.getElementById('reg-email');
form.addEventListener('submit', (event) => {
// Если встроенная проверка формата и заполненности не пройдена
if (!emailInput.validity.valid) {
event.preventDefault(); // Отменяем отправку
// Устанавливаем свое сообщение в зависимости от типа ошибки
if (emailInput.validity.valueMissing) {
emailInput.setCustomValidity('Укажите email для регистрации');
} else if (emailInput.validity.typeMismatch) {
emailInput.setCustomValidity('Введите корректный адрес электронной почты');
}
emailInput.reportValidity(); // Показываем сообщение
} else {
// На всякий случай очищаем customValidity, если до этого была ошибка
emailInput.setCustomValidity('');
}
});
</script>
С точки зрения UX:
- Пользователь сразу видит конкретное сообщение.
- HTML берет на себя большую часть проверки.
- Сервер при этом все равно должен перепроверить данные, когда форма дойдет до него.
Форма обратной связи с необязательным email
Иногда email не обязателен, но вы хотите проверить формат, если пользователь его ввел:
<form id="feedback-form">
<label for="message">Сообщение</label>
<textarea id="message" name="message" required></textarea>
<label for="contact-email">
Email для ответа (необязательно)
</label>
<input
id="contact-email"
type="email"
name="email"
placeholder="name@example.com"
>
<button type="submit">Отправить</button>
</form>
<script>
const form = document.getElementById('feedback-form');
const emailInput = document.getElementById('contact-email');
form.addEventListener('submit', (event) => {
// Если поле пустое, то ошибок нет - email необязателен
if (!emailInput.value) {
emailInput.setCustomValidity(''); // Сбрасываем прошлые ошибки
return;
}
// Если что-то введено, проверяем формат
if (!emailInput.validity.valid) {
event.preventDefault();
if (emailInput.validity.typeMismatch) {
emailInput.setCustomValidity('Если вы указываете email, он должен быть в корректном формате');
}
emailInput.reportValidity();
} else {
emailInput.setCustomValidity('');
}
});
</script>
Такая логика дает пользователю свободу: можно оставить поле пустым, но если email указан, он должен быть корректным.
Частые ошибки и анти‑паттерны
Использование type="text" вместо type="email"
Одна из распространенных ошибок — использовать type="text" для email:
<!-- Неудачный вариант -->
<input type="text" name="email">
Чем это плохо:
- Не работает встроенная валидация формата.
- Мобильные устройства не показывают удобную клавиатуру.
- Менеджеры паролей и autofill хуже распознают поле.
Лучше всегда использовать:
<input type="email" name="email">
Полная опора только на HTML-валидацию
Еще один анти‑паттерн — полагаться только на HTML‑валидацию, не проверяя данные на сервере. Например, многие думают, что раз в браузере стоит type="email", то проверять email на сервере уже не обязательно.
Это ошибочное предположение, потому что:
- Пользователь может отключить валидацию.
- Запрос можно отправить напрямую, минуя браузер (через скрипт или API‑клиент).
- HTML‑валидация не проверяет существование почтового ящика.
Сервер всегда должен проверять email заново.
Слишком строгие регулярные выражения
Если вы добавляете собственную проверку email через RegExp в JavaScript, есть риск сделать ее слишком строгой и заблокировать корректные адреса. Например:
// Пример неоправданно строгого паттерна
const EMAIL_REGEXP = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/;
Проблема:
- Не учитываются длинные домены верхнего уровня (например,
.museum,.business). - Не учитывается возможное использование Unicode‑символов (в некоторых случаях).
Нередко оказывается лучше:
- Положиться на встроенную HTML‑валидацию
type="email". - На сервере использовать хорошо протестированные библиотеки для проверки email.
Расширенные возможности: pattern и кастомные правила
Атрибут pattern
Если встроенной проверки type="email" недостаточно, можно добавить свой паттерн через атрибут pattern. Например, вы хотите разрешать только корпоративные адреса на домене company.com:
<input
type="email"
name="email"
required
pattern="^[^@]+@company\.com$" <!-- Разрешаем только домен company.com -->
title="Используйте корпоративный email на домене company.com" <!-- Подсказка браузеру -->
>
Обратите внимание:
patternприменяется поверх проверки типа. То есть строка сначала должна быть похожа на email, а уже потом — подходить под шаблон.titleотображается как подсказка для пользователя при ошибке валидации.
Сложные правила лучше вынести в JavaScript
Если правила становятся слишком громоздкими, регулярное выражение в атрибуте pattern может сделать код плохо читаемым. В этом случае удобнее перенести дополнительную проверку в JavaScript:
const emailInput = document.querySelector('#email');
function isCorporateEmail(email) {
// Простая проверка домена, без сложного RegExp
// Здесь мы просто проверяем, что строка заканчивается нужным доменом
return email.endsWith('@company.com');
}
emailInput.addEventListener('input', () => {
const value = emailInput.value;
// Если поле пустое, даем стандартной required‑валидации все обработать
if (!value) {
emailInput.setCustomValidity('');
return;
}
// Сначала убеждаемся, что базовый формат email верный
if (!emailInput.validity.typeMismatch && isCorporateEmail(value)) {
emailInput.setCustomValidity(''); // Все хорошо
} else {
emailInput.setCustomValidity('Используйте корпоративный email на домене company.com');
}
});
Так код получается более читаемым, а проверка — наглядной.
Заключение
Поле email в HTML, заданное как input type="email", — это не просто текстовое поле, а элемент с набором встроенных возможностей: проверка формата, поддержка автозаполнения, удобное поведение на мобильных устройствах и интеграция с системой валидации форм в браузере.
Используя его, вы получаете:
- Базовую валидацию формата email без JavaScript.
- Улучшенный пользовательский опыт на смартфонах и планшетах.
- Более понятную разметку для браузеров, менеджеров паролей и средств доступности.
Но при этом важно помнить:
- HTML‑валидация — лишь первый слой. Сервер должен обязательно перепроверять email и применять бизнес‑правила.
- Не стоит усложнять проверку с помощью чрезмерно строгих регулярных выражений.
- Пользовательские сообщения через
setCustomValidityи объектvalidityпозволяют сделать ошибки понятными и аккуратно встроенными в интерфейс. - Для необязательных полей email логика валидации должна учитывать, что пустое значение — это нормально.
Если вы будете комбинировать HTML‑возможности, JavaScript‑логику и серверную проверку, поле email станет надежной частью формы, а пользователю будет проще и быстрее выполнять ввод.
Частозадаваемые технические вопросы по теме и ответы
Как отключить встроенную HTML-валидацию email и проверять все только через JavaScript?
Чтобы отключить встроенную валидацию браузера для всей формы, используйте атрибут novalidate у <form>:
<form id="form" novalidate>
<input type="email" id="email">
</form>
В этом случае браузер не будет блокировать отправку формы и показывать свои сообщения. Далее вы сами подписываетесь на событие submit и проверяете поле в JavaScript:
form.addEventListener('submit', (event) => {
const value = emailInput.value.trim();
if (!value) {
event.preventDefault();
// Показываете свое сообщение об ошибке
}
// Здесь может быть ваша проверка формата
});
Почему email с символами вроде плюс или точка иногда считается неверным?
Часто проблема не в input type="email", а в кастомном регулярном выражении, которое вы добавили поверх. Браузер по умолчанию разрешает + и . в локальной части email, а ваша проверка может их запрещать. Решение: либо доверьтесь встроенной проверке типа, либо используйте более мягкое регулярное выражение и протестируйте популярные форматы вроде user.name+tag@example.com.
Как запретить вставку пробелов в поле email?
HTML сам не удаляет пробелы посередине строки, он лишь может обрезать их по краям при отправке. Если вы хотите очистить пробелы в процессе ввода, подпишитесь на событие input и фильтруйте значение:
emailInput.addEventListener('input', () => {
// Заменяем все пробелы на пустую строку
emailInput.value = emailInput.value.replace(/\s+/g, '');
});
Так вы не позволите пользователю случайно ввести пробел.
Как получить домен email в JavaScript и проверить его отдельно?
Сначала убедитесь, что поле прошло базовую проверку, а затем разделите строку по @:
const value = emailInput.value.trim();
if (emailInput.validity.valid) {
const [, domain] = value.split('@'); // Берем часть после @
if (domain === 'example.com') {
// Особая логика для этого домена
}
}
Важно предварительно убедиться, что формат валиден, иначе split('@') может вернуть неожиданные значения.
Как обойти ограничения pattern для тестовых данных в среде разработки?
Если в продакшене вы используете pattern для ограничений (например, только корпоративный домен), а в разработке нужно вводить любые email, делайте шаблон инициализируемым из конфигурации. Например, генерируйте атрибут pattern на сервере только для боевого окружения, а в dev‑режиме рендерьте поле без этого атрибута и переносите проверку домена в серверный код. Так разработчики смогут использовать тестовые адреса без ломки клиентской валидации.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев