Клавиша / esc

Принцип каскада

Один из основных принципов работы CSS. Стили читаются и применяются сверху вниз.

Время чтения: 6 мин

Если вы так боитесь каскада, что отказываетесь его изучать, вы не понимаете веба и лучше вам посмотреть в сторону чего-нибудь попроще в другой области кодинга. Спасибо, что прослушали мой доклад для фронтендеров.

— Эрик Мейер, автор «CSS: The Definitive Guide», источник

Большой Каскад в Петергофе

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

Точнее, в определении каскада принимает участие не только специфичность, но и в первую очередь источник этих правил и их важность. Также имеет важное значение порядок в коде (какие свойства были объявлены «позже», те «важнее»).

Источники правил

Скопировано

Чем выше — тем «важнее»:

  1. Стили во время CSS-переходов (transition);
  2. Браузерные стили с !important;
  3. Пользовательские стили с !important;
  4. Авторские (мы с вами пишем именно эти стили) стили с !important;
  5. Стили во время анимаций (animation);
  6. Обычные (т. е. без !important) авторские стили;
  7. Обычные пользовательские стили;
  8. Обычные браузерные стили.

Иногда браузеры нарушают этот порядок — порой осознанно (например, могут запретить делать слишком мелкий шрифт в полях ввода, как это делал Google Chrome) или по ошибке (до недавнего времени стили при анимации уступали !important-стилям только в Firefox).

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

Скопировано

Когда мы описываем стили (инлайном в теге или на селектор в <style> или файле), каждое правило имеет свой вес. Со свойствами, описанными через классические CSS-селекторы (классы, теги, id, атрибуты) общая логика такая: чем точнее мы описываем правило для селектора (как бы точнее прицеливаемся), т.е. чем специфичнее получилось это правило, тем выше его вес. Правила, описанные инлайном (в атрибуте style), перебивают правила на любой селектор, но не отменяют правила с !important (если только инлайн-правило само не содержит !important).

Установим цвет текста абзаца в красный:

        
          
          <style>p {  color: red;}</style><p>  Цвет текста будет красным — единственное правило описано  в теге &lt;style&gt;.</p>
          <style>
p {
  color: red;
}
</style>

<p>
  Цвет текста будет красным — единственное правило описано
  в теге &lt;style&gt;.
</p>

        
        
          
        
      

Теперь переопределим цвет текста инлайн-правилом (в CSS-каскаде оно считается более специфичным):

        
          
          <style>p {  color: red;}</style><p style="color: blue">  Цвет текста стал синим — инлайн «перебивает» &lt;style&gt;.</p>
          <style>
p {
  color: red;
}
</style>

<p style="color: blue">
  Цвет текста стал синим — инлайн «перебивает» &lt;style&gt;.
</p>

        
        
          
        
      

Повысим важность правилу из селектора, добавив ему !important:

        
          
          <style>p {  color: red !important;}</style><p style="color: blue">  Цвет текста снова стал красным за счёт !important.</p>
          <style>
p {
  color: red !important;
}
</style>

<p style="color: blue">
  Цвет текста снова стал красным за счёт !important.
</p>

        
        
          
        
      

Последний «шанс» разработчику повлиять на правило — добавить !important в инлайн-стиль:

        
          
          <style>p {  color: red !important;}</style><p style="color: blue !important">  Цвет текста снова синий — !important инлайн-правила «перебивает» даже  !important в &lt;style&gt;.</p>
          <style>
p {
  color: red !important;
}
</style>

<p style="color: blue !important">
  Цвет текста снова синий — !important инлайн-правила «перебивает» даже
  !important в &lt;style&gt;.
</p>

        
        
          
        
      

Инлайн-стили и !important — крайние меры влияния на стилизацию, правильнее описывать стили в селекторах в файлах.

Значение специфичности селектора складывается из специфичностей его составляющих (тегов, классов, псевдоклассов, ID и пр.). Самый простой способ разобраться в этом разнообразии — использовать так называемый калькулятор специфичности. Можно воспользоваться одним из множества онлайн-сервисов:

Подробнее про специфичность можно прочитать в статье «Специфичность».

Порядок в коде

Скопировано

Тут ещё проще — при равной специфичности правила, написанные ниже по ходу чтения переопределяют написанное выше:

        
          
          <style>.color_red {  /* Определяем начальное значение */  color: red;}.color_red {  /* Переопределяем написанное ранее правило */  color: blue;}</style><p class="color_red">Цвет текста — синий!</p>
          <style>
.color_red {
  /* Определяем начальное значение */
  color: red;
}

.color_red {
  /* Переопределяем написанное ранее правило */
  color: blue;
}
</style>

<p class="color_red">Цвет текста — синий!</p>

        
        
          
        
      

Влияние на каскад 👻

Скопировано

Помимо знания как и где написать селектор, можно управлять каскадом с помощью CSS-свойств!

Начальное значение — initial

Скопировано

Любое CSS-правило можно сбросить на начальное значение — то, которое было у правила до того как было установлено явно разработчиком. color станет #000, positionstatic, displayinline, padding и margin0 и так далее.

Заимствование у родителя — inherit

Скопировано

Некоторые свойства наследуются от родителя автоматически (color, font, text-align и другие). Но можно и явно позаимствовать какое-то значение у родителя:

        
          
          <div class="wrapper">  <div class="inner"></div></div>
          <div class="wrapper">
  <div class="inner"></div>
</div>

        
        
          
        
      
        
          
          .wrapper {  background-color: #2E9AFF;  border: 10px solid #FFFFFF;}.inner {  background-color: #F498AD;  border: inherit;}
          .wrapper {
  background-color: #2E9AFF;
  border: 10px solid #FFFFFF;
}

.inner {
  background-color: #F498AD;
  border: inherit;
}

        
        
          
        
      
Открыть демо в новой вкладке

Отмена значения — unset

Скопировано

По своему поведению unset чем-то похож на initial + inherit — если это свойство ненаследуемое от родителя — оно сбросится до начального значения, наследуемое — получит значение родителя. Как если бы свойство вообще нигде не было задано.

Сброс значения — revert

Скопировано

Это менее строгий режим сброса — он отменяет все установленные разработчиком значения для данного свойства до значения, которое считается браузером «значением по умолчанию».

Подсказки

Скопировано

💡 В CSS есть такое волшебное свойство — all — это своеобразный шорткат (сокращённый формат записи), который внутри себя содержит все-все CSS-свойства. В сочетании с initial, inherit, unset или revert это позволяет повлиять на каскад в одну строчку.

Все наследуемые свойства .widget и вложенных элементов будут сброшены:

        
          
          .widget {  all: revert;}
          .widget {
  all: revert;
}

        
        
          
        
      

На практике

Скопировано

Николай Лопин советует

Скопировано

🛠 Если вы знакомы с JavaScript, то каскад можно представить как создание объекта через спред-синтаксис на основе приоритета стилей:

        
          
          const styles = {  ...inheritedStyles,  ...tagStyles,  ...classStyles,  ...idStyles,  ...inlineStyles,  ...importantStyles,  ...transitionStyles}
          const styles = {
  ...inheritedStyles,
  ...tagStyles,
  ...classStyles,
  ...idStyles,
  ...inlineStyles,
  ...importantStyles,
  ...transitionStyles
}

        
        
          
        
      

Realetive советует

Скопировано

🛠 Понимание каскада — один из ключевых моментов в понимании работы CSS. С опытом вы научитесь так эффективно писать селекторы и группировать стили, что сам уровень каскада будет минимальным — это ускоряет «чтение» кода и упрощает поддержку. Ну и в идеале — исключить необходимость использования !important.