иконка discount

Скидка 15% по промокоду

кибер понедельник до 01.12иконка discount
CYBER2025
логотип PurpleSchool
логотип PurpleSchool

Элемент списка HTML li - как правильно создавать и оформлять элементы списка

Автор

Олег Марков

Введение

Элемент списка li — один из самых частых «рабочих» тегов в HTML. Вы используете его каждый раз, когда создаете меню, список преимуществ, чек-лист, таблицу содержимого или нумерованный план. Но за кажущейся простотой скрывается много нюансов: семантика, вложенность, управление нумерацией, стилизация, доступность, поведение при использовании с CSS и JavaScript.

Здесь я шаг за шагом покажу вам, как работать с li осознанно: не просто «чтобы работало», а с учетом стандартов, удобства сопровождения и доступности для всех пользователей.

Что такое li и где он используется

Основное назначение элемента li

Элемент li (list item) — это тег, который обозначает отдельный пункт списка. Его ключевая особенность в том, что он:

  • всегда должен находиться внутри контейнерного списка;
  • описывает одну логическую единицу внутри этой группы;
  • по умолчанию не может существовать сам по себе без родительского списка.

Основная семантика элемента li — это «элемент набора схожих элементов». В HTML такими наборами обычно являются:

  • ul — маркированный список (unordered list);
  • ol — нумерованный список (ordered list);
  • menu — меню (редко используется, но формально допустимо в HTML).

Давайте сразу посмотрим на простой пример.

<ul>
  <li>Элемент списка номер один</li>
  <li>Элемент списка номер два</li>
  <li>Элемент списка номер три</li>
</ul>

// ul — контейнер для маркированного списка
// каждый li — отдельный пункт внутри списка

Как видите, li не используется без контейнера. Если попробовать разместить li напрямую в body, валидатор HTML укажет на ошибку структуры документа.

Обязательное окружение для li

По стандарту HTML элемент li допускается внутри следующих элементов:

  • ul — наиболее распространенный случай;
  • ol — используется для упорядоченных списков с нумерацией;
  • menu — логическое меню (в реальных проектах встречается редко и чаще заменяется на ul).

Пример с ol:

<ol>
  <li>Зарегистрироваться на сайте</li>
  <li>Подтвердить электронную почту</li>
  <li>Заполнить профиль</li>
</ol>

// ol — нумерованный список
// браузер автоматически добавляет нумерацию 1 2 3 к элементам li

Если вы случайно завернете li, например, в div без ul или ol, HTML скорее всего «починит» разметку на лету, но итоговая структура может отличаться от ожидаемой. Поэтому лучше следить за правильным контекстом сразу.

Основные типы списков с li

Маркированный список ul + li

Маркированный список используется там, где порядок элементов не важен. Например, список характеристик, список преимуществ, перечень пунктов меню.

<ul>
  <li>Быстрая доставка</li>
  <li>Поддержка 24/7</li>
  <li>Гарантия возврата в течение 30 дней</li>
</ul>

// ul — каждый пункт отмечается маркером (точкой или другим символом)
// порядок элементов здесь не несет смысловой нагрузки

Браузер по умолчанию применяет к li в ul маркер в виде точки, но тип маркера можно легко поменять с помощью CSS. Чуть позже мы посмотрим, как это сделать.

Нумерованный список ol + li

Нумерованный список используют, когда порядок элементов важен: инструкции, шаги, рейтинги, этапы процессов.

<ol>
  <li>Выберите тариф</li>
  <li>Введите данные карты</li>
  <li>Подтвердите оплату</li>
</ol>

// ol — браузер автоматически создает нумерацию
// логический порядок 1 2 3 важен для понимания инструкции

С ol связан еще один важный момент — управление нумерацией с помощью атрибутов start и value. Мы разберем это отдельно.

Список-меню menu + li

Элемент menu используется редко, однако по спецификации он также может содержать элементы li. На практике почти всегда для меню используют ul, так как это более предсказуемо и принято в сообществе разработчиков.

<nav>
  <ul>
    <li><a href="/">Главная</a></li>
    <li><a href="/blog">Блог</a></li>
    <li><a href="/contacts">Контакты</a></li>
  </ul>
</nav>

// в навигации принято использовать ul а не menu
// каждый li — отдельный пункт меню со ссылкой

Структура и содержимое li

Что можно помещать внутрь li

Внутри элемента li можно размещать практически любой контент:

  • текст;
  • ссылки;
  • изображения;
  • другие списки (вложенные списки);
  • блоки div, article, section и похожие элементы;
  • формы или их части.

Вот пример сложного элемента списка. Смотрите, я покажу вам, как это работает.

<ul>
  <li>
    <h3>Тариф Базовый</h3>
    <p>Подходит для личного использования и небольших проектов.</p>
    <ul>
      <li>До 3 проектов</li>
      <li>До 5 пользователей</li>
      <li>Поддержка по email</li>
    </ul>
  </li>
</ul>

// внутри li есть заголовок абзац и вложенный ul
// это один логический пункт — описание конкретного тарифа

Важно помнить: li — блочный элемент по умолчанию. То есть он занимает всю ширину контейнера и располагается друг под другом. Это удобно, когда нужно управлять отступами и оформлением через CSS.

Вложенные списки и уровни структуры

Вложенные списки удобны, когда вам нужно показать иерархию: основной пункт и его подэлементы. Теперь вы увидите, как это выглядит в коде.

<ul>
  <li>Фрукты
    <ul>
      <li>Яблоки</li>
      <li>Груши</li>
      <li>Бананы</li>
    </ul>
  </li>
  <li>Овощи
    <ul>
      <li>Помидоры</li>
      <li>Огурцы</li>
    </ul>
  </li>
</ul>

// вложенный ul внутри li создает подсписок
// так передается иерархия категорий и элементов

Обратите внимание, что вложенный список также должен быть обернут в ul или ol, а не просто набором дополнительных li.

Атрибуты li и управление нумерацией

Атрибут value в li внутри ol

Для нумерованных списков вы можете управлять номером конкретного пункта с помощью атрибута value. Это полезно, когда нужно:

  • продолжить нумерацию после пропуска;
  • начать список не с единицы;
  • создать разорванный список с осознанной нумерацией.

Давайте разберемся на примере.

<ol>
  <li>Первый шаг</li>
  <li>Второй шаг</li>
  <li value="10">Сразу десятый шаг</li>
  <li>Следующий шаг будет одиннадцатым</li>
</ol>

// третий li имеет атрибут value="10"
// нумерация будет 1 2 10 11 — браузер продолжит от установленного значения

Атрибут value работает только внутри нумерованных списков ol. В ul он игнорируется.

Атрибут start у ol и взаимодействие с li

Иногда нужно задать стартовое значение для всего списка. Для этого у ol есть атрибут start. Он задает номер первого элемента списка.

<ol start="5">
  <li>Пятый пункт</li>
  <li>Шестой пункт</li>
  <li>Седьмой пункт</li>
</ol>

// нумерация начинается с 5
// значения для li рассчитываются автоматически — 5 6 7

Если одновременно использовать start у ol и value у конкретного li, приоритет будет у value для этого элемента.

Атрибут type для ol и стиль нумерации

Хотя атрибут type официально считается устаревшим для ol, в практике он все еще встречается. Он влияет на вид нумерации:

  • 1 — стандартные арабские цифры (по умолчанию);
  • A — заглавные латинские буквы;
  • a — строчные латинские буквы;
  • I — римские цифры заглавные;
  • i — римские цифры строчные.

Пример:

<ol type="A">
  <li>Пункт A</li>
  <li>Пункт B</li>
  <li>Пункт C</li>
</ol>

// нумерация будет A B C
// часто используется в юридических документах или сложных списках

На новых проектах лучше управлять внешним видом нумерации через CSS (list-style-type), но понимание type поможет при разборе старого кода.

Стилизация li с помощью CSS

Управление маркерами: list-style-type

Стилизация li почти всегда идет в связке с родительским ul или ol. Один из самых частых сценариев — изменить вид маркера или убрать его.

<ul class="features">
  <li>Легкий старт</li>
  <li>Простое управление</li>
  <li>Гибкие настройки</li>
</ul>
.features {
  list-style-type: square;  /* меняем маркеры на квадраты */
}

// свойство list-style-type применяется к ul
// автоматически меняется отображение маркеров у всех вложенных li

Несколько распространенных значений list-style-type:

  • disc — стандартная закрашенная точка;
  • circle — незакрашенный кружок;
  • square — квадрат;
  • decimal — числа (обычно для ol);
  • none — маркеры отключены.

Пример отключения маркеров:

ul.menu {
  list-style-type: none;   /* убираем стандартные маркеры */
  padding-left: 0;         /* убираем отступ слева */
}

// часто используется для навигационных меню
// дальше можно стилизовать li как горизонтальное меню

Расположение и отступы у li

Браузеры по умолчанию задают отступы для ul и ol. В реальной верстке почти всегда эти отступы настраивают вручную.

ul,
ol {
  margin: 0;         /* сбрасываем внешние отступы */
  padding-left: 1.5rem;  /* задаем контролируемый левый отступ */
}

li {
  margin-bottom: 0.5rem;  /* расстояние между пунктами */
}

// такой подход дает предсказуемые отступы
// удобно для единообразного оформления во всем проекте

Горизонтальное расположение пунктов списка

Очень часто li используют для меню, где пункты нужно выстроить в одну строку. Покажу вам, как это реализовано на практике.

<ul class="nav">
  <li><a href="/">Главная</a></li>
  <li><a href="/services">Услуги</a></li>
  <li><a href="/about">О компании</a></li>
</ul>
.nav {
  list-style: none;       /* убираем маркеры */
  padding-left: 0;        /* убираем отступ слева */
  display: flex;          /* выстраиваем элементы в линию */
  gap: 1.5rem;            /* расстояние между пунктами меню */
}

.nav li {
  /* можно добавить дополнительные стили при необходимости */
}

// flex делает li строчными блоками
// gap удобно задает равномерное расстояние

Раньше для этого часто использовали inline-block или float, но сейчас flex — более простой и предсказуемый вариант.

Пользовательские маркеры с псевдоэлементами

Если стандартные маркеры вас не устраивают, можно отключить их и добавить свои с помощью ::before. Давайте посмотрим, что происходит в следующем примере.

<ul class="checklist">
  <li>Регистрация выполнена</li>
  <li>Профиль заполнен</li>
  <li>Подписка активирована</li>
</ul>
.checklist {
  list-style: none;        /* отключаем стандартный маркер */
  padding-left: 0;
}

.checklist li {
  position: relative;      /* для позиционирования псевдоэлемента */
  padding-left: 24px;      /* место под кастомный маркер */
}

.checklist li::before {
  content: "✔";            /* кастомный символ маркера */
  position: absolute;
  left: 0;
  top: 0;
  color: green;
}

// создаем собственный маркер с помощью псевдоэлемента ::before
// li получает отступ чтобы текст не налезал на маркер

Этот прием часто используют в маркетинговых блоках, списках преимуществ, чек-листах.

Доступность и семантика списков с li

Почему важно использовать li правильно

Экранные читалки и другие ассистивные технологии сильно зависят от семантики. Когда вы используете ul/ol + li, пользователь:

  • слышит, что начался список;
  • получает количество пунктов в списке;
  • может перемещаться по пунктам списка с помощью специальных клавиш.

Если вместо li вы просто выведите текст с иконками, для пользователей с читателями экрана это будет просто набор несвязанных абзацев.

Пример корректной разметки:

<h2>Что входит в тариф</h2>
<ul>
  <li>Неограниченное количество проектов</li>
  <li>Ежедневный бэкап</li>
  <li>Поддержка по телефону и email</li>
</ul>

// здесь у пользователя есть понятное объявление списка
// и ясная структура — заголовок плюс набор элементов

Когда список — действительно список

Иногда разработчики используют ul/li для выравнивания элементов, которые по смыслу не являются списком. Например, иконки соцсетей, оформленные как список, — еще допустимый вариант, так как это все-таки набор однородных элементов.

Но вот сетка карточек товаров как ul + li — спорный с точки зрения семантики вариант. Если вы представляете «набор товаров», а не «список характеристик», чаще уместнее использовать div и более семантические элементы (article, section).

Подход такой: если вы при описании говорите «список чего-то» — используйте ul/ol + li, если «сетка/набор карточек» — думайте, нужна ли здесь именно семантика списка.

Работа с li в JavaScript

Получение списка элементов li

Очень часто вам нужно программно обойти элементы списка: посчитать количество, применить обработчики событий, добавить или убрать пункты. Здесь я размещаю пример, чтобы вам было проще понять.

<ul id="todo">
  <li>Купить продукты</li>
  <li>Оплатить счета</li>
  <li>Позвонить клиенту</li>
</ul>
// Получаем список элементов li внутри списка с id="todo"
const items = document.querySelectorAll("#todo li");

// Выводим текст каждого пункта в консоль
items.forEach((item, index) => {
  console.log(index, item.textContent);
  // index — порядковый номер в NodeList
  // item.textContent — текст содержимого элемента li
});

// querySelectorAll возвращает статический список элементов li
// можно итерироваться по нему с помощью forEach

Динамическое добавление элементов li

Теперь давайте перейдем к следующему шагу — добавим новый элемент списка через JavaScript.

// Находим ul по id
const list = document.getElementById("todo");

// Создаем новый элемент li
const newItem = document.createElement("li");
newItem.textContent = "Запланировать встречу";  // задаем текст

// Добавляем новый li в конец списка
list.appendChild(newItem);

// createElement создает новый DOM-узел li
// appendChild вставляет его в конец списка

При этом браузер автоматически обновит отображение: для ol — нумерацию, для ul — маркеры.

Удаление элемента li

Удалить элемент списка также несложно. Обратите внимание, как этот фрагмент кода решает задачу.

// Удаляем первый элемент списка
const firstItem = list.querySelector("li");  // находим первый li
if (firstItem) {
  list.removeChild(firstItem);              // удаляем его из ul
}

// сначала находим li в DOM
// затем через removeChild удаляем из родителя

В современных браузерах можно использовать и более короткий способ:

firstItem?.remove();  // если элемент существует — удалить его

// оператор ?. предотвращает ошибку если элемента нет

Типичные ошибки при работе с li

Использование li вне списка

Иногда разработчики по ошибке создают li напрямую внутри div или другого контейнера, без ul/ol. Визуально браузер может попытаться «исправить» ситуацию, но:

  • валидность HTML нарушается;
  • поведение может отличаться между браузерами;
  • ассистивные технологии могут некорректно озвучивать структуру.

Правильный вариант: всегда оборачивать элементы li в ul/ol.

Неправильно:

<div>
  <li>Пункт 1</li>
  <li>Пункт 2</li>
</div>

Правильно:

<div>
  <ul>
    <li>Пункт 1</li>
    <li>Пункт 2</li>
  </ul>
</div>

Разрыв списка лишними обертками

Другая распространенная ошибка — размещать блоки, которые нарушают непрерывность списка. Например:

<ol>
  <li>Пункт 1</li>
</ol>
<div>Какой-то блок между</div>
<ol start="2">
  <li>Пункт 2</li>
</ol>

С точки зрения браузера это два разных списка, хотя визуально можно добиться иллюзии одного списка. Если вам нужен один логический список, лучше использовать один ol и управлять оформлением через CSS, а не разрывать структуру.

Лишние отступы и «двойные» маркеры

Иногда пытаются стилизовать li так, что получается «двойной» маркер: стандартный браузерный плюс добавленный псевдоэлемент. Чтобы такого не происходило, при создании кастомных маркеров всегда отключайте стандартные:

.custom-list {
  list-style: none;    /* отключили базовый маркер */
  padding-left: 0;     /* убрали базовый отступ */
}

// это базовый шаг перед созданием своих маркеров через ::before
// иначе браузер добавит и стандартный и ваш собственный маркер

Практические шаблоны использования li

Навигационное меню

Самый частый сценарий — горизонтальное или вертикальное меню. Покажу вам один из базовых шаблонов.

<nav class="main-nav">
  <ul>
    <li><a href="/">Главная</a></li>
    <li><a href="/products">Продукты</a></li>
    <li><a href="/pricing">Цены</a></li>
    <li><a href="/contacts">Контакты</a></li>
  </ul>
</nav>
.main-nav ul {
  list-style: none;        /* без маркеров */
  margin: 0;
  padding-left: 0;
  display: flex;           /* горизонтальное меню */
  gap: 1rem;
}

.main-nav a {
  text-decoration: none;   /* убрали подчеркивание */
  color: #222;
  padding: 0.5rem 1rem;
}

.main-nav a:hover {
  background-color: #f0f0f0;  /* подсветка при наведении */
}

// li служит контейнером для ссылки
// flex делает меню гибким и удобным для адаптивной верстки

Список шагов процесса

Еще один сценарий — пошаговые инструкции. Здесь li удобно комбинировать с CSS-счетчиками, но можно обойтись базовой нумерацией.

<ol class="steps">
  <li>Заполните анкету</li>
  <li>Дождитесь звонка менеджера</li>
  <li>Подпишите договор</li>
  <li>Получите доступ к сервису</li>
</ol>
.steps {
  max-width: 480px;
}

.steps li {
  margin-bottom: 0.75rem;
}

// ol автоматически нумерует шаги
// li обеспечивает читаемую поэтапную структуру

Список свойств или характеристик

Иногда нужно показать пары «название — значение». Здесь можно использовать список для единообразия.

<ul class="product-specs">
  <li><strong>Мощность</strong> 1200 Вт</li>
  <li><strong>Вес</strong> 3.5 кг</li>
  <li><strong>Гарантия</strong> 2 года</li>
</ul>
.product-specs {
  list-style: none;      /* убираем маркеры */
  padding-left: 0;
}

.product-specs li {
  margin-bottom: 0.25rem;
}

// каждый li — одна характеристика
// strong подсвечивает название свойства

Заключение

Элемент li — базовый кирпичик любой структурированной информации в HTML. При правильном использовании он:

  • задает четкую, понятную иерархию данных;
  • улучшает доступность для пользователей с ассистивными технологиями;
  • облегчает стилизацию и управление содержимым через CSS и JavaScript.

Ключевые моменты, на которые стоит опираться в работе:

  • li всегда используется внутри ul, ol или menu;
  • для нумерованных списков вы можете управлять номерами через start у ol и value у li;
  • внешний вид маркеров и отступы лучше настраивать через CSS;
  • для сложных пунктов списка можно использовать любые вложенные элементы, включая другие списки;
  • не забывайте про семантику и доступность — список должен оставаться списком по смыслу, а не только по внешнему виду.

Если вы будете помнить об этих принципах, работа с li станет предсказуемой и удобной, а разметка — понятной как для людей, так и для браузеров и машинных инструментов.

Частозадаваемые технические вопросы

Как убрать маркеры только у вложенного списка li а не у всего списка

Если вам нужно убрать маркеры только у второго уровня списка, а первый оставить, используйте селекторы дочерних ul:

ul ul {
  list-style: none;      /* убираем маркер у вложенных ul */
  padding-left: 1rem;    /* оставляем небольшой отступ для структуры */
}

// селектор ul ul выбирает только списки внутри других ul
// основной список при этом сохраняет маркеры

Как сделать нумерацию продолженной если список разбит на несколько ol

Формально это разные списки, но можно имитировать непрерывную нумерацию через атрибут start:

<ol>
  <li>Пункт 1</li>
  <li>Пункт 2</li>
</ol>

<ol start="3">
  <li>Пункт 3</li>
  <li>Пункт 4</li>
</ol>

// первый список заканчивается на 2
// второй начинается с 3 за счет атрибута start

Как задать индивидуальный номер только некоторым li в середине ol

Используйте атрибут value на нужных пунктах:

<ol>
  <li>Пункт 1</li>
  <li>Пункт 2</li>
  <li value="10">Пункт 10</li>
  <li>Пункт 11</li>
</ol>

// третий li получает номер 10
// четвертый автоматически становится 11 без дополнительных настроек

Как сделать разные маркеры для разных уровней вложенности списка

Настройте list-style-type для разных уровней через селекторы:

ul {
  list-style-type: disc;    /* первый уровень — точки */
}

ul ul {
  list-style-type: circle;  /* второй уровень — кружки */
}

ul ul ul {
  list-style-type: square;  /* третий уровень — квадраты */
}

// каждый уровень вложенности получает свой тип маркера
// так визуально подчеркивается иерархия

Как превратить li в кликабельную область целиком а не только текст ссылки

Оборачивайте содержимое li в a и делайте ссылку блочным элементом:

<ul class="cards">
  <li>
    <a href="/product/1">
      <h3>Товар 1</h3>
      <p>Краткое описание</p>
    </a>
  </li>
</ul>
.cards a {
  display: block;       /* ссылка занимает всю площадь li */
  padding: 1rem;
}

// теперь клик по любой точке внутри li сработает как клик по ссылке
// это улучшает удобство использования на мобильных устройствах

Стрелочка влевоНумерованный список HTML olТермин определения HTML dtСтрелочка вправо

Постройте личный план изучения Html до уровня Middle — бесплатно!

Html — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Все гайды по Html

Тег section в HTML - семантическая разметка структуры страницыТег nav в HTML - полное руководство по семантической навигацииТег header в HTML - полное практическое руководствоТег main в HTML - подробное руководство по использованиюТег footer в HTML - назначение семантика и практические примерыТег figure в HTML - как правильно оформлять иллюстрации и подписиТег figcaption в HTML - подробное руководство с примерамиТег aside в HTML - назначение правильная семантика и примеры
Текстовая область HTML textarea - практическое руководствоВыпадающий список HTML select - полное руководство для разработчиковОпция списка HTML option - как работает и как правильно использоватьАтрибут method в HTML - как правильно отправлять данные формыЗаголовок группы HTML legend - как правильно использовать и оформлятьТег input в HTML - типы атрибуты валидация и примерыТег формы form в HTMLГруппа полей HTML fieldsetАтрибут action в HTML - как правильно задавать адрес отправки формы
Открыть базу знаний

Лучшие курсы по теме

изображение курса

HTML и CSS

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий