Вопрос-ответ

Популярные вопросы с ответами для владельцев и разработчиков сайтов

Как браузер читает CSS?

Браузер читает CSS справа налево (от самого конкретного селектора к самому общему), разбирает каждый селектор на составляющие, сопоставляет их с элементами DOM-дерева и применяет правила в порядке каскада с учётом специфичности. Этот процесс называется построением CSSOM (CSS Object Model). После того как браузер получает CSS-файл, он не применяет всё подряд, а выполняет сложный алгоритм парсинга, вычисления приоритетов и визуализации, чтобы определить, какой именно стиль должен быть у каждого элемента на странице.

От получения CSS до визуального отображения: полный цикл

Чтобы понять, как браузер читает и обрабатывает CSS, нужно проследить весь путь от загрузки файла до отрисовки пикселей на экране. Браузер не просто читает CSS построчно — он выполняет чёткую последовательность действий.

ЭтапЧто происходитРезультат
Загрузка и парсинг CSS Браузер скачивает CSS-файл (или читает тег <style>) и разбивает его на токены (ключевые слова, селекторы, свойства, значения) CSS разобран на синтаксические элементы, ошибки отброшены
Построение CSSOM На основе отпарсенных правил браузер строит древовидную структуру — CSS Object Model, где каждому узлу DOM сопоставлены стили CSSOM готов к сопоставлению с DOM
Вычисление каскада и специфичности Браузер определяет, какие правила из разных источников (браузерные стили, авторские, пользовательские) имеют приоритет Для каждого элемента определён победитель среди всех конфликтующих правил
Расчёт финальных значений Относительные единицы (em, rem, %), ключевые слова (inherit, initial) превращаются в абсолютные значения Каждое CSS-свойство получило конкретное числовое значение
Привязка к DOM Браузер проходит по DOM-дереву и для каждого элемента применяет вычисленные стили из CSSOM Каждый HTML-элемент получил полный набор CSS-свойств
Построение Render Tree Браузер объединяет DOM и CSSOM в дерево рендеринга, оставляя только видимые элементы (скрытые через display:none исключаются) Готово дерево для расчёта геометрии страницы

Как браузер читает CSS-селекторы: правосторонний парсинг

Самый контринтуитивный момент для новичков: браузер читает селекторы не слева направо, а справа налево. Например, селектор .menu ul li a:hover будет обрабатываться начиная с a:hover.

Почему справа налево? Потому что так браузеру нужно проверить гораздо меньше элементов. Алгоритм выглядит так:

  • Найти все элементы, соответствующие самому правому селектору (например, все теги <a> с псевдоклассом :hover).
  • Для каждого найденного элемента проверить, есть ли у него родитель, соответствующий следующему селектору слева (li).
  • Затем проверить родителя этого родителя на соответствие .menu ul, и так до конца.

Если бы браузер читал слева направо, ему пришлось бы проверять все элементы .menu, затем внутри них все ul, затем все li, и только потом искать a:hover. Это в разы медленнее, особенно на больших страницах. Поэтому правильный порядок написания селекторов (избегайте длинных цепочек, не начинайте с универсальных селекторов) напрямую влияет на скорость чтения CSS браузером.

Каскад: как браузер разрешает конфликты между правилами

CSS расшифровывается как Cascading Style Sheets (каскадные таблицы стилей). "Каскадность" означает, что к одному элементу может применяться несколько правил из разных источников, и браузер должен выбрать одно. Алгоритм выбора строгий и предсказуемый.

Источники CSS-правил (от низшего приоритета к высшему)

  • Браузерные стили (User Agent) — стили по умолчанию, которые есть в каждом браузере (например, синий цвет ссылки).
  • Пользовательские стили — если пользователь явно задал свои стили в настройках браузера или через расширения.
  • Авторские стили — CSS, который написал разработчик сайта (основной источник).
  • !important в авторских стилях — перебивает обычные правила.
  • !important в пользовательских стилях — самый высокий приоритет.

Если правила из одного источника конфликтуют, вступает в силу механизм специфичности (веса селектора).

Специфичность: как браузер вычисляет вес селектора

Каждому CSS-селектору браузер присваивает числовой вес, который считается по трём категориям (условно — сотни, десятки, единицы).

  • Инлайн-стили (атрибут style) — вес 1000 (самый высокий).
  • ID (#header) — вес 100.
  • Классы (.active, .menu), псевдоклассы (:hover), атрибуты ([type="text"]) — вес 10.
  • Теги (div, p, a) и псевдоэлементы (::before, ::after) — вес 1.
  • Универсальный селектор (*), комбинаторы (+, >, ~) — вес 0.

Пример расчёта специфичности браузером:

  • p → вес 0,0,1
  • .text → вес 0,1,0
  • #header .menu p → вес 1,1,1 (один ID, один класс, один тег)
  • div#header .menu a:hover → вес 1,2,2 (ID, два класса/псевдокласса, два тега)

Правило с большим весом перебивает правило с меньшим независимо от порядка в файле. Если веса равны, побеждает то правило, которое объявлено позже (ниже по коду). Это знание критически важно для отладки CSS — когда вы не понимаете, почему браузер не применяет нужный стиль, проблема почти всегда в специфичности или порядке каскада.

0971

Что происходит с невалидным CSS и ошибочными свойствами

Браузер спроектирован так, чтобы не падать из-за ошибок в CSS. Он читает файл блоками (правило за правилом) и если встречает синтаксическую ошибку (например, незакрытую фигурную скобку, опечатку в свойстве), то отбрасывает только это одно правило. Всё остальное продолжает работать.

Пример:

p {
  color: red;
  font-sieze: 16px; // опечатка, свойство не существует
  margin: 10px;
}

Браузер применит color: red и margin: 10px, а строку с font-sieze проигнорирует. Далее браузер проверит каждое значение на корректность. Если указан неподдерживаемый формат (например, color: super-red), правило тоже будет проигнорировано, но соседние правила в том же селекторе останутся активными. Механизм толерантности к ошибкам позволяет сайтам не разваливаться полностью из-за одной опечатки.

Перерисовка и перекомпоновка: как браузер реагирует на изменения CSS

Когда браузер уже прочитал CSS и отобразил страницу, но затем что-то меняется (например, при наведении мыши, клике или через JavaScript), он не перечитывает весь CSS-файл заново. Вместо этого происходят процессы перекомпоновки (reflow) и перерисовки (repaint).

  • Reflow (перекомпоновка) — браузер пересчитывает геометрию (размеры, позиции) элементов. Это самая тяжёлая операция. Например, изменение ширины блока, добавление нового DOM-элемента, изменение шрифта.
  • Repaint (перерисовка) — браузер заново рисует видимые части элементов без пересчёта геометрии. Например, изменение цвета фона, видимости, прозрачности. Это быстрее, чем reflow.

Некоторые CSS-свойства (transform, opacity, filter) могут обрабатываться на GPU отдельным слоем, что вообще не вызывает ни reflow, ни repaint основного документа. Именно поэтому для анимаций рекомендуют использовать transform вместо margin или top.

Как браузер обрабатывает медиа-запросы и условный CSS

При чтении CSS браузер проверяет каждое правило @media. Если условия медиа-запроса (ширина экрана, ориентация, поддержка определённых возможностей) не выполняются в данный момент, браузер не парсит содержимое этого медиа-блока? На самом деле — парсит, но не применяет. Токенизация и построение CSSOM происходят для всех правил, но в дерево рендеринга попадают только те, условия которых истинны.

Это важно для производительности: браузер всё равно скачивает и разбирает CSS внутри медиа-запросов. Поэтому не стоит прятать тонны стилей в недостижимые условия — они всё равно будут потреблять память и время парсинга. Более эффективно загружать разные CSS-файлы асинхронно с атрибутом media в теге <link>.

Инструменты для изучения того, как браузер прочитал CSS

Вы не можете заглянуть в "голову" браузера, но можете воспользоваться встроенными инструментами разработчика, чтобы увидеть результат его работы.

  • Вкладка Elements (Styles) — показывает все CSS-правила, применённые к выбранному элементу, отсортированные по специфичности и каскаду. Зачёркнутые свойства — перебитые правилами с большим весом.
  • Вкладка Computed — показывает финальные вычисленные значения каждого CSS-свойства после применения каскада, специфичности и преобразования относительных единиц.
  • Coverage (вкладка Performance или настройки Sources) — показывает, какой процент CSS-кода реально был использован на странице, а какие селекторы так и не нашли подходящих элементов в DOM.
  • Вкладка Performance с записью — можно увидеть время парсинга CSS, построения CSSOM и этапы Render, Layout, Paint.

Эти инструменты — ваш главный способ "услышать", как браузер прочитал ваш CSS. Если селектор имеет высокую специфичность, но стиль не применяется — проверьте, нет ли опечатки или не закрыт ли медиа-запрос.

Итог: Браузер читает CSS в несколько этапов: загрузка и токенизация → построение CSSOM → вычисление каскада и специфичности → расчёт финальных значений → привязка к DOM → построение Render Tree. Чтение селекторов идёт справа налево для оптимизации скорости. Вес селектора вычисляется по строгим правилам (инлайн > ID > классы/атрибуты > теги), а при равном весе побеждает правило, объявленное позже. Понимание этого алгоритма позволяет писать CSS, который браузер обработает быстро и предсказуемо. Избегайте слишком длинных селекторов, не злоупотребляйте !important и помните, что браузер толерантен к ошибкам, но лучше их не допускать.