Основой HTML-документа являются теги.
В соответствии с объектной моделью документа («Document Object Model», коротко DOM), каждый HTML-тег является объектом. Вложенные теги являются «детьми» родительского элемента. Текст, который находится внутри тега, также является объектом.
Все эти объекты доступны при помощи JavaScript, мы можем использовать их для изменения страницы.
Например, document.body
– объект для тега <body>
.
Если запустить этот код, то <body>
станет красным на 3 секунды:
document.body.style.background = 'red'; // сделать фон красным
setTimeout(() => document.body.style.background = '', 3000); // вернуть назад
Это был лишь небольшой пример того, что может DOM. Скоро мы изучим много способов работать с DOM, но сначала нужно познакомиться с его структурой.
Пример DOM
Начнём с такого, простого, документа:
<!DOCTYPE HTML>
<html>
<head>
<title>О лосях</title>
</head>
<body>
Правда о лосях.
</body>
</html>
DOM – это представление HTML-документа в виде дерева тегов.
Каждый узел этого дерева – это объект.
Теги являются узлами-элементами (или просто элементами). Они образуют структуру дерева: <html>
– это корневой узел, <head>
и <body>
его дочерние узлы и т.д.
Текст внутри элементов образует текстовые узлы, обозначенные как #text
. Текстовый узел содержит в себе только строку текста. У него не может быть потомков, т.е. он находится всегда на самом нижнем уровне.
Например, в теге <title>
есть текстовый узел "О лосях"
.
Обратите внимание на специальные символы в текстовых узлах:
- перевод строки:
↵
(в JavaScript он обозначается как\n
) - пробел:
␣
Пробелы и переводы строки – это полноправные символы, как буквы и цифры. Они образуют текстовые узлы и становятся частью дерева DOM. Так, в примере выше в теге <head>
есть несколько пробелов перед <title>
, которые образуют текстовый узел #text
(он содержит в себе только перенос строки и несколько пробелов).
Существует всего два исключения из этого правила:
- По историческим причинам пробелы и перевод строки перед тегом
<head>
игнорируются - Если мы записываем что-либо после закрывающего тега
</body>
, браузер автоматически перемещает эту запись в конецbody
, поскольку спецификация HTML требует, чтобы всё содержимое было внутри<body>
. Поэтому после закрывающего тега</body>
не может быть никаких пробелов.
В остальных случаях всё просто – если в документе есть пробелы (или любые другие символы), они становятся текстовыми узлами дерева DOM, и если мы их удалим, то в DOM их тоже не будет.
Здесь пробельных текстовых узлов нет:
<!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях.</body></html>
Пробелы по краям строк и пробельные текстовые узлы скрыты в инструментах разработки
Когда мы работаем с деревом DOM, используя инструменты разработчика в браузере (которые мы рассмотрим позже), пробелы в начале/конце текста и пустые текстовые узлы (переносы строк) между тегами обычно не отображаются.
Таким образом инструменты разработки экономят место на экране.
В дальнейших иллюстрациях DOM мы также будем для краткости пропускать пробельные текстовые узлы там, где они не имеют значения. Обычно они не влияют на то, как отображается документ.
Автоисправление
Если браузер сталкивается с некорректно написанным HTML-кодом, он автоматически корректирует его при построении DOM.
Например, в начале документа всегда должен быть тег <html>
. Даже если его нет в документе – он будет в дереве DOM, браузер его создаст. То же самое касается и тега <body>
.
Например, если HTML-файл состоит из единственного слова "Привет"
, браузер обернёт его в теги <html>
и <body>
, добавит необходимый тег <head>
При генерации DOM браузер самостоятельно обрабатывает ошибки в документе, закрывает теги и так далее.
Есть такой документ с незакрытыми тегами:
<p>Привет
<li>Мама
<li>и
<li>Папа
…Но DOM будет нормальным, потому что браузер сам закроет теги и восстановит отсутствующие детали
Таблицы всегда содержат <tbody>
Важный «особый случай» – работа с таблицами. По стандарту DOM у них должен быть <tbody>
, но в HTML их можно написать (официально) без него. В этом случае браузер добавляет <tbody>
в DOM самостоятельно.
Для такого HTML:
<table id="table"><tr><td>1</td></tr></table>
Видите? Из пустоты появился <tbody>
, как будто документ и был таким. Важно знать об этом, иначе при работе с таблицами возможны сюрпризы.