Теги и атрибуты
Теги -- строительные блоки HTML, определяющие элементы страницы. Атрибуты -- дополнительные свойства тегов, уточняющие их поведение.
Зачем нужно
Весь HTML-документ состоит из тегов и атрибутов. Понимание их синтаксиса -- базовый навык. Неправильная вложенность, пропущенный закрывающий тег или ошибка в атрибуте -- и страница рендерится с багами.
Где используется
- Любой HTML-код
- Шаблонизаторы (JSX, Pug, Handlebars, Jinja2)
- HTML-парсеры и линтеры
Предпосылки
Теги
Анатомия тега
открывающий тег содержимое закрывающий тег
| | |
v v v
<tagname attribute="value">Content here</tagname>
^ ^
| |
угловые скобки слеш перед именем
Парные (открывающий + закрывающий)
Большинство тегов парные -- у них есть открывающий и закрывающий тег:
<p>Параграф текста</p>
<h1>Заголовок</h1>
<div>Контейнер</div>
<a href="https://example.com">Ссылка</a>
<ul>
<li>Пункт 1</li>
<li>Пункт 2</li>
</ul>
Пустые (self-closing, void elements)
Некоторые элементы не могут иметь содержимого. У них нет закрывающего тега:
<!-- Void elements -- нет закрывающего тега -->
<br>
<hr>
<img src="photo.jpg" alt="Описание">
<input type="text" name="username">
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<source src="video.mp4" type="video/mp4">
<wbr>
<col>
<area>
<embed>
<track>
Слеш в конце не нужен в HTML5:
<!-- Оба варианта валидны, но слеш не обязателен -->
<br> <!-- Рекомендуемый стиль -->
<br /> <!-- XHTML-стиль, тоже работает -->
<br/> <!-- Тоже работает -->
Полный список void elements: area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr.
Вложенность тегов
Теги вкладываются друг в друга, создавая дерево:
<!-- Правильная вложенность -->
<article>
<h2>Заголовок</h2>
<p>Текст с <strong>жирным</strong> и <em>курсивом</em>.</p>
<ul>
<li>Пункт <a href="#">со ссылкой</a></li>
</ul>
</article>
Правило: теги закрываются в обратном порядке (LIFO -- Last In, First Out):
<!-- ПРАВИЛЬНО: открыт первым -- закрыт последним -->
<p>Текст <strong><em>жирный курсив</em></strong></p>
<!-- НЕПРАВИЛЬНО: вложенность нарушена -->
<p>Текст <strong><em>жирный курсив</strong></em></p>
Необязательные закрывающие теги
HTML-спецификация разрешает опускать закрывающие теги у некоторых элементов:
<!-- Формально валидно, но НЕ рекомендуется -->
<ul>
<li>Пункт 1
<li>Пункт 2
<li>Пункт 3
</ul>
<p>Первый параграф
<p>Второй параграф
<!-- Лучше всегда закрывать -->
<ul>
<li>Пункт 1</li>
<li>Пункт 2</li>
<li>Пункт 3</li>
</ul>
Рекомендация: всегда закрывай парные теги явно. Это предотвращает баги и делает код читаемым.
Атрибуты
Синтаксис атрибутов
<тег атрибут="значение" другой-атрибут="значение">
Атрибуты:
- Пишутся в открывающем теге
- Разделяются пробелами
- Состоят из имени и значения (через
=) - Значение -- в кавычках (двойных или одинарных)
<!-- Двойные кавычки (стандарт) -->
<a href="https://example.com" target="_blank">Ссылка</a>
<!-- Одинарные кавычки (тоже валидно) -->
<a href='https://example.com' target='_blank'>Ссылка</a>
<!-- Без кавычек (валидно если нет пробелов, но не рекомендуется) -->
<div class=container>Текст</div>
<!-- Смешивание при необходимости -->
<div data-info='{"key": "value"}'>Данные</div>
Boolean-атрибуты
Некоторые атрибуты не имеют значения -- их наличие означает true, отсутствие -- false:
<!-- Все три записи эквивалентны -->
<input type="text" disabled>
<input type="text" disabled="">
<input type="text" disabled="disabled">
<!-- Другие boolean-атрибуты -->
<input type="checkbox" checked>
<video autoplay muted>
<details open>
<script defer>
Нельзя задать disabled="false" -- атрибут boolean, его наличие = true. Чтобы "выключить", нужно убрать атрибут:
<!-- ЭТО НЕ РАБОТАЕТ: input всё равно disabled -->
<input type="text" disabled="false">
<!-- Правильно: убери атрибут -->
<input type="text">
Глобальные атрибуты
Атрибуты, которые можно использовать на любом HTML-элементе:
<div
id="unique-id"
class="card card--large"
style="color: red;"
title="Подсказка при наведении"
hidden
data-user-id="42"
tabindex="0"
lang="en"
dir="ltr"
draggable="true"
contenteditable="true"
>
Содержимое
</div>
Подробнее -- в Глобальные атрибуты HTML.
Атрибуты data-*
Пользовательские атрибуты для хранения данных:
<article
data-id="123"
data-category="tech"
data-author-name="Иван"
data-publish-date="2026-04-06"
>
<h2>Заголовок</h2>
</article>
<script>
const article = document.querySelector('article');
// Чтение через dataset (camelCase)
console.log(article.dataset.id); // "123"
console.log(article.dataset.category); // "tech"
console.log(article.dataset.authorName); // "Иван" (data-author-name -> authorName)
console.log(article.dataset.publishDate); // "2026-04-06"
// Запись
article.dataset.status = 'published';
// В DOM: data-status="published"
</script>
Перечислимые (enumerated) атрибуты
Атрибуты с фиксированным набором значений:
<!-- contenteditable: "true" | "false" | "plaintext-only" -->
<div contenteditable="true">Редактируемый текст</div>
<!-- dir: "ltr" | "rtl" | "auto" -->
<p dir="rtl">Текст справа налево</p>
<!-- autocomplete: "on" | "off" -->
<input type="email" autocomplete="off">
<!-- translate: "yes" | "no" -->
<span translate="no">Google Chrome</span>
<!-- inputmode: "none" | "text" | "decimal" | "numeric" | "tel" | "search" | "email" | "url" -->
<input type="text" inputmode="numeric">
ARIA-атрибуты
Атрибуты для доступности (Accessible Rich Internet Applications):
<button aria-label="Закрыть диалог" aria-expanded="false">
<svg><!-- иконка крестика --></svg>
</button>
<div role="alert" aria-live="polite">
Сообщение для screen reader
</div>
Подробнее -- в ARIA атрибуты.
Частые ошибки
| Ошибка | Пример | Как правильно |
|---|---|---|
| Пропущен закрывающий тег | <p>Текст |
<p>Текст</p> |
| Неправильная вложенность | <b><i>текст</b></i> |
<b><i>текст</i></b> |
| Закрывающий тег у void | <br></br> или <img></img> |
<br> и <img> |
disabled="false" |
Элемент всё равно disabled | Убери атрибут disabled |
| Атрибут без кавычек с пробелом | class=my class |
class="my class" |
Дублирование id |
Два элемента с id="main" |
id должен быть уникальным |
data- с заглавными |
data-userName |
data-user-name (lowercase) |
Практика
- Создай HTML с парными тегами (
<p>,<div>,<a>) и void-элементами (<img>,<br>,<input>) - Проверь валидность на validator.w3.org -- намеренно сделай ошибку вложенности и посмотри на сообщение
- Добавь
data-*атрибуты к элементу и прочитай их черезelement.datasetв консоли - Попробуй
disabled="false"на<input>-- убедись, что поле всё равно заблокировано - Создай элемент со всеми глобальными атрибутами:
id,class,style,title,hidden,data-*,tabindex
Связанные темы
- Глобальные атрибуты HTML -- все глобальные атрибуты подробно
- Семантическая разметка -- правильный выбор тегов
- Блочные и строчные элементы -- как теги влияют на layout
- ARIA атрибуты -- атрибуты для доступности