CSS: спецификация и каскад

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

Не будем зацикливаться на раздувании споров. Вместо этого углубимся в теорию и проведем время с пользой.

Пример под рукой

Используем тот же пример, который использовался в опросе. Я заменил color на background и использовал более приятные цвета.

Вот, что получилось:

HTML

<main>
    <div class="red blue"></div>
    <div class="blue red"></div>
</main>

CSS

.red {
    background: #c23616;
}

.blue {
    background: #4b7bec;
}






/* Нерелевантный вид и стили */
body {
    height: 100vh;
    margin: 0;
    display: grid;
    place-items: center;
}

main {
    padding: 2rem;
}

div {
    width: 180px;
    height: 180px;
    border-radius: 5px;
}

div + div {
    margin-top: 10px;
}

Как видите, оба блока синего цвета. Но почему? Причина этого заключается в том, что и .red, и .blue имеют одинаковый уровень специфичности. Поэтому браузер выбирает последний стиль в CSS-коде. В примере – это .blue.

Если поменять местами объявления классов в CSS, то получим следующее:

HTML

<main>
    <div class="red blue"></div>
    <div class="blue red"></div>
</main>

CSS

.blue {
    background: #273c75;
}

.red {
    background: #c23616;
}





/* Нерелевантный вид и стили */
body {
    height: 100vh;
    margin: 0;
    display: grid;
    place-items: center;
}

main {
    padding: 2rem;
}

div {
    width: 180px;
    height: 180px;
    border-radius: 5px;
}

div + div {
    margin-top: 10px;
}

Так как .red был объявлен после .blue, то блоки стали красными. Логика браузера при каскадной сортировке выглядит следующим образом: он перемещается вниз по таблице стилей, пока не обнаружит самое специфичное правило. Приведенные выше правила обладают равной специфичностью, поэтому объявление .red после .blue приводит к окрашиванию блоков в красный цвет.

Базовое введение в спецификацию

Будем использовать тот же пример, чтобы разобраться с применением спецификации.

Используем селектор ID

Селектор повышает приоритетность правила в спецификации. id будет приоритетнее, чем class. Поэтому в следующем примере новое правило #green станет специфичнее, чем .red и .blue, несмотря на расположение в CSS.

Использование селекторов ID в CSS допустимо. Но лучше привязывать стили к классам, элементам и атрибутам HTML.

Пример:

HTML

<main>
    <div class="red blue" id="green"></div>
    <div class="blue red"></div>
</main>

CSS

.red {
    background: #c23616;
}

.blue {
    background: #4b7bec;
}

#green {
    background: #20bf6b;
}





/* Нерелевантный вид и стили */
body {
    height: 100vh;
    margin: 0;
    display: grid;
    place-items: center;
}

main {
    padding: 2rem;
}

div {
    width: 180px;
    height: 180px;
    border-radius: 5px;
}

div + div {
    margin-top: 10px;
}

Добавляем атрибут style

Добавим в первый div атрибут style. Это сделает правило #green менее специфичным, потому что атрибуты style приоритетнее любого правила в CSS, кроме !important.

В следующем примере я установил фиолетовый цвет для #green в атрибуте style. В результате он становится специфичнее всех остальных стилей (в том числе определенных в .red и .blue).

Пример:

HTML

<main>
    <div class="red blue" id="green" style="background: #a55eea"></div>
    <div class="blue red"></div>
</main>

CSS

.red {
    background: #c23616;
}

.blue {
    background: #4b7bec;
}

#green {
    background: #20bf6b;
}


body {
    height: 100vh;
    margin: 0;
    display: grid;
    place-items: center;
}

main {
    padding: 2rem;
}

div {
    width: 180px;
    height: 180px;
    border-radius: 5px;
}

div + div {
    margin-top: 10px;
}

Добавляем !important

Последнее правило, рассматриваемое в данной статье – !important. Этот модификатор выигрывает в любом случае.

Я добавлю !important в класс .red. В результате все блоки станут красными. Так как !important имеет наибольший приоритет. Но использовать этот модификатор необходимо с умом. Ведь из-за его важности ни один элемент не может быть специфичнее, чем !important.

Пример:

HTML

<main>
    <div class="red blue" id="green" style="background: #a55eea"></div>
    <div class="blue red"></div>
</main>

CSS

.red {
    background: #c23616 !important;
}

.blue {
    background: #4b7bec;
}

#green {
    background: #20bf6b;
}





/* Нерелевантный вид и стили */
body {
    height: 100vh;
    margin: 0;
    display: grid;
    place-items: center;
}

main {
    padding: 2rem;
}

div {
    width: 180px;
    height: 180px;
    border-radius: 5px;
}

div + div {
    margin-top: 10px;
}

Заключение

Понимание каскада и спецификации CSS важно. Эти знания помогут вам стать профессиональным веб-разработчиком.