Формы в HTML
Элемент
<form>создаёт интерактивную форму для сбора данных от пользователя и отправки на сервер.
Зачем нужно
Формы -- основной способ ввода данных в вебе: авторизация, регистрация, поиск, комментарии, заказы, фильтры. Без форм веб-приложения не могут взаимодействовать с пользователем.
Где используется
- Логин/регистрация
- Поиск по сайту
- Оформление заказа
- Обратная связь, комментарии
- Настройки профиля
- Фильтры каталога
Предпосылки
Элемент <form>
<form action="/api/login" method="POST">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="password">Пароль:</label>
<input type="password" id="password" name="password" required>
<button type="submit">Войти</button>
</form>
Атрибуты <form>
| Атрибут | Значение | Описание |
|---|---|---|
action |
URL | Куда отправлять данные |
method |
GET / POST |
HTTP-метод |
enctype |
MIME-тип | Кодировка данных |
novalidate |
boolean | Отключить встроенную валидацию |
autocomplete |
on / off |
Автозаполнение |
name |
строка | Имя формы |
target |
_self, _blank |
Куда открыть ответ |
method -- GET vs POST
<!-- GET: данные в URL (строка запроса) -->
<!-- Для поиска, фильтров, публичных данных -->
<form action="/search" method="GET">
<input type="search" name="q">
<button type="submit">Найти</button>
</form>
<!-- Результат: /search?q=html -->
<!-- POST: данные в теле запроса -->
<!-- Для паролей, файлов, изменения данных -->
<form action="/api/register" method="POST">
<input type="email" name="email">
<input type="password" name="password">
<button type="submit">Регистрация</button>
</form>
| GET | POST | |
|---|---|---|
| Данные | В URL (?key=value) | В теле запроса |
| Видимость | Видны в адресной строке | Скрыты |
| Кеширование | Можно закешировать | Нельзя |
| Закладки | Можно сохранить | Нельзя |
| Длина | Ограничена (~2048 символов) | Неограничена |
| Применение | Поиск, фильтры | Логин, файлы, мутации |
enctype -- кодировка данных
<!-- По умолчанию: key=value&key2=value2 -->
<form method="POST" enctype="application/x-www-form-urlencoded">
<!-- Для загрузки файлов (обязательно!) -->
<form method="POST" enctype="multipart/form-data">
<input type="file" name="avatar">
<button type="submit">Загрузить</button>
</form>
<!-- Чистый текст (редко используется) -->
<form method="POST" enctype="text/plain">
Процесс отправки формы
1. Пользователь нажимает submit
2. Браузер валидирует поля (required, pattern, type)
3. Если валидация провалена -- показ ошибок, отправка не происходит
4. Если ОК -- данные кодируются согласно enctype
5. GET: данные добавляются в URL как query string
POST: данные отправляются в теле HTTP-запроса
6. Браузер переходит на URL из action (или перезагружает страницу)
Отправка через JavaScript (без перезагрузки)
<form id="contactForm">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">Отправить</button>
</form>
<script>
document.getElementById('contactForm').addEventListener('submit', async (e) => {
e.preventDefault(); // Предотвращает стандартную отправку
const formData = new FormData(e.target);
try {
const response = await fetch('/api/contact', {
method: 'POST',
body: formData
});
if (response.ok) {
alert('Сообщение отправлено!');
e.target.reset();
}
} catch (error) {
console.error('Ошибка:', error);
}
});
</script>
Объект FormData
const form = document.querySelector('form');
const formData = new FormData(form);
// Получить значение
formData.get('email');
// Добавить поле
formData.append('timestamp', Date.now());
// Перебрать все поля
for (const [key, value] of formData) {
console.log(key, value);
}
// Отправить как JSON
const data = Object.fromEntries(formData);
fetch('/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
Структура доступной формы
<form action="/api/register" method="POST">
<fieldset>
<legend>Личные данные</legend>
<div class="field">
<label for="name">Имя:</label>
<input type="text" id="name" name="name" required autocomplete="given-name">
</div>
<div class="field">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required autocomplete="email">
</div>
</fieldset>
<fieldset>
<legend>Безопасность</legend>
<div class="field">
<label for="password">Пароль:</label>
<input type="password" id="password" name="password"
required minlength="8" autocomplete="new-password">
<p class="hint" id="password-hint">Минимум 8 символов</p>
</div>
</fieldset>
<button type="submit">Зарегистрироваться</button>
</form>
Формы без <form>
Элементы формы могут существовать вне <form>, если связаны через атрибут form:
<form id="searchForm" action="/search" method="GET">
<input type="search" name="q">
</form>
<!-- Кнопка вне формы, но привязана к ней -->
<button type="submit" form="searchForm">Найти</button>
Частые ошибки
| Ошибка | Почему плохо | Как правильно |
|---|---|---|
Нет name на input |
Данные не отправляются | name обязателен для отправки |
| GET для паролей | Пароль виден в URL | method="POST" для паролей |
Нет enctype при загрузке файлов |
Файл не отправится | enctype="multipart/form-data" |
| Вложенные формы | Невалидно, непредсказуемое поведение | Формы не вкладываются друг в друга |
Нет label |
Недоступно для screen readers | Каждый input должен иметь label |
<a> вместо <button type="submit"> |
Нет стандартной отправки формы | Используй <button> |
Практика
- Создай форму логина с
method="POST", email и password полями - Создай поисковую форму с
method="GET"-- посмотри query string в URL - Создай форму загрузки файла с
enctype="multipart/form-data" - Перехвати отправку формы через
e.preventDefault()и отправь черезfetch - Проверь форму через Tab -- все поля должны быть доступны с клавиатуры
Связанные темы
- input типы -- все типы полей ввода
- select и textarea -- выпадающие списки и текстовые области
- button -- кнопки отправки
- label и fieldset -- доступная группировка
- Валидация форм -- проверка данных