Урок 05

Списки, таблицы

Зачем списки

Списки — для перечисления. Три вида:

  • <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.

Дальше — формы и инпуты.