Данные в строках и столбцах и страницы, которые принимают данные от людей
Таблица — для данных, у которых есть строки и столбцы: расписание, прайс, сравнение тарифов. Строка — <tr>, ячейка — <td>, ячейка-заголовок — <th>. <caption> — название таблицы, <thead> и <tbody> отделяют шапку от данных.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Расписание</title>
<style>
table, th, td { border: 1px solid #999; border-collapse: collapse; padding: 4px 8px; }
</style>
</head>
<body>
<table>
<caption>Расписание группы 21В на понедельник</caption>
<thead>
<tr>
<th scope="col">Время</th>
<th scope="col">Предмет</th>
<th scope="col">Аудитория</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">9:00</th>
<td>Основы Python</td>
<td>214</td>
</tr>
<tr>
<th scope="row">10:40</th>
<td colspan="2">Большая перемена</td>
</tr>
<tr>
<th scope="row">12:20</th>
<td>Основы HTML и CSS</td>
<td>301</td>
</tr>
</tbody>
</table>
</body>
</html>

Без CSS у таблицы нет рамок — строка в <style> их добавляет (как устроен CSS — в модуле 04). colspan="2" растягивает ячейку на два столбца, rowspan — на несколько строк. scope="col" и scope="row" связывают заголовок со столбцом или строкой: экранный диктор, читая ячейку «214», может сообщить, что это аудитория для 9:00.
Форма — <form> с полями внутри. action — адрес, куда отправить данные, method — как (раздел 05). У каждого поля есть name — под этим именем значение уйдёт на сервер — и подпись <label>.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Запись на курс</title>
</head>
<body>
<h1>Запись на курс</h1>
<form action="thanks.html" method="get">
<p>
<label for="name">Имя</label><br>
<input type="text" id="name" name="name" required autocomplete="name">
</p>
<p>
<label for="email">Почта</label><br>
<input type="email" id="email" name="email" required autocomplete="email">
</p>
<p>
<label for="course">Курс</label><br>
<select id="course" name="course">
<option value="python">Основы Python</option>
<option value="html" selected>Основы HTML и CSS</option>
</select>
</p>
<fieldset>
<legend>Формат</legend>
<label><input type="radio" name="format" value="online" checked> онлайн</label>
<label><input type="radio" name="format" value="offline"> в аудитории</label>
</fieldset>
<p>
<label for="comment">Комментарий</label><br>
<textarea id="comment" name="comment" rows="3" cols="30"></textarea>
</p>
<p>
<label>
<input type="checkbox" name="consent" value="yes" required>
Согласен на обработку персональных данных
</label>
</p>
<button type="submit">Записаться</button>
</form>
</body>
</html>

Так выглядит форма со стилями браузера по умолчанию — оформлять её будем в модулях 04–05. Подпись связывается с полем атрибутом for, равным id поля, или полем внутри <label>. Связанная подпись кликабельна (попасть по ней проще, чем по маленькому флажку), и диктор читает её, когда поле получает фокус.
placeholder — серый текст-пример внутри поля — не заменяет <label>: он исчезает, как только пользователь начал печатать, и часто слишком бледный, чтобы его прочитать.Атрибут type у <input> меняет поле: на телефоне для tel откроется цифровая клавиатура, для email — клавиатура с @, для date — календарь.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Типы полей</title>
</head>
<body>
<form>
<p><label for="t">tel</label> <input type="tel" id="t" name="t" placeholder="+7 900 000-00-00"></p>
<p><label for="n">number</label> <input type="number" id="n" name="n" min="1" max="10" value="3"></p>
<p><label for="d">date</label> <input type="date" id="d" name="d" value="2026-10-15"></p>
<p><label for="p">password</label> <input type="password" id="p" name="p" value="секрет"></p>
<p><label for="r">range</label> <input type="range" id="r" name="r" min="0" max="100" value="70"></p>
<p><label for="c">color</label> <input type="color" id="c" name="c" value="#1967d2"></p>
</form>
</body>
</html>

| Элемент | Для чего |
|---|---|
text, email, tel, url, password | Строка текста; у password символы скрыты |
number, range | Число; min, max, step ограничивают значения |
date, time | Дата и время с выбором из календаря |
checkbox | Флажок: да/нет или несколько вариантов из списка |
radio | Один вариант из группы; группа — одинаковый name |
file | Выбор файла для загрузки |
<select> + <option> | Выпадающий список |
<textarea> | Многострочный текст |
<button type="submit"> | Отправить форму |
Связанные поля группируют в <fieldset> с заголовком <legend> — как переключатели «Формат» в форме выше. Атрибут autocomplete (name, email, tel) позволяет браузеру подставить сохранённые данные.
Атрибуты проверки браузер выполняет сам, до отправки: required — поле обязательно, type="email" — строка похожа на адрес почты, min/max — границы числа, minlength/maxlength — длина текста, pattern — шаблон (регулярное выражение). Если проверка не прошла, форма не отправится, а у первого неверного поля появится подсказка. Сообщения, которые Chromium с русским интерфейсом выдал для формы выше:
Пустая форма, поле «Имя»: Заполните это поле.
Почта «anna@»: Введите часть адреса после символа "@". Адрес "anna@" неполный.
required в инструментах разработчика или послать запрос программой. Сервер обязан проверять всё заново.При отправке браузер собирает пары name=значение всех заполненных полей. Для флажков и переключателей уходит value отмеченного. Форму выше заполнили и отправили в Chromium — вот адрес, на который перешёл браузер (метод get):
thanks.html?name=%D0%90%D0%BD%D0%BD%D0%B0&email=anna%40example.ru&course=html&format=offline&comment=%D0%A3%D0%B4%D0%BE%D0%B1%D0%BD%D0%BE+%D0%BF%D0%BE+%D0%B2%D0%B5%D1%87%D0%B5%D1%80%D0%B0%D0%BC&consent=yes
Пары разделены & и добавлены к адресу после ?. Кириллица и спецсимволы закодированы: «Анна» — это %D0%90%D0%BD%D0%BD%D0%B0 (байты UTF-8), @ — %40, пробел — +.
| method | Как передаются данные | Для чего |
|---|---|---|
get | В адресе страницы: видны, сохраняются в истории, в закладках и журналах сервера | Поиск и фильтры: адрес с результатом можно отправить другу |
post | В теле запроса, в адресе их нет | Регистрация, заказ, всё, что меняет данные или содержит личные сведения |
Форму записи на курс правильно отправлять методом post: имя и почта не должны оставаться в истории браузера и журналах. get в примере — чтобы данные было видно. Без сервера, который примет данные, форма никуда их не сохранит: обработку пишут на Python, PHP или другом серверном языке.
Имя, телефон и почта — персональные данные. Сайт, который их собирает, становится оператором персональных данных по закону 152-ФЗ, и форма должна это учитывать:
required).post.Кроме того, оператор подаёт уведомление в Роскомнадзор и хранит данные граждан России на серверах в России. Это уже не вёрстка, но верстальщик первым видит форму и должен задать заказчику вопрос, кто и как будет хранить эти данные.
caption, thead/tbody, th со scopename (ключ на сервере) и связанный <label>; placeholder подпись не заменяетemail, tel, date) даёт нужную клавиатуру и проверкуrequired, min, pattern — подсказка пользователю, сервер проверяет зановоget — данные в адресе, post — в теле запроса; личные данные — только post