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 важно. Эти знания помогут вам стать профессиональным веб-разработчиком.