Как работает таблица стилей и как браузер определяет применяемый стиль к элементу?
Что проверяют
Понимаете ли вы каскад как алгоритм с чёткими ступенями, а не как «побеждает самый специфичный селектор». Следом обычно спрашивают, что сильнее: !important или инлайн-стиль, и как на порядок влияют каскадные слои @layer.
Как отвечать
Браузер строит DOM и CSSOM, затем на этапе вычисления стилей собирает для каждого элемента все подходящие объявления. Селекторы сопоставляются справа налево: сначала правая часть, потом предки. Если на одно свойство претендуют несколько объявлений, каскад сравнивает их по ступеням до первого различия:
- источник и важность: стили браузера, пользователя и автора. Обычные авторские сильнее браузерных, а у
!importantпорядок источников переворачивается; - контекст: при Shadow DOM обычные стили снаружи побеждают стили внутри компонента, для
!importantнаоборот; - атрибут
style: инлайн-объявления сильнее любых селекторов того же уровня важности; - слои: у обычных объявлений стили вне
@layerсильнее любых слоёв, среди слоёв побеждает объявленный позже. Для!importantпорядок обратный; - специфичность: тройка (ID, классы с атрибутами и псевдоклассами, теги с псевдоэлементами), сравнивается слева направо.
:is(),:not()и:has()берут специфичность самого сильного аргумента,:where()даёт ноль; - порядок появления: при равенстве побеждает объявленное позже.
Если каскадного значения нет, работает наследование: color, font-size, line-height берутся у родителя, а margin, border и padding получают начальное значение. Затем значение становится вычисленным: em и проценты переводятся в конкретные величины, это видно в getComputedStyle().
Где спотыкаются
Думают, что инлайн-стиль сильнее всего. Авторский !important в таблице стилей его перебивает, а анимации и переходы стоят в каскаде отдельно.
Считают специфичность одним числом, где 11 классов бьют один ID. Разряды не переполняются, один ID сильнее любого количества классов.
Забывают, что наследование слабее любого правила. Стиль, заданный элементу напрямую, даже селектором *, перебьёт унаследованный от родителя цвет.