Список в HTML собирают из двух частей: тег-контейнер и пункты внутри него. Контейнер <ul> даёт маркированный список с точками, <ol> даёт нумерованный, а каждый пункт оборачивают в <li>. Для пар «термин и пояснение» есть третий вид, список определений <dl>.
<ul>
<li>Молоко</li>
<li>Хлеб</li>
</ul>
Названия тегов пришли из английского: ul означает unordered list (неупорядоченный список), ol значит ordered list (упорядоченный), li расшифровывается как list item, то есть пункт списка. Если разметку вы видите впервые, сначала прочитайте, что такое HTML и как устроены теги.
Ниже разбираем все три вида, атрибуты нумерации, вложенные списки, оформление через CSS и ошибки, на которых спотыкаются новички. Код из статьи мы прогнали в Chrome и через валидатор W3C. Разобрать вёрстку с преподавателем можно на курсах из каталога по HTML.
Как сделать список в HTML: пошагово

Порядок одинаковый для любого вида списка.
- Решите, важен ли порядок пунктов. Шаги рецепта и места в рейтинге нумеруют, поэтому берут
<ol>. Состав набора или список преимуществ пишут через<ul>. - Откройте контейнер:
<ul>или<ol>. - Каждый пункт оберните в
<li>и</li>. - Закройте контейнер.
- Маркеры, отступы и цвет настройте в CSS. У CSS вариантов больше, а атрибут
typeу<ul>устарел.
<ol>
<li>Разогрейте духовку до 180 °C.</li>
<li>Смешайте муку с сахаром.</li>
<li>Выпекайте 25 минут.</li>
</ol>
Браузер сам поставит номера 1, 2 и 3, а при удалении пункта перенумерует остальные. Вписывать цифры руками в текст пунктов не нужно.
Какие бывают списки: ul, ol и dl
В HTML три вида списков. Ещё есть тег <menu>: по спецификации HTML это смысловой вариант <ul> для набора команд, например кнопок панели инструментов. Браузер показывает его так же, как <ul>.
| Тег | Вид списка | Когда нужен | Как выглядит без стилей |
|---|---|---|---|
<ul> |
маркированный (ненумерованный) | порядок пунктов не важен: состав, преимущества, пункты меню | чёрные точки слева |
<ol> |
нумерованный | порядок важен: шаги, рейтинг, пункты договора | 1., 2., 3. |
<dl> |
список определений | пары «название и значение»: словарь, характеристики товара | описание сдвинуто вправо на 40 px |
Внутрь <ul> и <ol> кладут только пункты <li>. Абзац, заголовок или картинку размещают уже внутри пункта. Чем пункт списка отличается от обычного абзаца, мы разбирали в статье про тег p в HTML.
Маркированный список ul
Маркированный список подходит для перечислений, где пункты равноправны. Мы открыли страницу без своих стилей в Chrome и замерили, что браузер делает со списком по умолчанию.
- Маркер первого уровня закрашенный кружок (
disc). - Отступ слева 40 px, на этом месте стоит маркер.
- Поля сверху и снизу по 1em, при обычном шрифте это 16 px.
Те же значения записаны в разделе спецификации о стилях по умолчанию. Отступ слева живёт во внутреннем поле, поэтому убирают его через padding. Свойство margin отвечает за поля сверху и снизу.
Эти стандартные значения первым делом обнуляют, когда начинают вёрстку страницы по макету: в макете дизайнера отступы свои, и браузерные им мешают.
В старых учебниках вид маркера задают атрибутом type прямо в теге, например <ul type="square">. Chrome такой квадрат до сих пор рисует, но валидатор W3C выдаёт ошибку: The “type” attribute on the “ul” element is obsolete. Use CSS instead. Атрибут устарел, вид маркера задают в CSS.
Нумерованный список ol и его атрибуты
У <ol> три своих атрибута, у пункта <li> внутри него ещё один. Все четыре описаны в справочнике MDN по тегу ol. В таблице результат, который мы получили в Chrome.
| Атрибут | Что делает | Код | Что покажет браузер |
|---|---|---|---|
type |
вид нумерации: 1, a, A, i, I |
<ol type="a"> |
a. b. c. |
start |
с какого числа начать | <ol type="I" start="4"> |
IV. V. |
reversed |
обратный счёт | <ol reversed> из трёх пунктов |
3. 2. 1. |
value у <li> |
номер конкретного пункта, следующие идут от него | <li value="10"> во втором пункте |
1. 10. 11. |
Атрибуты сочетаются. Список <ol reversed start="10"> из двух пунктов покажет 10 и 9, а start="0" начнёт счёт с нуля.
Когда атрибут, а когда CSS. Атрибут
typeу<ol>не устарел, его оставляют, когда буква или номер важны по смыслу: «см. пункт b». Если номер нужен только для красоты, его вид задают в CSS.
Чаще всего start выручает в пошаговой инструкции для пользователя, которую разорвали картинкой или пояснением. Первый список заканчивается на шаге 3, второй открывают с start="4", и нумерация идёт дальше без ручной правки.
Список определений dl, dt и dd
Список определений собирают из трёх тегов. <dl> служит контейнером, <dt> содержит термин, а <dd> его описание.
<dl>
<dt>Вес</dt>
<dd>1,2 кг</dd>
<dt>Цвет</dt>
<dd>Серый</dd>
<dd>Синий</dd>
</dl>
Одному термину можно дать несколько описаний, как с цветом в примере. Спецификация разрешает и обратное, несколько <dt> подряд перед общим <dd>. Каждую пару ещё можно обернуть в <div>, чтобы удобнее стилизовать строку целиком.
Где пригождается: глоссарий, характеристики товара, блок «вопрос и ответ», реквизиты компании. Без стилей браузер выводит термин обычным шрифтом, а описание сдвигает вправо на 40 px. Жирность термину задают сами.
Карточки товаров с такими таблицами характеристик собирают фронтенд-разработчики интернет-магазинов. Если хочется в эту работу, посмотрите курсы фронтенд-разработки в нашем каталоге.
Вложенные и многоуровневые списки

Вложенный список кладут внутрь пункта <li>, перед его закрывающим тегом. Браузер строит из разметки дерево элементов (как оно устроено, мы рассказывали в статье про DOM-дерево), и подсписок становится частью пункта.
<ul>
<li>Фрукты
<ul>
<li>Яблоки</li>
<li>Груши</li>
</ul>
</li>
<li>Овощи</li>
</ul>
Маркеры на уровнях меняются сами: на первом закрашенный кружок, на втором пустой (circle), с третьего квадрат (square). У вложенного списка нет полей сверху и снизу, поэтому он прилегает к пункту. Нумерованный список внутри другого начинает счёт заново с единицы.
Типы можно смешивать: внутри шага инструкции <ol> бывает нужен <ul> с вариантами. Так же строят меню сайта с подразделами, где каждый пункт ведёт гиперссылкой на свою страницу.
Нумерация вида 1, 1.1, 1.2, как в договоре, отдельного атрибута не имеет. Её собирают CSS-счётчиком, и в Chrome этот код дал «1. A», «1.1. A1», «1.2. A2», «2. B»:
ol { counter-reset: item; list-style: none; }
ol > li { counter-increment: item; }
ol > li::before { content: counters(item, ".") ". "; }
Как оформить список через CSS
Внешний вид списка настраивают четырьмя свойствами. Если CSS для вас новый, начните со статьи что такое CSS и как его подключить.
| Свойство | Что меняет | Пример |
|---|---|---|
list-style-type |
вид маркера или нумерации | square, circle, decimal, lower-roman, none |
list-style-position |
маркер снаружи текста или внутри строки | outside (по умолчанию), inside |
list-style-image |
картинка вместо маркера | url(star.svg) |
list-style |
три свойства одной строкой | list-style: square inside; |
Цвет и размер маркера меняют псевдоэлементом ::marker, например li::marker { color: red; }. Отступы и фон он не принимает: по справке MDN у него только цвет, шрифт, content, анимации и ещё несколько свойств.
Как убрать маркеры и сделать список в строку
Меню сайта почти всегда размечают списком, а точки и отступ снимают:
.menu {
list-style: none;
padding: 0;
margin: 0;
display: flex;
gap: 24px;
}
Свойство display: flex выстраивает пункты в строку, gap задаёт расстояние между ними. Флексбокс и другие способы раскладки подробно разбирают на курсах по CSS.
Нюанс для Safari. Как пишет MDN, после
list-style: noneSafari перестаёт сообщать программе экранного доступа, что перед ней список, если он не лежит внутри<nav>. Разработчики WebKit считают это задуманным поведением. Вернуть смысл помогаетrole="list"на<ul>или<ol>.
Как добавить пункт в список через JavaScript
Список дел, корзина, лента комментариев: пункты в них появляются без перезагрузки страницы. Новый <li> создают скриптом и добавляют в конец списка.
<ul id="todo">
<li>Купить хлеб</li>
</ul>
<script>
const list = document.querySelector('#todo');
const item = document.createElement('li');
item.textContent = 'Купить молоко';
list.append(item);
</script>
После запуска в Chrome в списке стало два пункта, а list.children.length вернул 2. Удалить пункт можно методом remove(): после list.firstElementChild.remove() остаётся только «Купить молоко».
Текст пункта задают через textContent. Он вставит строку как обычный текст, даже если в ней окажутся угловые скобки, и чужой код не попадёт на страницу.
Частые ошибки в разметке списков

Браузер показывает почти все эти ошибки без жалоб, поэтому их легко пропустить. В таблице ответ валидатора W3C на каждую, мы проверили их на тестовом файле.
| Ошибка | Что скажет валидатор | Как исправить |
|---|---|---|
Текст или <p> прямо внутри <ul> |
Element “p” not allowed as child of element “ul” |
обернуть в <li>, абзац положить внутрь пункта |
Вложенный <ul> стоит между пунктами |
Element “ul” not allowed as child of element “ul” |
перенести подсписок внутрь предыдущего <li> |
<li> без контейнера |
Element “li” not allowed as child of element “body” |
добавить <ul> или <ol> |
value="x" у пункта |
Bad value “x” for attribute “value” |
в value только целое число |
<ul type="square"> |
ошибка: атрибут устарел | list-style-type: square в CSS |
Пункт без контейнера Chrome рисует с точкой, как настоящий. Подсписок между пунктами тоже выглядит прилично, с тем же отступом. Поэтому проверять разметку валидатором удобнее, чем глазами.
Ещё одна ошибка не ловится ничем: список, набранный дефисами и тегом <br>. Выглядит похоже, но для поисковика и программ экранного доступа это просто текст, а длинный пункт на узком экране переносится под дефис, без отступа.
А вот незакрытый <li> ошибкой не считается. По спецификации закрывающий тег можно опустить, если дальше идёт новый пункт или список кончается, и браузер закроет пункты сам. В рабочем коде </li> всё же ставят, так разметку проще читать и править.
Где освоить HTML и вёрстку системно
Списки, абзацы и ссылки относятся к самым первым темам курсов вёрстки. За ними идут сетки, адаптивность под телефоны и работа с макетом из Figma. Как выстроить этот путь до первой работы, мы расписали в статье как стать фронтенд-разработчиком, а что делает верстальщик на проекте, разобрали в обзоре профессии HTML-верстальщик.
Если удобнее учиться с наставником и проверкой домашних заданий, вот курсы по HTML из нашего каталога:
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| HTML и CSS с нуля Перейти на сайт курса | 91 626 ₽ | 7635 ₽/мес. | 11 месяцев | Обзор курса | |
| HTML и CSS. Адаптивная вёрстка и автоматизация Перейти на сайт курса | 23 400 ₽ | 3900 ₽/мес. | 2 месяца | Обзор курса | |
| Основы вёрстки HTML и CSS Перейти на сайт курса | 32 676 ₽ | 2723 ₽/мес. | 3 месяца | Обзор курса | |
| HTML и CSS с нуля | 195 160 ₽ | 7972 ₽/мес. | 12 месяцев | Обзор курса | |
| Frontend-разработчик: сайты на HTML/CSS/JavaScript Перейти на сайт курса | 9200 ₽ | - | 3 месяца | Обзор курса |
Больше программ — в полном каталоге курсов по HTML




