Принцип каскада
Один из основных принципов работы CSS. Стили читаются и применяются сверху вниз.
- Источники правил
- Область видимости
- Специфичность
- Порядок в коде
- Влияние на каскад 👻
- Начальное значение — initial
- Заимствование у родителя — inherit
- Отмена значения — unset
- Сброс значения — revert
- Николай Лопин советует
- Realetive советует
Если вы так боитесь каскада, что отказываетесь его изучать, вы не понимаете веба и лучше вам посмотреть в сторону чего-нибудь попроще в другой области кодинга. Спасибо, что прослушали мой доклад для фронтендеров.
Каскад — одно из важнейших понятий в CSS. Само название CSS — Cascading Style Sheets, «каскадные таблицы стилей» явно упоминают это неочевидное определение.
Точнее, в определении каскада принимает участие не только специфичность, но и в первую очередь источник этих правил и область видимости. Также имеет важное значение порядок в коде (какие свойства были объявлены «позже», те «важнее»).
Источники правил
Скопировать ссылку «Источники правил» Скопировано
- Стили во время CSS-переходов ( transition );
- Браузерные стили с !important ;
- Пользовательские стили с !important ;
- Авторские (мы с вами пишем именно эти стили) стили с !important ;
- Стили во время анимаций ( animation );
- Обычные (т. е. без !important ) авторские стили;
- Обычные пользовательские стили;
- Обычные браузерные стили.
Иногда браузеры нарушают этот порядок — порой осознанно (например, могут запретить делать слишком мелкий шрифт в полях ввода, как это делал Google Chrome) или по ошибке (до недавнего времени стили при анимации перекрывали остальные стили только в Firefox).
Область видимости
Скопировать ссылку «Область видимости» Скопировано
Со свойствами, описанными через классические CSS-селекторы (классы, теги, id, атрибуты) иначе — чем точнее мы описываем правило для селектора, тем сильнее мы суживаем область видимости (т. е. как бы точнее прицеливаемся), тем самым увеличивая и приоритетность правила. Но это работает до тех пор, пока CSS-правило не содержит «подлого» !important . Именно поэтому их использование считается плохой практикой — они «меняют правила игры». Это правило мгновенно становится приоритетнее, но чем шире область видимости — тем оно важнее 🤯
Специфичность
Скопировать ссылку «Специфичность» Скопировано
Установим цвет текста абзаца в красный:
p color: red;> Цвет текста будет красным — единственное правило описано в теге <style>.
style> p color: red; > style> p> Цвет текста будет красным — единственное правило описано в теге <style>. p>
Теперь переопределим цвет текста более специфичным инлайн-правилом:
p color: red;> Цвет текста стал синим — инлайн «перебивает» <style>.
style> p color: red; > style> p style="color: blue"> Цвет текста стал синим — инлайн «перебивает» <style>. p>
Повысим специфичность, добавив !important в правила селектора:
p color: red !important;> Цвет текста снова стал красным за счёт !important в <style>.
style> p color: red !important; > style> p style="color: blue"> Цвет текста снова стал красным за счёт !important в <style>. p>
Последний «шанс» разработчику повлиять на правило — добавить !important в инлайн-стиль:
p color: red !important;> Цвет текста снова синий — !important инлайн-правила «перебивает» даже !important в <style>.
style> p color: red !important; > style> p style="color: blue !important"> Цвет текста снова синий — !important инлайн-правила «перебивает» даже !important в <style>. p>
Инлайн-стили и !important — крайние меры влияния на стилизацию, правильнее описывать стили в селекторах в файлах. Но разные правила можно описать так, что они будут претендовать на одну и ту же сущность (тег и его содержимое). В этом случае на применимость правила будет влиять специфичность, т. е. тип (тег, класс, id, атрибуты и псевдоклассы) и их совокупность и комбинации. Самый простой способ разобраться в этом разнообразии — использовать так называемый калькулятор специфичности. Можно воспользоваться одним из множества онлайн-сервисов:
Подробнее про специфичность можно прочитать в статье «Специфичность».
Порядок в коде
Скопировать ссылку «Порядок в коде» Скопировано
Тут ещё проще — при равной специфичности правила, написанные ниже по ходу чтения переопределяют написанное выше:
.color_red /* Определяем начальное значение */ color: red;> .color_red /* Переопределяем написанное ранее правило */ color: blue;>
Цвет текста — синий!
style> .color_red /* Определяем начальное значение */ color: red; > .color_red /* Переопределяем написанное ранее правило */ color: blue; > style> p class="color_red">Цвет текста — синий!p>
Влияние на каскад 👻
Скопировать ссылку «Влияние на каскад 👻» Скопировано
Помимо знания как и где написать селектор, можно управлять каскадом с помощью CSS-свойств!
Начальное значение — initial
Скопировать ссылку «Начальное значение — initial» Скопировано
Любое CSS-правило можно сбросить на начальное значение — то, которое было у правила до того как было установлено явно разработчиком. color станет #000 , position — static , display — inline , padding и margin — 0 и так далее.
Даже если для тега какое-то свойство имеет конкретное значение (например, для по умолчанию браузером ставится display : block ), установка initial выставит именно дефолтное значение без учёта значения для тега (то есть для свойство display : initial вычислится как inline ).
Заимствование у родителя — inherit
Скопировать ссылку «Заимствование у родителя — inherit» Скопировано
Некоторые свойства наследуются от родителя автоматически ( color , font , text — align и другие). Но можно и явно позаимствовать какое-то значение у родителя:
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» Скопировано
По своему поведению unset чем-то похож на initial + inherit — если это свойство ненаследуемое от родителя — оно сбросится до начального значения, наследуемое — получит значение родителя.
Сброс значения — revert
Скопировать ссылку «Сброс значения — 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 советует
Скопировать ссылку «Realetive советует» Скопировано
🛠 Понимание каскада — один из ключевых моментов в понимании работы CSS. С опытом вы научитесь так эффективно писать селекторы и группировать стили, что сам уровень каскада будет минимальным — это ускоряет «чтение» кода и упрощает поддержку. Ну и в идеале — исключить необходимость использования !important .
Каскадирование и специфичность CSS
Наверно у многих, кто занимается (занимался) версткой и в плотную сталкивался с таблицами стилей, наступали моменты когда !important на !important’e сидел, css превращался в вереницу длинных цепочек, но все равно кто-то, где-то, кого-то перебивал (или наоборот). И не совсем ясно, почему так происходит.
Давайте раз и навсегда разберемся с каскадированием стилей и специфичностью селекторов.
Специфичность селекторов определяет их приоритетность в таблице стилей. Чем специфичнее селектор, тем выше его приоритет.
Подсчитать приоритет селектора очень просто.- inline-стили имеют специфичность 1000
- за каждый идентификатор (#) 0100
- за каждый класс (.) и псевдо-класс (. []) 0010
- за каждый тег и псевдо-элемент 0001
- * и стили браузера 0000
* /* специфичность 0000 */ li /* специфичность 0001*/ ul li /* специфичность 0002*/ .list li /* специфичность 0011*/ #list li /* специфичность 0101*/ a[href^="http://"] /* специфичность 0011 */
При добавлении !important приоритет становится главенствующим. Если !important несколько
стоит задуматься о смене профессииони начинают подчиняться тем же правилам.li /* специфичность 0001 - win*/ ul li /* специфичность 0002*/
li /* специфичность 0001*/ ul li /* специфичность 0002 - win*/
После всех манипуляций специфичность совпала — выигрывает последнее (то что ниже) правило.
Ну и конечно же CSS-анимации, имеющие приоритет выше, даже чем !important в inline-стилях.
UPD Почему 11 классов не имеют большего приоритета над идентификатором читать здесь