Олег Марков
Тег html в HTML5 - полное практическое руководство
Введение
Тег html — это корневой элемент любого HTML-документа. Без него браузер все равно попытается что‑то отобразить, но уже будет догадываться о структуре, а не опираться на четкие правила. Именно тег html говорит браузеру: «Вот здесь начинается HTML-документ и вот здесь он заканчивается».
Давайте разберем, зачем нужен тег html, какие атрибуты он поддерживает, как правильно его использовать в современном HTML5 и какие типичные ошибки связаны именно с этим элементом.
Роль тега html в структуре документа
Что такое тег html формально
Тег html:
- является корневым (root) элементом документа;
- содержит в себе ровно два основных дочерних элемента первого уровня — head и body;
- определяет, что документ написан на языке HTML (в связке с DOCTYPE).
Минимальная корректная структура HTML-документа выглядит так:
<!DOCTYPE html> <!-- Объявляем тип документа - HTML5 -->
<html> <!-- Корневой элемент документа -->
<head>
<meta charset="UTF-8"> <!-- Кодировка документа -->
<title>Моя первая страница</title> <!-- Заголовок окна/вкладки -->
</head>
<body>
<p>Контент страницы</p> <!-- То, что видит пользователь -->
</body>
</html>Как видите, тег html оборачивает всю разметку. Никаких других тегов на одном уровне с html быть не должно.
Связка DOCTYPE и html
Объявление <!DOCTYPE html> не является тегом, но работает в паре с тегом html:
- DOCTYPE сообщает браузеру, что документ нужно интерпретировать как HTML5;
- тег html задает корень дерева DOM, с которым далее будет работать браузер и JavaScript.
Если DOCTYPE опустить, браузер перейдет в режим «совместимости», где некоторые современные особенности будут работать непредсказуемо, а старые «костыли» — наоборот, оживут. Внешне страница может выглядеть «нормально», но верстка, связанная с CSS и JS, начинает вести себя нестабильно.
Поэтому всегда используйте эту связку:
<!DOCTYPE html>
<html lang="ru">
<!-- дальше head и body -->
</html>Основные атрибуты тега html
Тег html сам по себе встречается в каждом документе, а его реальная «польза» проявляется через атрибуты. Сейчас в HTML5 на практике используются в основном:
- lang — язык основного содержимого страницы;
- manifest (устаревший, но вы могли его встретить в старых статьях);
- глобальные атрибуты (class, id, data-*, style и другие — допускаются, но используются очень осторожно).
Атрибут lang — один из важнейших
Атрибут lang сообщает браузеру и внешним системам (поисковым роботам, скринридерам) язык документа. Это помогает:
- корректно озвучивать текст пользователям с ограничениями по зрению;
- выбирать правильные правила переноса и типографики;
- улучшать SEO за счет правильной языковой разметки.
Пример:
<!DOCTYPE html>
<html lang="ru"> <!-- Язык страницы - русский -->
<head>
<meta charset="UTF-8">
<title>Русскоязычная страница</title>
</head>
<body>
<p>Это текст на русском языке.</p>
</body>
</html>Если у вас страница на английском:
<html lang="en">
<!-- ... -->
</html>Если в документе встречаются фрагменты на другом языке (например, английские цитаты на русской странице), то язык конкретного фрагмента лучше уточнять уже на самих элементах:
<p>Статья о термине <span lang="en">event loop</span> в JavaScript.</p>Здесь я показываю пример, чтобы вам было проще понять: lang на корневом html задает основной язык документа, а lang на внутренних элементах уточняет язык отдельных фрагментов.
Указание регионального варианта языка
Иногда язык дополняют указанием региона:
- ru-RU — русский (Россия);
- en-US — английский (США);
- en-GB — английский (Великобритания);
- fr-FR — французский (Франция).
Формат — язык-регион.
<html lang="ru-RU">
<!-- ... -->
</html>Это может использоваться поисковыми системами и некоторыми сервисами для еще более точной настройки отображения и озвучивания.
Глобальные атрибуты на html
По спецификации HTML5, тег html, как и большинство элементов, может использовать глобальные атрибуты (global attributes): id, class, data-* и другие.
Формально вы можете написать так:
<html id="root" class="theme-dark">
<!-- ... -->
</html>Но на практике так делать не рекомендуется, если вы не решаете очень специфичную задачу (например, совместимость со старым кодом, который полагается на class на теге html). Стили и JS-привязки вполне удобнее организовывать через тег body или конкретные элементы внутри.
А вот атрибут data-* иногда используют для передачи конфигурации «на весь документ». Покажу, как это может выглядеть:
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-app-version="1.2.0">
<head>
<meta charset="UTF-8">
<title>Приложение с темами</title>
</head>
<body>
<p>Содержимое приложения.</p>
<script>
// Здесь мы читаем пользовательскую тему из атрибута на html
const root = document.documentElement; // documentElement - это тег html
const theme = root.dataset.theme; // считываем data-theme
// В зависимости от темы подключаем нужные стили или применяем классы
if (theme === 'dark') {
document.body.classList.add('theme-dark'); // Навешиваем тему на body
}
</script>
</body>
</html>Обратите внимание, как этот фрагмент кода решает задачу: вся информация о теме приложения хранится именно на теге html, а дальше используется скриптом внутри страницы.
Атрибут manifest (устаревший)
Раньше атрибут manifest на теге html использовали для указания кэш-манифеста (Application Cache):
<html manifest="app.appcache">
<!-- ... -->
</html>В современных проектах это использовать не стоит: механизм устарел, а его место заняли сервис-воркеры и PWA-подход. Но если вы разбираете старые материалы, важно понимать, что именно тег html был точкой входа к этому механизму.
Структура документа внутри тега html
Обязательные дочерние элементы: head и body
По спецификации внутри тега html должны быть:
- один head;
- один body.
В таком порядке:
<html lang="ru">
<head>
<!-- Метаданные документа -->
</head>
<body>
<!-- Визуальный контент -->
</body>
</html>Давайте разберемся:
- head содержит информационные элементы: title, meta, link, script (обычно подключение библиотек), style и т. д.;
- body содержит то, что непосредственно видит пользователь: текст, изображения, формы, компоненты интерфейса.
Иногда читатели спрашивают, можно ли опустить head или body и оставить только, скажем, body. Браузер попытается «достроить» дерево DOM за вас, но это считается некорректным HTML и может привести к неожиданным результатам — особенно при работе сложных фреймворков.
Что происходит, если тег html опустить
Технически, если вы не напишете тег html вообще, браузер:
- все равно создаст его в DOM как корневой элемент;
- попытается найти внутри потенциальные head и body;
- может некорректно распознать некоторые части документа (особенно если структура «ломаная»).
Но такой подход оставляет вас без гарантии, что документ во всех браузерах будет интерпретирован одинаково. В современном фронтенде, где важен предсказуемый результат, лучше явно писать html, head и body.
Пример «плохого» кода:
<!DOCTYPE html>
<head>
<title>Без тега html</title>
</head>
<body>
<p>Браузер это отобразит, но структура будет нарушена.</p>
</body>Браузер подставит html сам, но такие эксперименты лучше не использовать в реальной разработке.
Тег html и DOM-дерево
Как получить доступ к тегу html через JavaScript
В JavaScript тег html доступен через свойство document.documentElement. Это корневой элемент DOM-дерева, основанного на HTML-разметке.
Давайте посмотрим, что происходит в следующем примере:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Работа с documentElement</title>
<style>
/* Здесь мы объявляем стили для разных тем */
.theme-dark body {
background-color: #222;
color: #eee;
}
.theme-light body {
background-color: #fff;
color: #222;
}
</style>
</head>
<body>
<p>Переключение темы через класс на html.</p>
<button id="darkBtn">Темная тема</button>
<button id="lightBtn">Светлая тема</button>
<script>
// Получаем корневой элемент документа - тег html
const root = document.documentElement;
// Находим кнопки
const darkBtn = document.getElementById('darkBtn');
const lightBtn = document.getElementById('lightBtn');
// Вешаем обработчики клика
darkBtn.addEventListener('click', () => {
// Устанавливаем класс theme-dark на html
root.classList.add('theme-dark');
root.classList.remove('theme-light');
});
lightBtn.addEventListener('click', () => {
// Устанавливаем класс theme-light на html
root.classList.add('theme-light');
root.classList.remove('theme-dark');
});
</script>
</body>
</html>Смотрите, я показываю вам, как это работает: вместо того чтобы навешивать классы на body, мы навешиваем их на html, и в CSS используем селектор .theme-dark body. Этот подход часто используют для глобальных настроек (темы, направление текста и т. д.).
Связка html и CSS-переменных (custom properties)
Часто корневой тег html используют как место, где объявляются CSS-переменные:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>CSS-переменные на html</title>
<style>
/* Здесь мы объявляем CSS-переменные на корневом элементе */
html {
--main-bg: #ffffff;
--main-color: #222222;
}
body {
background-color: var(--main-bg); /* Подставляем переменную */
color: var(--main-color);
}
</style>
</head>
<body>
<p>Использование CSS-переменных, заданных на html.</p>
</body>
</html>Покажу вам, как это реализовано на практике в более продвинутом варианте с темами:
<!DOCTYPE html>
<html lang="ru" class="theme-light">
<head>
<meta charset="UTF-8">
<title>Темы через CSS-переменные</title>
<style>
/* Базовые переменные для светлой темы */
html.theme-light {
--bg: #ffffff;
--fg: #222222;
}
/* Переопределение переменных для темной темы */
html.theme-dark {
--bg: #222222;
--fg: #ffffff;
}
body {
background-color: var(--bg); /* Берем значение из текущего состояния html */
color: var(--fg);
transition: background-color 0.3s, color 0.3s; /* Плавный переход */
}
</style>
</head>
<body>
<p>Теперь вы увидите, как это выглядит в коде.</p>
<button id="toggle">Переключить тему</button>
<script>
// Получаем корневой элемент - html
const root = document.documentElement;
const button = document.getElementById('toggle');
button.addEventListener('click', () => {
// Проверяем, какая тема сейчас установлена
if (root.classList.contains('theme-light')) {
// Переключаем на темную
root.classList.remove('theme-light');
root.classList.add('theme-dark');
} else {
// Переключаем на светлую
root.classList.remove('theme-dark');
root.classList.add('theme-light');
}
});
</script>
</body>
</html>Как видите, тег html становится «центральной точкой» управления темами, а все остальное подстраивается через CSS.
Особенности тега html в HTML5
Обязателен ли закрывающий тег </html>
Согласно спецификации, закрывающий тег </html> является обязательным. На практике:
- большинство браузеров подставят его автоматически, если вы забыли его написать;
- валидатор HTML укажет на ошибку или предупреждение;
- некоторые инструменты (парсеры, генераторы статических сайтов) могут работать некорректно с незакрытым тегом.
Поэтому в реальной разработке всегда закрывайте тег html явно:
<html lang="ru">
<!-- ... -->
</html>Можно ли вкладывать несколько тегов html
В одном HTML-документе должен быть только один корневой тег html. Вложенные html не допускаются. Если вы вставляете один документ в другой (например, через iframe), внутри фрейма будет свой независимый html, но это уже отдельный документ.
Неправильный пример:
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Неправильная структура</title>
</head>
<body>
<html> <!-- Так делать нельзя -->
<body>Вложенный html внутри body</body>
</html>
</body>
</html>Такой код может быть частично «исправлен» браузером, но он противоречит спецификации и может привести к непредсказуемому DOM-дереву.
Тег html и XML-режим (XHTML)
Раньше часто использовали XHTML — HTML, оформленный как XML. Для него применялись другие правила (обязательные закрывающие теги, строгие атрибуты, прописные/строчные буквы и т. д.). Там тег html мог выглядеть так:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<!-- ... -->
</html>Сейчас в большинстве случаев используется HTML5 в обычном «текстовом» режиме, без XML-синтаксиса. Специальные атрибуты вида xml:lang почти не встречаются. Для современных проектов достаточно:
<html lang="ru">
<!-- ... -->
</html>Здесь я отмечаю это, чтобы вы не пугались более сложных примеров из старых учебников.
Тег html и доступность (a11y)
Влияние lang на доступность
Скринридеры (программы для озвучивания интерфейса) используют атрибут lang на теге html, чтобы выбрать:
- правильную базу произношения;
- подходящий голосовой движок;
- правила чтения чисел, дат, сокращений.
Если язык указан неверно или не указан вообще, русская страница может быть озвучена английским голосом, и наоборот. Это делает сайт хуже для пользователей с нарушением зрения.
Поэтому даже если вы не занимаетесь «формальной» доступностью, просто указывая корректный lang, вы уже сильно улучшаете опыт части пользователей.
Направление текста (dir)
Хотя атрибут dir чаще используют непосредственно на html в документах с письмом справа налево (например, арабский, иврит), стоит хотя бы знать о его существовании. Пример:
<!DOCTYPE html>
<html lang="ar" dir="rtl"> <!-- Текст справа налево -->
<head>
<meta charset="UTF-8">
<title>Страница на арабском</title>
</head>
<body>
<p>Пример текста на языке с направлением справа налево.</p>
</body>
</html>При необходимости вы можете менять направление только для отдельных блоков, но корневой тег html — это «общая настройка».
Типичные ошибки при работе с тегом html
Ошибка 1. Отсутствие lang
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Без lang</title>
</head>
<body>
<p>Русский текст без указания языка.</p>
</body>
</html>Чем это плохо:
- скринридер не знает, как правильно читать текст;
- поисковик не всегда уверенно понимает язык страницы;
- автоматические инструменты могут некорректно обрабатывать страницу.
Как исправить:
<html lang="ru">
<!-- ... -->
</html>Ошибка 2. Вложенный html или элементы до/после html
<!DOCTYPE html>
<!-- Неправильная конструкция перед html -->
<p>Какой-то текст до тега html</p>
<html lang="ru">
<head>
<title>Нарушенная структура</title>
</head>
<body>
<p>Контент страницы.</p>
</body>
</html>Браузеры попытаются это «пересобрать», но DOM может отличаться от ожидаемого. В правильной структуре html должен начинаться сразу после DOCTYPE, и все содержимое документа должно быть внутри html.
Ошибка 3. Неправильный порядок head и body
<!DOCTYPE html>
<html lang="ru">
<body>
<p>Содержимое страницы.</p>
</body>
<head>
<title>Неправильный порядок</title>
</head>
</html>Браузер попытается привести порядок к head → body, но такие конструкции повышают риск странных эффектов (особенно если вы активно работаете со скриптами во время загрузки страницы).
Корректно всегда писать:
<html lang="ru">
<head>
<!-- метаданные -->
</head>
<body>
<!-- контент -->
</body>
</html>Ошибка 4. Несоответствие lang и реального языка
Например:
<html lang="en">
<head>
<title>Страница на русском</title>
</head>
<body>
<p>Весь контент при этом на русском языке.</p>
</body>
</html>С точки зрения браузера и вспомогательных технологий это англоязычная страница, и все алгоритмы обработки будут настроены на английский. Лучше синхронизировать lang с реальным содержимым.
Практические рекомендации по использованию тега html
Базовый «шаблон» для новых страниц
Если вы создаете новую HTML-страницу, удобнее начать с простого шаблона и уже от него двигаться дальше. Давайте разберемся на примере:
<!DOCTYPE html>
<html lang="ru"> <!-- Указывайте язык сразу -->
<head>
<meta charset="UTF-8"> <!-- Правильная кодировка -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- meta viewport важен для адаптивной верстки на мобильных устройствах -->
<title>Название страницы</title>
</head>
<body>
<!-- Содержимое здесь -->
</body>
</html>Здесь тег html используется по всем основным правилам:
- стоит сразу после DOCTYPE;
- содержит атрибут lang;
- включает head и body.
Где логично «цепляться» к html в реальных проектах
Тег html удобно использовать для:
- Настройки языка (lang).
- Управления темами (class, data-theme, CSS-переменные).
- Считывания глобальных настроек (data-* атрибуты) с помощью JavaScript.
- Редких случаев, когда вам нужен глобальный CSS-селектор (например, разные стили для режима печати/просмотра, вкупе с медиа-выражениями).
Но при этом:
- не перегружайте html лишними классами, если можно обойтись body;
- не используйте его как «контейнер для всего», к которому всегда привязывается JavaScript, — для этого лучше подойдут более конкретные элементы или корневые контейнеры приложения.
Использование html в SPA и фреймворках
Если вы работаете с React, Vue, Angular или другими фреймворками, вы обычно не трогаете тег html в каждом компоненте. Вместо этого есть один HTML-шаблон (часто index.html), в котором:
- объявлен DOCTYPE и тег html;
- в head находятся основные метаданные;
- в body — корневой div (например,
<div id="root"></div>), куда фреймворк «монтирует» приложение.
Например:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Одностраничное приложение</title>
</head>
<body>
<div id="app"><!-- Здесь будет рендериться SPA --></div>
<script src="bundle.js"></script> <!-- Подключаем собранный JS -->
</body>
</html>В этом сценарии тег html по-прежнему важен: он задает язык, является document.documentElement, может хранить глобальные настройки темы и т. д. Просто вы работаете с ним через базовый шаблон проекта, а не в каждом компоненте.
Заключение
Тег html — это не просто формальность в начале документа. Он:
- задает корень DOM-дерева;
- определяет базовый язык страницы через атрибут lang;
- служит удобной точкой для хранения глобальных настроек (темы, конфигурация через data-*);
- используется браузерами, поисковиками и вспомогательными технологиями для корректной интерпретации страницы.
В спецификации HTML5 этот тег выглядит простым, но его правильное использование напрямую влияет на доступность, предсказуемость поведения и качество фронтенда в целом. Если вы будете:
- всегда объявлять DOCTYPE;
- использовать тег html один раз на документ;
- задавать корректный lang;
- аккуратно применять глобальные настройки через атрибуты и классы,
структура страниц станет понятной и для браузеров, и для людей, которые будут поддерживать ваш код.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Можно ли задавать разные значения lang на html и на отдельных элементах
Да. Атрибут lang на теге html задает основной язык документа, а на внутренних элементах вы можете переопределять язык для конкретных фрагментов. Браузеры и скринридеры идут от внутреннего к внешнему элементу и ищут ближайший lang. Если вы используете иностранные термины или цитаты, добавляйте lang на соответствующие теги.
Как программно изменить язык документа через JavaScript
Вы можете изменить атрибут lang на корневом элементе, используя document.documentElement. Пример мини-инструкции:
// Здесь мы меняем язык документа на английский
document.documentElement.lang = 'en';После этого скринридеры и некоторые сервисы могут начать воспринимать страницу как англоязычную. Делайте это только осознанно, когда контент действительно меняется.
Можно ли использовать style напрямую на теге html
Да, это допустимо, но обычно не рекомендуется. Гораздо понятнее управлять стилями через CSS. Если очень нужно:
<html lang="ru" style="background-color:#f0f0f0;">
<!-- ... -->
</html>Лучше вынести это в CSS:
html {
background-color: #f0f0f0;
}Так код проще поддерживать и переиспользовать.
Как получить ширину или высоту окна через тег html
Обычно размеры окна получают через window.innerWidth / innerHeight. Но иногда используют размеры document.documentElement:
// Здесь мы получаем ширину области просмотра
const width = document.documentElement.clientWidth;
// И высоту
const height = document.documentElement.clientHeight;clientWidth и clientHeight учитывают размер области без полос прокрутки. Это полезно для адаптивных интерфейсов и расчета макета.
Есть ли разница между html и :root в CSS
В обычном HTML-документе селектор :root и тег html совпадают. Но :root используется именно как «корень дерева» и чаще применяется для объявления CSS-переменных:
:root {
--color-primary: #3366ff;
}Технически вы можете заменить :root на html, но :root считается более «семантичным» для этих целей и лучше отражает намерение использовать корневой контекст стилей.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

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