HTML: из чего состоит страница
- Зачем это нужно
- Три языка, три разных вопроса
- Элемент: тег, атрибуты, содержимое
- Скелет документа
- Браузер не отказывается — он достраивает
- У каждого тега уже есть оформление
- Смысловые теги: не всё есть div
- Формы: браузер проверяет за вас
- Ссылки, картинки и то, что к ним прилагается
- Типичные ошибки
- Слова главы
- Тренажёр: набрать вслепую
- На чемпионате
- Куда углубиться
- Куда дальше: проверенные ресурсы
Зачем это нужно
Контракт развёрнут, адрес есть, транзакции проходят. Но пользоваться этим пока может только тот, кто умеет писать скрипты.
Задание требует другого: рабочий интерфейс, в котором человек нажимает кнопку, подтверждает операцию в кошельке и видит результат. Оценивают именно его — вместе с контрактом, а не вместо.
Начинается интерфейс с языка разметки. Он не программирует — он описывает, что на странице есть: заголовок, поле ввода, кнопка, таблица операций. Всё остальное — оформление и поведение — прикладывается к этому описанию.
Три языка, три разных вопроса
Язык разметки отвечает на вопрос «что здесь есть». Это заголовок. Это поле для суммы. Это кнопка отправки. Это таблица.
Язык оформления отвечает «как это выглядит»: размеры, цвета, расположение.
Язык сценариев отвечает «что происходит»: нажали кнопку — собрали транзакцию, отправили в сеть, показали результат. Это уже знакомый нам TypeScript, только выполняется он не в Node, а в браузере.
Порядок не случаен. Страница живёт без оформления (некрасиво, но работает) и без сценариев (статично, но читается). Без разметки не живёт вовсе: оформлять и оживлять нечего.
Элемент: тег, атрибуты, содержимое
<input id="amount" type="number" min="1" placeholder="Сумма в ETH">
Большинство элементов устроены иначе — с содержимым и закрывающим тегом:
<button type="submit">Отправить</button>
Здесь Отправить — содержимое, а </button> — закрывающий тег. Элементы вкладывают друг в друга, и получается дерево: страница — это не текст сверху вниз, а дерево элементов.
Скелет документа
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Хранилище</title>
</head>
<body>
<h1>Хранилище</h1>
</body>
</html>
Проверка на живой странице показывает, что из этого куда попадает:
заголовок вкладки: "Хранилище"
язык страницы : ru
Браузер не отказывается — он достраивает
Компилятор Solidity на ошибку отвечает отказом. Браузер устроен ровно наоборот: он всегда что-нибудь покажет, даже если разметка сломана. Это удобно и опасно одновременно.
Первый прогон: ни один тег не закрыт.
написали: <p>первый<p>второй<div>третий</div> — ни один тег не закрыт
получилось: p, p, div
внутри первого p: "первый"
Браузер сам закрыл первый абзац, когда начался второй. Результат оказался тем, что мы имели в виду.
Второй прогон выглядит так же безобидно, но заканчивается иначе:
написали: <p>снаружи<div>внутри</div>хвост</p>
── что получилось ──
<p>
текст: "снаружи"
<div>
текст: "внутри"
текст: "хвост"
<p>
Разберём по шагам. Абзац открылся. Встретился блочный элемент — по правилам разбора он закрывает абзац, потому что абзац не может содержать блочные элементы. Слово «хвост» оказалось уже вне абзаца — прямо в теле документа. А закрывающий </p> без открывающего создал пустой абзац.
Вместо двух элементов получилось четыре узла, и один из них пуст. При этом:
- ошибки не было;
- предупреждения не было;
- на экране всё выглядит примерно как задумано.
Расхождение проявится позже: оформление применится не туда, поиск по дереву вернёт не то, а «хвост» невозможно будет выбрать как часть абзаца.
Отсюда правило: разметку проверяют инструментом, а не глазами. Глазами она выглядит правильной ровно до того момента, когда что-то перестаёт работать без объяснений.
У каждого тега уже есть оформление
Файл без единой строки оформления выглядит не как голый текст. Браузер применяет к тегам собственные стили. Прогон снимает их с живой страницы:
тег размер жирность отступы св/сн поток
h1 32px 700 21.44px / 21.44px блочный
h2 24px 700 19.92px / 19.92px блочный
h3 18.72px 700 18.72px / 18.72px блочный
p 16px 400 16px / 16px блочный
ul 16px 400 16px / 16px блочный
li 16px 400 0 / 0 элемент списка
a 16px 400 0 / 0 строчный
strong 16px 700 0 / 0 строчный
code 13px 400 0 / 0 строчный
button 13.3333px 400 0 / 0 строчно-блочный
input 13.3333px 400 0 / 0 строчно-блочный
span 16px 400 0 / 0 строчный
div 16px 400 0 / 0 блочный
body: margin 8px, шрифт Times
Три вывода.
Блочные и строчные — разные по поведению. Блочный занимает всю доступную ширину и начинается с новой строки: заголовки, абзацы, списки, div. Строчный занимает только своё место в строке и переносится вместе с текстом: ссылка, strong, code, span.
Отступы у заголовков и абзацев — не ваши. Их дал браузер. Отсюда вечное «между блоками откуда-то взялся зазор»: он был там с самого начала.
У тела документа поля 8 точек, а шрифт — Times. Это и есть причина, по которой оформление почти всегда начинают со сброса: обнуляют поля и задают нормальный шрифт.
Размер 13.3333px у кнопки и поля ввода — не опечатка. Это наследие давних договорённостей об элементах управления, и в разных браузерах числа чуть расходятся. Ещё одна причина задавать размеры самому.
Смысловые теги: не всё есть div
Технически всю страницу можно собрать из div и span. Работать будет. Но теги выбирают не за внешний вид, а за смысл — по нему страницу понимают те, кто её не видит.
<header><h1>Хранилище</h1></header>
<nav><a href="/">Главная</a> <a href="/about">О проекте</a></nav>
<main>
<article>
<h2>Ваш вклад</h2>
<p>0 ETH</p>
</article>
</main>
<footer><p>2026</p></footer>
| тег | что означает |
|---|---|
<header> | шапка страницы или раздела |
<nav> | набор ссылок для перехода |
<main> | основное содержимое; на странице ровно один |
<article> | самостоятельный кусок, который имеет смысл отдельно |
<section> | раздел со своим заголовком |
<footer> | подвал |
<h1>…<h6> | заголовки по уровням, без пропусков |
Программа чтения с экрана строит по этим тегам оглавление и позволяет перейти сразу к основному содержимому. Из сплошных div оглавления не получится: все они для неё одинаковы.
Практический признак: если для элемента есть подходящий смысловой тег — берите его. div и span остаются для случаев, когда элемент нужен только ради оформления и ничего не значит сам по себе.
Формы: браузер проверяет за вас
Форма — это то, через что пользователь вводит данные: сумму вклада, адрес получателя, согласие.
<form>
<label for="a">Сумма</label>
<input id="a" name="amount" type="number" required min="1">
<input name="to" type="text" placeholder="адрес">
<input name="agree" type="checkbox" checked>
<button type="submit">Отправить</button>
</form>
Прогон показывает, что из этого умеет сам браузер:
полей в форме : 4
поле amount : type=number, required=true
подпись через for/id : "Сумма" → amount
проверка до отправки : форма верна? false
после ввода 5 : форма верна? true
что уйдёт на сервер : amount=5&to=&agree=on
Строка amount=5&to=&agree=on — то, как данные формы выглядят при отправке. Пустое поле уходит с пустым значением, галочка — словом on.
Ссылки, картинки и то, что к ним прилагается
<a href="https://etherscan.io/address/0x8464…" target="_blank" rel="noopener noreferrer">
Посмотреть в обозревателе
</a>
<img src="logo.svg" alt="Логотип хранилища" width="120" height="40">
Типичные ошибки
Забыли кодировку. Кириллица превращается в «Ð¥Ñанилище». Строка с кодировкой ставится первой в служебной части.
Забыли строку про ширину экрана. На телефоне страница показывается уменьшенной целиком, буквы нечитаемы. На компьютере при этом всё в порядке — и ошибку не видно.
Поле без имени. Данные не уходят. Никаких сообщений при этом нет.
Кнопка в форме без указания вида. Нажатие перезагружает страницу, и всё, что было введено, теряется.
Блочный элемент внутри абзаца. Дерево получается не тем, что задумано, — молча.
Пропущенный уровень заголовка: после h1 сразу h3. Оглавление для незрячих ломается, хотя на экране разницы нет.
div вместо кнопки. Выглядит как кнопка, но на неё не перейти с клавиатуры и не нажать пробелом. Если это кнопка — пишите кнопку.
Слова главы
- Элемент — тег, его атрибуты и содержимое; элементы вкладываются и образуют дерево.
- Атрибут — имя и значение внутри открывающего тега; бывают и без значения.
- Служебная часть — кодировка, заголовок вкладки, ширина экрана; на странице не видна.
- Кодировка — первой строкой, иначе кириллица ломается.
- Блочный и строчный — занимает всю ширину с новой строки или только место в строке.
- Стили браузера — размеры и отступы, которые есть у тегов до всякого оформления.
- Смысловые теги — шапка, навигация, основное, подвал; по ним страницу понимают программы чтения.
- Форма — поля с именами; браузер проверяет обязательность и ограничения сам.
Тренажёр: набрать вслепую
Цель: скорость ≥ 100 зн/мин, точность ≥ 88%
<!doctype html>
На чемпионате
Скелет набирают наизусть. Пять строк: вид документа, язык, кодировка, ширина экрана, заголовок. Каждая из них, если её забыть, портит результат так, что причину ищут долго.
Смысловые теги — это баллы. Доступность интерфейса проверяют, и разница между div и правильным тегом видна сразу — по оглавлению и по переходу с клавиатуры.
Проверьте на узком экране. Достаточно сузить окно браузера. Строка про ширину экрана и отсутствие горизонтальной прокрутки — две минуты работы и заметная часть впечатления.
Кнопки — кнопками, ссылки — ссылками. Кнопка делает что-то на месте, ссылка ведёт куда-то. Перепутать легко, а с клавиатуры разница становится очевидной.
Куда углубиться
- Таблицы — заголовки строк и столбцов, подписи; понадобятся для списка операций.
- Диалоговые окна — встроенный элемент вместо самодельного всплывающего окна.
- Атрибуты доступности — когда смысловых тегов не хватает.
- Порядок обхода с клавиатуры — что попадает в него само, а что нет.
- Проверка разметки — официальная служба, которая находит именно те расхождения, что не видны глазами.
Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.
Куда дальше: проверенные ресурсы
- MDN: основы HTML — на русском, с примерами.
- MDN: справочник элементов — все теги с описанием.
- MDN: формы — поля, проверка, доступность.
- W3C Markup Validation Service — та самая проверка разметки инструментом.
- HTML Living Standard — правила разбора, по которым браузер достраивает дерево.
Комментарии
Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.