Олег Марков
Маркированный список HTML ul - основы синтаксиса стилизация и лучшие практики
Введение
Маркированный список в HTML создается с помощью тега <ul> и используется для отображения неупорядоченных наборов элементов. Это могут быть пункты меню, списки преимуществ, чек-листы, группы ссылок и многое другое.
Смотрите, я покажу вам, как это выглядит в самом простом виде:
<ul>
<li>Первый пункт</li>
<li>Второй пункт</li>
<li>Третий пункт</li>
</ul>Маркированные списки кажутся простой темой, но в реальной верстке вокруг них возникает много вопросов: как правильно вкладывать списки, как менять вид маркеров, как использовать <ul> для меню, как не ломать семантику и доступность сайта. В этой статье вы разберетесь с основами и увидите практические примеры применения <ul> в реальных интерфейсах.
Синтаксис и базовая структура <ul>
Минимальная разметка
Маркированный список всегда состоит из контейнера <ul> и элементов списка <li>. Без <li> тег <ul> не имеет смысла.
<ul>
<li>HTML</li> <!-- Элемент списка -->
<li>CSS</li>
<li>JavaScript</li>
</ul>Ключевые моменты:
<ul>— контейнер списка.<li>— отдельный пункт списка.- Каждый пункт списка должен быть внутри
<ul>(или<ol>). - Внутри
<li>могут находиться другие элементы: текст, ссылки, изображения, вложенные списки и т.д.
Когда использовать <ul>
Используйте маркированный список, когда:
- порядок пунктов неважен;
- элементы можно переставить местами без потери смысла;
- вы перечисляете свойства, характеристики, опции, пункты меню.
Не стоит использовать <ul> только ради отступов или декоративных точек, когда список по смыслу не нужен. В таких случаях лучше применить обычные блоки и CSS.
Семантика и роль <ul> в структуре документа
Семантический смысл <ul>
Тег <ul> сообщает браузеру и вспомогательным технологиям (например, скринридерам), что перед ними список однородных элементов. Это важно:
- для доступности (озвучивание количества пунктов, навигация по спискам),
- для SEO и анализа структуры контента,
- для удобства поддержки кода.
По умолчанию:
<ul>имеет роль списка;<li>— роль элемента списка.
Если вы используете <ul> для навигации, часто его оборачивают в <nav>:
<nav>
<ul>
<li><a href="/">Главная</a></li>
<li><a href="/blog">Блог</a></li>
<li><a href="/contacts">Контакты</a></li>
</ul>
</nav>Так вы явно показываете браузеру и поисковым системам, что этот список — часть навигации.
Разница между <ul>, <ol> и <dl>
Чтобы понимать, когда именно нужен <ul>, сравним его с другими типами списков:
<ul>— неупорядоченный список, маркеры без номера, порядок не важен.<ol>— нумерованный список, важен порядок пунктов (инструкции, шаги алгоритма).<dl>— список описаний, используется для пар «термин — определение».
Если вы описываете шаги установки программы — лучше <ol>. Если просто перечисляете функции программы — <ul>.
Вложенные списки и иерархические структуры
Очень часто требуется показать структуру с подуровнями: категории и подкатегории, пункты меню второго уровня и т.д. Здесь помогают вложенные <ul>.
Простой пример вложенного списка
Давайте разберемся на примере многоуровневого меню:
<ul>
<li>Фрукты
<ul> <!-- Вложенный список -->
<li>Яблоки</li>
<li>Бананы</li>
<li>Апельсины</li>
</ul>
</li>
<li>Овощи
<ul>
<li>Морковь</li>
<li>Огурцы</li>
</ul>
</li>
<li>Ягоды</li>
</ul>Обратите внимание:
- Вложенный
<ul>располагается внутри<li>родительского списка. - Нельзя вкладывать
<ul>напрямую в<ul>без<li>между ними. - Каждый уровень списка можно стилизовать по‑разному с помощью CSS.
Управление отступами и маркерами у вложенных списков
Чаще всего разработчикам нужно настроить внешний вид вложенных уровней: уменьшить отступы, сменить маркеры и т.д.
<ul class="categories">
<li>Фрукты
<ul>
<li>Яблоки</li>
<li>Бананы</li>
</ul>
</li>
<li>Овощи
<ul>
<li>Морковь</li>
<li>Огурцы</li>
</ul>
</li>
</ul>/* Стили для корневого списка */
.categories {
list-style-type: disc; /* Классические кружки */
padding-left: 20px; /* Отступ слева */
}
/* Стили для вложенных списков */
.categories ul {
list-style-type: circle; /* Маркер-колечко для второго уровня */
padding-left: 20px;
}Здесь я размещаю пример, чтобы вам было проще понять, как можно выделить разные уровни иерархии с помощью разных маркеров.
Атрибут type и свойство list-style-type
Атрибут type у <ul>
Исторически <ul> поддерживает атрибут type, который задает тип маркера. Однако в HTML5 его использование считается устаревшим. Лучше управлять маркерами через CSS.
Пример устаревшего подхода (так лучше не делать в новом коде):
<ul type="square">
<li>Пункт 1</li>
<li>Пункт 2</li>
</ul>Сейчас предпочтительнее использовать CSS.
Свойство CSS list-style-type
Современный способ задать стиль маркера — CSS:
<ul class="features">
<li>Высокая производительность</li>
<li>Удобный интерфейс</li>
<li>Гибкая настройка</li>
</ul>.features {
list-style-type: disc; /* Возможные значения disc circle square none и др. */
}Наиболее часто используемые значения:
disc— закрашенный кружок (по умолчанию),circle— пустой кружок,square— квадрат,none— без маркеров.
Если вы хотите полностью убрать маркеры (например, для горизонтального меню), используйте:
.menu {
list-style-type: none; /* Убираем стандартные маркеры */
margin: 0; /* Часто обнуляют еще и отступы */
padding: 0;
}Сброс стандартных стилей и работа с отступами
Почему важно обнулять отступы
Каждый браузер по‑своему задает отступы для <ul>. Это может ломать дизайн, особенно в шапках и футерах. Поэтому в макетах часто обнуляют margin и padding у списков, а затем задают нужные отступы явно.
<ul class="menu">
<li><a href="/">Главная</a></li>
<li><a href="/services">Услуги</a></li>
<li><a href="/about">О компании</a></li>
</ul>.menu {
list-style: none; /* Сокращенная запись - убираем маркеры */
margin: 0; /* Обнуляем внешний отступ */
padding: 0; /* Обнуляем внутренний отступ */
}Смотрите, я покажу вам, как можно добавить свои отступы уже к элементам списка:
.menu li {
display: inline-block; /* Делаем пункты горизонтальными */
margin-right: 16px; /* Задаем промежуток между пунктами */
}Свойство list-style как сокращенная запись
Вместо list-style-type, list-style-position и list-style-image можно использовать одно свойство:
ul.custom {
list-style: square inside;
/* square - тип маркера
inside - положение маркера внутри блока li */
}Здесь мы задаем сразу несколько параметров в одной строке.
Кастомные маркеры: иконки, изображения, псевдоэлементы
Стандартных кружков и квадратиков часто недостаточно. В современных интерфейсах вы часто увидите свои иконки вместо стандартных маркеров.
Использование list-style-image
Самый прямой способ — указать изображение как маркер:
<ul class="with-icon">
<li>Пункт с картинкой</li>
<li>Еще один пункт</li>
</ul>.with-icon {
list-style-image: url("bullet.png");
/* Используем изображение как маркер */
}Но у этого подхода есть ограничения: сложно контролировать размер и отступы маркера.
Кастомные маркеры через псевдоэлемент ::before
Более гибкий и популярный подход — полностью убрать стандартный маркер и нарисовать свой через ::before.
<ul class="checklist">
<li>Проверено</li>
<li>Подтверждено</li>
<li>Завершено</li>
</ul>.checklist {
list-style: none; /* Убираем стандартные маркеры */
margin: 0;
padding: 0;
}
.checklist li {
position: relative; /* Чтобы псевдоэлемент позиционировать относительно li */
padding-left: 24px; /* Оставляем место под кастомный маркер */
}
.checklist li::before {
content: "✔"; /* Сам маркер - символ галочки */
position: absolute;
left: 0;
top: 0;
color: green;
/* Можно добавить line-height и другие параметры
чтобы выровнять значок по вертикали */
}Теперь вы увидите, как это выглядит в коде: стандартные маркеры пропали, вместо них выводится зеленая галочка слева от текста.
Преимущества этого метода:
- легко менять иконку (можно использовать символ, SVG, фон),
- гибкий контроль отступов,
- удобно подстраивать под дизайн.
Пример с иконкой через фон
Еще один вариант — использовать фоновое изображение:
.list-icon {
list-style: none;
margin: 0;
padding: 0;
}
.list-icon li {
background: url("icon.svg") no-repeat 0 4px;
/* Располагаем иконку слева и немного смещаем вниз */
padding-left: 24px; /* Делаем отступ под иконку */
}В этом случае маркер — часть фона элемента списка.
Горизонтальные списки и меню на <ul>
Горизонтальное меню
Одно из самых частых применений <ul> — создание навигационного меню. Давайте посмотрим, что происходит в следующем примере.
<nav>
<ul class="main-menu">
<li><a href="/">Главная</a></li>
<li><a href="/catalog">Каталог</a></li>
<li><a href="/prices">Цены</a></li>
<li><a href="/contacts">Контакты</a></li>
</ul>
</nav>.main-menu {
list-style: none; /* Убираем маркеры */
margin: 0;
padding: 0;
display: flex; /* Выстраиваем элементы в строку */
gap: 20px; /* Расстояние между пунктами меню */
}
.main-menu a {
text-decoration: none; /* Убираем подчеркивание ссылок */
color: #333;
padding: 8px 12px; /* Внутренние отступы для кликабельной зоны */
}
.main-menu a:hover {
background-color: #f0f0f0; /* Подсветка при наведении */
}Здесь <ul> выступает структурным контейнером, а CSS задает нужный вид.
Списки-кнопки и панели управления
Точно так же можно строить панели с кнопками, вкладки и другие интерфейсные элементы.
<ul class="tabs">
<li class="active"><button type="button">Профиль</button></li>
<li><button type="button">Настройки</button></li>
<li><button type="button">Безопасность</button></li>
</ul>.tabs {
list-style: none;
margin: 0;
padding: 0;
display: flex;
border-bottom: 1px solid #ccc;
}
.tabs li {
margin-right: 12px;
}
.tabs button {
border: none;
background: transparent;
padding: 8px 16px;
cursor: pointer;
}
.tabs .active button {
border-bottom: 2px solid #007bff; /* Активная вкладка */
font-weight: 600;
}Покажу вам, как это реализовано на практике: сам список задает структуру, а визуальное оформление и «кнопочность» целиком в руках CSS и JavaScript.
<ul> и доступность (a11y)
Как списки помогают скринридерам
Семантически корректные списки упрощают навигацию для пользователей со скринридерами. Когда вы используете <ul> и <li>:
- скринридер может сообщить «список из N элементов»;
- пользователь может быстро перемещаться между элементами списка;
- структура контента становится предсказуемой.
Важно:
- не вставлять посторонние элементы между
<ul>и<li>, которые ломают структуру; - не использовать
<br>вместо корректных<li>.
Текст ссылок в списках навигации
Если у вас <ul> в навигации, следите, чтобы текст ссылок был понятным вне контекста. Например, вместо:
<ul>
<li><a href="/more">Подробнее</a></li>
<li><a href="/click">Кликните сюда</a></li>
</ul>лучше так:
<ul>
<li><a href="/pricing">Тарифы</a></li>
<li><a href="/documentation">Документация</a></li>
</ul>Так пользователю (и скринридеру) будет понятно, куда ведет каждая ссылка.
Использование ARIA свойств
В большинстве случаев <ul> с <li> достаточно без дополнительных атрибутов ARIA. Но, если вы делаете сложные компоненты (например, выпадающее меню), могут понадобиться роли и атрибуты вроде role="menu", role="menuitem", aria-expanded и т.д.
Важно: добавлять ARIA стоит только тогда, когда вы понимаете, как это повлияет на поведение скринридеров. Для обычных списков с текстом или ссылками в большинстве случаев достаточно стандартной семантики <ul>.
Частые ошибки при работе с <ul>
Неправильное вложение элементов
Одна из типичных ошибок — вставка других элементов вместо <li> напрямую в <ul>.
<ul>
<p>Текст внутри ul</p> <!-- Так делать не нужно -->
<li>Правильный пункт</li>
</ul>Корректный вариант:
<ul>
<li>Текст внутри списка</li> <!-- Текст должен быть внутри li -->
<li>Еще один пункт</li>
</ul>Если вам нужен заголовок над списком, разместите его до <ul>, а не внутри.
<h3>Основные преимущества</h3>
<ul>
<li>Надежность</li>
<li>Простота использования</li>
<li>Гибкая настройка</li>
</ul>Использование списка только ради отступов
Иногда новички используют <ul> как способ создать отступы или выровнять элементы:
<!-- Неправильный подход -->
<ul>
<li>Блок 1</li>
<li>Блок 2</li>
</ul>Если по смыслу это просто два независимых блока, а не элементы списка, лучше использовать <div> или другие подходящие теги и управлять внешним видом через CSS.
Непоследовательная структура списков
Старайтесь, чтобы структура всех элементов списка была похожей. Плохой пример:
<ul>
<li>
<h4>Заголовок</h4>
<p>Описание пункта</p>
</li>
<li>Просто текст без заголовка</li>
</ul>Лучше выровнять структуру:
<ul>
<li>
<h4>Заголовок 1</h4>
<p>Описание пункта</p>
</li>
<li>
<h4>Заголовок 2</h4>
<p>Еще одно описание</p>
</li>
</ul>Так код становится более предсказуемым и удобным для стилизации.
<ul> внутри других элементов: карточки, статьи, списки в списках
Список характеристик в карточке товара
Очень распространенный сценарий — использовать <ul> для характеристик товара.
<article class="product">
<h2>Ноутбук X100</h2>
<p>Мощный ноутбук для работы и игр.</p>
<h3>Характеристики</h3>
<ul class="product-specs">
<li>Процессор Intel Core i7</li>
<li>16 ГБ оперативной памяти</li>
<li>SSD 512 ГБ</li>
</ul>
</article>.product-specs {
list-style: disc inside; /* Маркеры внутри строки текста */
}Здесь <ul> помогает структурировать данные и делает их легко воспринимаемыми.
Список внутри пункта списка
Иногда внутри одного <li> вам нужно сделать еще один список. Например, план занятий:
<ul>
<li>Понедельник
<ul>
<li>Математика</li>
<li>Физика</li>
</ul>
</li>
<li>Вторник
<ul>
<li>История</li>
<li>Литература</li>
</ul>
</li>
</ul>Обратите внимание, как этот фрагмент кода решает задачу структурирования: каждый день — отдельный пункт, а внутри него — список уроков.
Управление позиционированием маркера
Свойство list-style-position
С помощью list-style-position можно управлять тем, где именно рисуется маркер — внутри или снаружи блока <li>.
ul.inside {
list-style-position: inside; /* Маркер будет внутри области li */
}
ul.outside {
list-style-position: outside; /* Маркер снаружи области li (значение по умолчанию) */
}Посмотрим на пример:
<ul class="inside">
<li>Длинный текст пункта списка, который переносится на несколько строк и выравнивается по маркеру.</li>
</ul>
<ul class="outside">
<li>Тот же длинный текст, но маркер расположен иначе, и выравнивание строк будет другим.</li>
</ul>- При
insideпереносы строк начинаются под маркером. - При
outsideпереносы идут под началом текста, а маркер остается слева в полях.
Это особенно важно, если вы заботитесь о читаемости длинных пунктов.
Стилизованные списки в макетах (UI‑паттерны)
Список шагов или этапов
Даже если порядок не критичен, часто хочется визуально показать шаги или этапы процесса с помощью <ul>.
<ul class="steps">
<li>
<h4>Шаг 1</h4>
<p>Заполните форму регистрации.</p>
</li>
<li>
<h4>Шаг 2</h4>
<p>Подтвердите email.</p>
</li>
<li>
<h4>Шаг 3</h4>
<p>Начните работу с личным кабинетом.</p>
</li>
</ul>.steps {
list-style: none;
margin: 0;
padding: 0;
}
.steps li {
margin-bottom: 16px;
padding-left: 12px;
border-left: 2px solid #007bff; /* Вертикальная линия слева */
}Здесь мы используем <ul> как структурный контейнер, но полностью переопределяем его внешний вид.
Колонки с помощью flex или grid
Списки можно «разложить» по колонкам:
<ul class="columns">
<li>Пункт 1</li>
<li>Пункт 2</li>
<li>Пункт 3</li>
<li>Пункт 4</li>
<li>Пункт 5</li>
<li>Пункт 6</li>
</ul>.columns {
list-style: disc inside;
columns: 2; /* Две колонки */
-webkit-columns: 2; /* Поддержка старых браузеров WebKit */
-moz-columns: 2; /* Поддержка старых Firefox */
}Или через flex:
.columns {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap; /* Разрешаем перенос элементов на новую строку */
gap: 8px 24px; /* Вертикальные и горизонтальные отступы */
}
.columns li {
width: 45%; /* Укладываем примерно по два элемента в строке */
}Так <ul> помогает создавать адаптивные сетки.
Заключение
Маркированный список <ul> — один из базовых, но очень гибких инструментов HTML. Он отвечает не только за визуальные маркеры, но и за семантику, структуру и доступность контента. Через <ul> вы можете:
- строить списки характеристик и преимуществ,
- организовывать навигацию и меню,
- создавать многоуровневые структуры и подменю,
- стилизовать пункты под чек‑листы, шаги, вкладки и другие паттерны интерфейса.
Ключевые практики, которые стоит учитывать:
- хранить всю структуру списка внутри
<li>; - использовать CSS (
list-style-*, псевдоэлементы) для управления видом маркеров; - обнулять стандартные отступы там, где важен точный контроль дизайна;
- помнить о семантике и доступности при использовании
<ul>для навигации и сложных интерфейсов.
Если вы будете сочетать корректную семантику с аккуратной стилизацией, <ul> станет надежной основой для чистой и поддерживаемой верстки.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Можно ли оборачивать <li> в <a>, а не наоборот в меню на основе <ul>?
Да, HTML5 допускает оборачивание <li> в <a>, но более распространенный и предсказуемый вариант — <a> внутри <li>. Если вы хотите кликабельной сделать всю область пункта, лучше стилизовать ссылку как блочный элемент:
<ul class="menu">
<li><a href="/catalog">Каталог</a></li>
</ul>.menu a {
display: block; /* Делает ссылку блочной и растягивает на всю li */
padding: 10px 16px;
}Как сделать разные маркеры для разных пунктов внутри одного <ul>?
У стандартного list-style-type нет возможности задавать разные маркеры для отдельных <li>, поэтому используйте псевдоэлементы:
ul li {
list-style: none; /* Убираем стандартный маркер */
position: relative;
padding-left: 20px;
}
ul li::before {
content: "•"; /* Общий маркер по умолчанию */
position: absolute;
left: 0;
}
/* Для конкретного пункта */
ul li.important::before {
content: "❗"; /* Особый маркер */
color: red;
}Как перенести длинный текст в <li>, чтобы маркер оставался выровненным?
Используйте list-style-position: outside (по умолчанию) и при необходимости управляйте отступами:
ul {
list-style-position: outside; /* Маркер вне блока li */
padding-left: 20px; /* Общий отступ списка */
}
li {
padding-left: 4px; /* Небольшой дополнительный отступ текста */
}Если вы используете кастомный маркер через ::before, выравнивание задается через padding-left и position: absolute.
Как задать номера внутри <ul> вместо кружков, не используя <ol>?
Семантически это спорно (если есть номера, логичнее <ol>), но технически возможно:
.numbered {
list-style: none;
counter-reset: item; /* Обнуляем счетчик */
}
.numbered li {
counter-increment: item; /* Увеличиваем счетчик на каждом li */
position: relative;
padding-left: 24px;
}
.numbered li::before {
content: counter(item) ". "; /* Выводим номер */
position: absolute;
left: 0;
}Как сделать адаптивное меню на <ul>, которое превращается в столбик на мобильных устройствах?
Сначала строите меню в строку, затем меняете направление при узком экране:
.nav {
list-style: none;
margin: 0;
padding: 0;
display: flex; /* Горизонтальное меню по умолчанию */
gap: 16px;
}
/* На мобильных экранах */
@media (max-width: 600px) {
.nav {
flex-direction: column; /* Переводим элементы в столбик */
gap: 8px;
}
}Структура HTML при этом не меняется — адаптивность полностью обеспечивается за счет CSS.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев