Теги и атрибуты

Теги -- строительные блоки 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>
<input required>
<input readonly>
<option selected>Выбрано</option>
<button type="submit" formnovalidate>Отправить</button>

Нельзя задать 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)

Практика

  1. Создай HTML с парными тегами (<p>, <div>, <a>) и void-элементами (<img>, <br>, <input>)
  2. Проверь валидность на validator.w3.org -- намеренно сделай ошибку вложенности и посмотри на сообщение
  3. Добавь data-* атрибуты к элементу и прочитай их через element.dataset в консоли
  4. Попробуй disabled="false" на <input> -- убедись, что поле всё равно заблокировано
  5. Создай элемент со всеми глобальными атрибутами: id, class, style, title, hidden, data-*, tabindex

Связанные темы

Ресурсы