DOM и CSSOM в браузере: что это и как работает

Что такое DOM в браузере? Что такое CSSOM?

Теория: DOM и CSSOM

DOM (Document Object Model) — это представление HTML-документа в памяти браузера в виде объектов и дерева узлов (элементы, текстовые узлы, комментарии и т.д.), с которым можно работать через API (обычно через JavaScript). CSSOM (CSS Object Model) — это модель, представляющая CSS как объекты: таблицы стилей, правила, селекторы и значения свойств, доступные для чтения и изменения программно.

Ключевая идея

  • DOM отвечает на вопрос «какая структура документа существует: какие узлы, где они находятся в дереве, какие у них атрибуты и текст».
  • CSSOM отвечает на вопрос «какие CSS-правила существуют и какие итоговые значения стилей получаются после применения каскада, наследования и специфичности».

Таблица: чем DOM отличается от CSSOM

ХарактеристикаDOMCSSOM
Что моделируетсяСтруктура документа и его содержимое.Таблицы стилей и правила CSS (в виде объектов).
Откуда строитсяИз HTML-разметки при ее разборе браузером.Из CSS (внешних/встроенных/инлайновых стилей) при разборе браузером.
Основное назначениеДоступ к узлам: поиск, обход дерева, изменение текста, атрибутов, добавление/удаление элементов.Доступ к стилям: чтение/изменение правил, анализ правил, вставка/удаление правил, получение вычисленных стилей.
Связь с отрисовкойОпределяет, «что» потенциально может быть отображено.Определяет, «как» это должно выглядеть после вычисления стилей.
DOM и CSSOM — это модели данных и API (структуры в памяти браузера), а не «ресурсы» вроде картинок и шрифтов и не «слои GPU».

Как строится рендеринг

В упрощенном виде браузер сначала разбирает HTML и строит DOM-дерево, затем разбирает CSS и строит CSSOM-дерево. Далее DOM и CSSOM используются совместно для построения render tree, после чего выполняются этапы layout (расчет размеров/координат) и paint (отрисовка).

Схема (упрощенно)

HTML bytes
  ↓ parse
DOM tree
          CSS bytes
            ↓ parse
          CSSOM tree
              ↓ combine
          Render tree
              ↓ layout
        Boxes geometry
              ↓ paint
           Pixels

Практический смысл этой цепочки

  • DOM без CSSOM не дает информации о том, как именно отображать элементы (например, display, visibility, размеры, шрифты).
  • CSSOM без DOM не понимает, к каким узлам применять селекторы и для каких узлов вычислять итоговые стили.
До получения достаточной информации о стилях невозможно корректно построить render tree и перейти к layout/paint, поэтому подключение CSS влияет на скорость первого отображения страницы.

Как читать и менять DOM/CSSOM

DOM обычно читается и изменяется через document и связанные интерфейсы (поиск узлов, изменение текста и атрибутов, вставка/удаление элементов). CSSOM доступен через document.styleSheets и интерфейсы таблиц стилей/правил (например, добавление правил), а также через получение вычисленных стилей конкретного элемента.

Пример: чтение/изменение DOM

<!-- index.html -->
<button id="inc">Увеличить</button>
<p id="value">0</p>

<script>
  const btn = document.getElementById('inc');
  const out = document.getElementById('value');

  btn.addEventListener('click', () => {
    out.textContent = String(Number(out.textContent) + 1);
  });
</script>

Что демонстрируется

  • Узлы (кнопка и абзац) существуют как объекты, а изменение textContent меняет текст в соответствующем узле DOM.

Пример: работа с CSSOM через таблицу стилей

<style id="dyn">
  .box { width: 120px; height: 60px; background: #ddd; }
</style>

<div class="box" id="box"></div>

<script>
  const sheet = document.getElementById('dyn').sheet; // CSSStyleSheet

  // Добавление правила через объектную модель стилей:
  sheet.insertRule('.box { border: 3px solid #333; }', sheet.cssRules.length);

  // Чтение правил:
  console.log(sheet.cssRules[0].cssText);
  console.log(sheet.cssRules[1].cssText);
</script>

Что демонстрируется

  • Встроенный тег style создает таблицу стилей, а insertRule добавляет правило на уровне CSSOM (через модель, а не только через «строку»).

Пример: computed styles (результат применения CSSOM к DOM)

<style>
  #box { font-size: 16px; }
  .big { font-size: 24px; }
</style>

<div id="box">Текст</div>

<script>
  const el = document.getElementById('box');

  console.log(getComputedStyle(el).fontSize); // "16px"
  el.classList.add('big');
  console.log(getComputedStyle(el).fontSize); // "24px"
</script>

Что демонстрируется

  • getComputedStyle(...) возвращает вычисленные стили конкретного DOM-элемента, то есть итог применения правил из CSSOM с учетом каскада.

Типичные ошибки и последствия

Частая ошибка — путать DOM с исходным HTML-текстом: HTML является входными данными, а DOM — результатом разбора и моделью, с которой работает API. Еще одна ошибка — считать CSSOM «ресурсами» (картинками/шрифтами): ресурсы могут участвовать в отображении, но CSSOM описывает именно правила стилей и их структуру.

Практические последствия (с точки зрения поведения и производительности)

  • Изменения DOM (добавление/удаление узлов) и изменения стилей (через CSSOM или style) могут вызывать пересчет стилей, layout и/или paint, потому что этапы рендеринга зависят от совместной работы DOM и CSSOM.
  • Понимание роли DOM/CSSOM помогает объяснить, почему некоторые изменения «дороже» (например, затрагивают геометрию), а некоторые дешевле (например, меняют только цвет).

Кратко: DOM — объектное дерево документа (узлы HTML в памяти), CSSOM — объектная модель CSS (правила и таблицы стилей); браузер строит DOM и CSSOM, совместно использует их для render tree, затем выполняет layout и paint, поэтому верным является вариант 1.