Списки, таблицы
Зачем списки
Списки — для перечисления. Три вида:
<ul>— неупорядоченный.<ol>— упорядоченный.<dl>— список определений.
Правило: любую группу однотипных элементов (меню, фичи, шаги) — через список.
<ul> — маркированный
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
Что даёт: браузер рисует точки.
Не использовать для навигации <div> + <a> — только <ul><li><a>.
<ol> — нумерованный
<ol>
<li>Открыть редактор</li>
<li>Создать файл</li>
<li>Написать код</li>
</ol>
Атрибуты:
<ol start="5"> <!-- начать с 5 -->
<ol reversed> <!-- обратный порядок -->
<ol type="a"> <!-- a, b, c -->
<ol type="I"> <!-- I, II, III -->
Что даёт: гибкая нумерация.
Вложенные списки
<ul>
<li>Frontend
<ul>
<li>HTML</li>
<li>CSS</li>
</ul>
</li>
<li>Backend
<ul>
<li>Laravel</li>
<li>Node.js</li>
</ul>
</li>
</ul>
Правило: вложенный список — внутри <li>, не между <li>.
<dl> — список определений
<dl>
<dt>HTML</dt>
<dd>Язык разметки гипертекста</dd>
<dt>CSS</dt>
<dd>Язык описания внешнего вида</dd>
</dl>
Что даёт: пары «термин — определение».
Когда: глоссарии, FAQ, метаданные.
Стилизация списков
Убрать маркеры:
ul { list-style: none; padding: 0; margin: 0; }
Кастомные маркеры:
ul li::before {
content: "→ ";
color: #c1442e;
}
Что даёт: свои иконки вместо точек.
Навигация — только список
Правильно:
<nav>
<ul>
<li><a href="/">Главная</a></li>
<li><a href="/about">О нас</a></li>
<li><a href="/contact">Контакты</a></li>
</ul>
</nav>
Почему:
- Скринридеры сообщают «список из 3 элементов».
- Стилистически — легко управлять.
- Семантически правильно.
Хлебные крошки
<nav aria-label="breadcrumb">
<ol>
<li><a href="/">Главная</a></li>
<li><a href="/blog">Блог</a></li>
<li aria-current="page">Статья</li>
</ol>
</nav>
Что даёт: путь до текущей страницы.
Правило: <ol> для порядка, <ul> — если порядок не важен.
Таблицы
Основной синтаксис:
<table>
<thead>
<tr>
<th>ID</th>
<th>Название</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>iPhone 15</td>
<td>99990</td>
</tr>
<tr>
<td>2</td>
<td>Galaxy S24</td>
<td>79990</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Итого</td>
<td>179980</td>
</tr>
</tfoot>
</table>
Что здесь:
<thead>— заголовок.<tbody>— тело.<tfoot>— подвал.<tr>— строка.<th>— ячейка заголовка.<td>— обычная ячейка.
Объединение ячеек
По горизонтали (colspan):
<tr>
<td colspan="2">Объединено по горизонтали</td>
</tr>
По вертикали (rowspan):
<tr>
<td rowspan="2">Объединено по вертикали</td>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
Подписи и группировка
Подпись таблицы:
<table>
<caption>Продажи за октябрь</caption>
...
</table>
Группировка колонок:
<table>
<colgroup>
<col>
<col span="2" style="background: #f5f5f5">
</colgroup>
...
</table>
Что даёт: единый стиль для группы колонок.
Атрибуты доступности
<table>
<caption>Продажи</caption>
<thead>
<tr>
<th scope="col">Товар</th>
<th scope="col">Цена</th>
<th scope="col">Количество</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">iPhone</th>
<td>99990</td>
<td>5</td>
</tr>
</tbody>
</table>
Что даёт:
scope="col"— заголовок колонки.scope="row"— заголовок строки.<caption>— название таблицы.
Правило: таблицы данных — с <caption> и scope.
Когда таблица НЕ нужна
Таблица — только для данных. Не для вёрстки.
Плохо:
<table>
<tr><td>Логотип</td><td>Меню</td></tr>
</table>
Решение: flex, grid, семантические теги.
Правило: таблица = табличные данные.
Скролл на мобильных
<div style="overflow-x: auto;">
<table>...</table>
</div>
Что даёт: горизонтальный скролл для широких таблиц.
Правило: не ломать таблицу на мобильных — скролл лучше.
Пример: таблица заказов
<table>
<caption>Заказы за последние 30 дней</caption>
<thead>
<tr>
<th scope="col">№</th>
<th scope="col">Клиент</th>
<th scope="col">Дата</th>
<th scope="col">Сумма</th>
<th scope="col">Статус</th>
</tr>
</thead>
<tbody>
<tr>
<td>1001</td>
<td>Алиса Петрова</td>
<td><time datetime="2026-10-15">15.10.2026</time></td>
<td>99 990 ₽</td>
<td>Оплачен</td>
</tr>
<tr>
<td>1002</td>
<td>Борис Иванов</td>
<td><time datetime="2026-10-14">14.10.2026</time></td>
<td>79 990 ₽</td>
<td>Отправлен</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">Всего</td>
<td>179 980 ₽</td>
<td></td>
</tr>
</tfoot>
</table>
Практика
1. Меню навигации:
<nav>
<ul>
<li><a href="/">Главная</a></li>
<li><a href="/courses">Курсы</a>
<ul>
<li><a href="/courses/laravel">Laravel</a></li>
<li><a href="/courses/react">React</a></li>
</ul>
</li>
<li><a href="/contact">Контакты</a></li>
</ul>
</nav>
2. Хлебные крошки — через <ol>.
3. Таблица с объединёнными ячейками.
4. <dl> для FAQ.
Частые ошибки
1. <li> вне <ul>/<ol>:
<li>Пункт</li>
Решение: всегда внутри списка.
2. Вложенный список между li:
<ul>
<li>Первый</li>
<ul>
<li>Вложенный</li>
</ul>
</ul>
Решение: вложенный внутри <li>.
3. Таблица для вёрстки:
<table><tr><td>Лого</td><td>Меню</td></tr></table>
Решение: flex/grid.
4. Нет <th>:
<tr><td>Имя</td><td>Возраст</td></tr>
Решение: <th scope="col">.
5. Нет <caption>:
Скринридер не понимает, о чём таблица
Решение: всегда <caption> для таблиц данных.
6. <td> без <tr>:
<table><td>Ячейка</td></table>
Решение: ячейки только в строках.
7. <tbody> с несколькими заголовками:
<table>
<thead>...</thead>
<tbody>...</tbody>
<thead>...</thead> <!-- ошибка -->
</table>
Решение: один thead, один tbody (можно несколько tbody, но не thead).
8. Дублирующиеся id в таблице:
Если каждая ячейка имеет id — он должен быть уникален
Решение: data-атрибуты вместо id.
Итог
- Списки:
<ul>,<ol>,<dl>. - Меню — через
<ul>, не div. - Вложенные списки — внутри
<li>. - Таблицы — только для табличных данных.
<thead>,<tbody>,<tfoot>— структура.<th scope>— доступность.<caption>— название таблицы.colspan/rowspan— объединение.- Скролл на мобильных — обёртка
overflow-x: auto.
Дальше — формы и инпуты.