Браузер умеет проверять данные форм ещё до отправки на сервер — без единой строки JavaScript. Встроенная валидация ускоряет обратную связь для пользователя, но никогда не заменяет серверную проверку.
Атрибут required
Запрещает отправить форму с пустым полем:
<input type="text" name="username" required />
<textarea name="message" required></textarea>
<select name="category" required>
<option value="">-- Выберите --</option>
<option value="python">Python</option>
</select>
Попытка отправить форму с незаполненным полем покажет всплывающую подсказку браузера.
Ограничения длины и диапазона
<!-- Длина текста -->
<input
type="text"
name="title"
minlength="5"
maxlength="100"
required
/>
<!-- Числовой диапазон -->
<input
type="number"
name="age"
min="18"
max="120"
step="1"
required
/>
<!-- Диапазон дат -->
<input
type="date"
name="publish_date"
min="2024-01-01"
max="2030-12-31"
/>
| Атрибут | Применяется к | Описание |
|---|---|---|
minlength |
text, email, password, textarea |
Минимальное число символов |
maxlength |
то же | Максимальное число символов |
min |
number, date, time |
Минимальное значение |
max |
то же | Максимальное значение |
step |
number, date |
Шаг изменения значения |
Тип поля как валидатор
Некоторые типы <input> автоматически проверяют формат:
<!-- Проверяет наличие @ и точки в домене -->
<input type="email" name="email" required />
<!-- Проверяет формат URL -->
<input type="url" name="website" placeholder="https://example.com" />
<!-- Телефон — формат зависит от браузера, ненадёжно -->
<input type="tel" name="phone" />
Шаблон pattern
Регулярное выражение для точной проверки формата:
<!-- Только латинские буквы и цифры, 3–20 символов -->
<input
type="text"
name="username"
pattern="[a-zA-Z0-9]{3,20}"
title="Только латинские буквы и цифры, от 3 до 20 символов"
required
/>
<!-- Формат телефона -->
<input
type="tel"
name="phone"
pattern="\+7\d{10}"
placeholder="+79001234567"
title="Формат: +7XXXXXXXXXX"
/>
<!-- Слаг для URL поста -->
<input
type="text"
name="slug"
pattern="[a-z0-9-]+"
title="Только строчные буквы, цифры и дефис"
/>
Атрибут title содержит текст подсказки, который покажет браузер при ошибке.
Псевдоклассы :valid и :invalid
CSS позволяет стилизовать поля в зависимости от их состояния валидации:
/* Состояние по умолчанию — нейтральный бордер */
input {
border: 1px solid #d1d5db;
border-radius: 4px;
padding: 0.5rem;
outline: none;
transition: border-color 0.2s;
}
/* Поле в фокусе */
input:focus {
border-color: #3b82f6;
}
/* Валидное поле (после первого взаимодействия) */
input:valid {
border-color: #22c55e;
}
/* Невалидное поле */
input:invalid {
border-color: #ef4444;
}
Проблема: :invalid срабатывает сразу при загрузке страницы для всех required-полей, ещё до того, как пользователь что-либо ввёл. Решение — использовать псевдокласс :user-invalid (современные браузеры) или активировать стили только после первого submit:
/* Срабатывает только после попытки отправки — поддерживается в Chrome 119+ */
input:user-invalid {
border-color: #ef4444;
}
Или программный вариант через JavaScript — добавить класс на форму при submit:
<style>
.was-validated input:invalid {
border-color: #ef4444;
}
</style>
<form id="contact-form">
<input type="email" name="email" required />
<button type="submit">Отправить</button>
</form>
<script>
document.getElementById("contact-form").addEventListener("submit", (e) => {
e.currentTarget.classList.add("was-validated");
});
</script>
Отключение встроенной валидации
Иногда нужно реализовать полностью кастомную логику проверки. Атрибут novalidate на форме отключает браузерную валидацию:
<form action="/contact/" method="post" novalidate>
<!-- Валидацию берёт на себя JavaScript или Django -->
</form>
Граница ответственности
Встроенная валидация HTML решает задачу UX: быстрая обратная связь до отправки запроса. Но её легко обойти — через DevTools, curl или сторонний HTTP-клиент.
Серверная валидация обязательна всегда:
# Django автоматически валидирует поля формы
class ContactForm(forms.Form):
name = forms.CharField(min_length=2, max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea, min_length=10)
def contact(request):
form = ContactForm(request.POST or None)
if form.is_valid():
# данные чисты — обрабатываем
pass
return render(request, "contact.html", {"form": form})
Правило: HTML-валидация — для удобства пользователя. Серверная валидация — для безопасности данных. Одно без другого неполноценно.
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!