CSS специфичность

Дан HTML-код:

<html>
<html>
  <head>
    <style>
      #element {
        color: red;
      }

      .element {
        color: blue;
      }

      div.element {
        color: yellow;
      }

      div.element {
        color: magenta;
      }
    </style>
  </head>
  <body>
    <div id="element" class="element">
      Some dummy text
    </div>
</body>
</html>

Какой будет цвет у текста «Some dummy text»?

Теория: каскад и специфичность

В CSS часто возникает ситуация, когда несколько правил задают одно и то же свойство одному и тому же элементу (здесь свойство color). Тогда применяется каскад: браузер выбирает «победившее» правило по приоритетам.

В типичной задаче (обычные стили автора, без !important) достаточно помнить два шага:

  1. Сначала сравнивается специфичность селекторов: более специфичный селектор выигрывает.
  2. Если специфичность равна, выигрывает правило, объявленное ниже (позже) в CSS.
Специфичность удобно считать в виде тройки ID-CLASS-TYPE:
  • ID: количество селекторов по идентификатору (#something)
  • CLASS: количество классов (.something), атрибутов ([type="..."]), псевдоклассов (:hover)
  • TYPE: количество селекторов по тегу (div, p) и псевдоэлементов (::before)
  • Правило сравнения двух селекторов по специфичности:

    • Сначала сравнивается ID (кто больше — тот сильнее)
    • Если ID равны, сравнивается CLASS
    • Если CLASS равны, сравнивается TYPE
    • Если все три части равны, решает порядок в CSS (ниже — сильнее)

    Пример «веса» для селекторов из условия:

    СелекторСпецифичность (ID-CLASS-TYPE)Комментарий
    #element1-0-0Очень высокий приоритет из-за id
    .element0-1-0Приоритет ниже, чем у любого id
    div.element0-1-1Сильнее, чем просто класс, но слабее id

    Разбор данного кода

    HTML-элемент в задаче:

    <div id="element" class="element">
      Some dummy text
    </div>
    

    К нему одновременно подходят все эти селекторы:

    • #element (потому что у элемента есть id="element")
    • .element (потому что у элемента есть class="element")
    • div.element (потому что это тег div и у него есть класс element)

    CSS из условия:

    #element {
      color: red;
    }
    
    .element {
      color: blue;
    }
    
    div.element {
      color: yellow;
    }
    
    div.element {
      color: magenta;
    }
    

    Далее выполняется последовательное сравнение:

    1. Селектор #element имеет специфичность 1-0-0.
    2. Селектор .element имеет специфичность 0-1-0.
    3. Селектор div.element имеет специфичность 0-1-1.

    Ключевой момент: у #element в части ID стоит 1, а у остальных — 0. Это означает, что правило #element { color: red; } выигрывает у любого правила, где нет id, даже если там есть и тег, и класс, и дополнительные типовые селекторы.

    Отдельно про два одинаковых селектора div.element:

    • Они имеют одинаковую специфичность (0-1-1).
    • Значит, между ними победит то правило, которое объявлено ниже.
    • Поэтому при отсутствии #element итогом для div.element было бы magenta, так как второе div.element перекрывает первое.

    Но в данной задаче более специфичный #element перекрывает оба варианта div.element и .element, поэтому итоговый цвет текста остаётся red.

    Дублирование одного и того же селектора (как два раза div.element) делает стили менее очевидными: визуально кажется, что задаются два разных случая, но фактически второе правило просто «перезаписывает» первое при равных условиях.

    Кратко: элемент подходит под #element, .element и div.element, а селектор #element имеет наибольшую специфичность из-за id, поэтому итоговый цвет текста — red; правило magenta победило бы только при отсутствии #element.