CSS изначально был построен на концепции каскадности, сама аббревиатура означает Cascading Style Sheets (каскадные таблицы стилей).

К сожалению, эта концепция имеет плохую репутацию. Разбираемся, так ли это плохо на самом деле?

Введение

Джон пишет очень много CSS, а затем открывает браузер, чтобы проверить свой код. К его удивлению, стили не применяются к тому элементу, который он хотел стилизовать, зато появляются какие-то другие изменения!

Из-за подобных ситуаций многие жалуются, что CSS – отстой.

В CSS несколько стилей могут влиять на один и тот же элемент. А любой блок можно заставить выглядеть как угодно. Это похоже на глобальную переменную JavaScript, которую может изменить любая функция в коде. Катастрофа!

Но вам придется принять это, потому что изменить ничего нельзя.

Что такое Каскад?

Каскад – это механизм, с помощью которого браузер определяет, какие стили применять к определенному элементу.

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

  • специфичность селекторов;
  • порядок написания стилей.

Специфичность селекторов

Специфичность селектора можно сравнить с тем, как человеческий разум интерпретирует инструкции.

Например, рассмотрим рисунок ниже:

Если я скажу: «Передай мне красную коробку», – что вы сделаете? Обе коробки красные!

Вы можете уточнить «Какой из ящиков нужен: a или b?».

Или вы можете взять обе коробки, ведь они соответствуют условию. Именно так ведет себя браузер.

Когда вы говорите, «установи красный фон для абзаца…»

p {
  background-color: red;
}

браузер не может спросить, какой именно абзац нужно покрасить, если их на странице несколько. Поэтому он просто идет и стилизует все абзацы, которые находит.

Однако если вы скажете, что нужно покрасить абзацы с классом reddy:

p.reddy {
  background-color: red;
}

это будет уже конкретнее.

Теперь браузер стилизует только некоторые элементы, подходящие под условие.

Технически браузер смотрит на каждый селектор, который указывает на какой-то элемент, и присваивает ему «баллы». Если таких селекторов несколько и они противоречат друг другу, то выигрывает тот, у которого более высокий показатель специфичности.

Способ вычисления оценок прост.

Предположим, что у браузера при интерпретации вашего CSS есть четверо футбольных ворот.

  1. Каждый инлайновый стиль, который задается с помощью атрибута style, забивает гол в первые ворота (a).
  2. Каждый селектор по id – во вторые (b).
  3. Каждый селектор класса, псевдокласса и атрибута  – в третьи (c).
  4. Каждый селектор элемента и псевдоэлемента – в четвертые (d).

Общее количество баллов рассчитывается путем конкатенации цифр. Вы получаете четырехзначное число, где первой цифрой является количество голов в первые ворота, второй – во вторые и т. д.

Пример специфичности

Возьмем следующие объявления стилей:

#nav .removed > a:hover {}
li:last-child h3 .title {}

Как браузер будет считать «голы» специфичности?

Разберем первый селектор:

#nav .removed > a:hover
  • (a) нет встроенного стиля, нет голов в первые ворота – 0.
  • (b) есть один селектор id – #nav – 1 гол во вторые ворота.
  • (c) есть также один селектор класса .removed и один селектор псевдо-класса :hover – итого 2 гола в третьи ворота.
  • (d) есть один селектор элемента – a – 1 гол.

Вот графическое представление результатов.

Общий балл специфичности 0121.

Как и в обычной математике, 0001 меньше 0005, а 0121 больше 0021.

Теперь вы понимаете, как рассчитывается специфичность. Попробуйте вычислить ее для второго селектора li:last-child h3 .title.

Порядок Стилей

Вторым фактором, влияющим на каскад, является порядок стилей. Простой пример – это стилизация одного и того же элемента в двух разных блоках кода.

p.reddy {
  background: red;
}

p.reddy {
   background: blue;
}

Оба селектора имеют одинаковую специфичность — 0011. И тут в игру вступает порядок.

Второе объявление отменит первое, и абзац будет синим, а не красным.

Вопрос с подвохом

Какой цвет текста будет у ссылки в следующем документе?

<!doctype html> 
<html>
    <head>
        <title>Inline Styles and Specificity</title> 
        <style type="text/css">
            #nav-force > ul > li > a.nav-link { 
                color: blue;
            };
        </style> 
    </head>
    <body>
        <nav id="nav-force">
            <ul> 
                <li>
                    <a href="/" class="nav-link" style="color: red;">
                        Link
                    </a> 
                </li>
            </ul> 
        </nav>
    </body> 
</html>

Синий или красный?

Обратите внимание, что стиль для ссылки задается как через атрибут, так и в блоке <style></style>.

На самом деле, инлайновый стиль всегда выигрывает. Это гол в первые ворота, который весит больше чем любой другой. Ведь окончательная специфичность будет больше или равна тысяче – 1000, а это больше даже 9 голов во вторые ворота – 0900.

На самом деле, даже если во вторых воротах будет 11 голов, один гол в первые будет весить больше. Специфичность будет равна 0, 11, 0, 0, что меньше, чем 1, 0, 0, 0, потому что четвертый разряд всегда больше третьего.

Вывод

Надеюсь, теперь вы твердо понимаете, как работает каскад, и дальнейшее изучение CSS будет проще.

4 комментария

  • stroitelstvo
    stroitelstvo
    10/06/2022, 01:07
    Спасибо за полезный материал.
  • HeSre
    HeSre
    16/11/2021, 05:12
    Спасибо, ваш сайт очень полезный!
  • somekell
    somekell
    9/09/2018, 06:01
    С точки зрения формальной логики "Передай мне красную коробкУ" - запрос, результатом которого должна стать Одна красная коробка. И только одна. Под описание "красная коробка" подходит сразу два объекта, но с разными свойствами. И мы не можем просто так взять и вернуть два объекта вместо одного. Мы должны уточнить, точно ли требуется именно одна коробка, и какая именно? Уточняющая информация - либо свойства объектов, либо сами объекты. Но результат уточнения - либо отсеивание объектов до одного, либо коррекция запроса.
    • Furry_web
      Furry_web
      9/09/2018, 09:16
      Да, действительно, не очень корректный пример :)

Оставить комментарий

*Доступные HTML-теги: a, abbr, blockquote, code, pre, del, i, em, strong, b, strike
*Не будет опубликован