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

CSS — это каскадные таблицы стилей (Cascading Style Sheets). Каскадность — это главный принцип css — это приоритет одних правил/стилей над другими. Когда одни стили перебивают другие. Это понятие также называется "специфичность селектора".

Читайте также о специфичности: https://developer.mozilla.org/ru/docs/Web/CSS/Specificity

При вычислении приоритета браузер определяет «Вес» каждого CSS правила, который складывается из веса отдельных селекторов этого правила. Стили менее весомых правил перебиваются стилями более весомых. В результате элемент получает собранные стили от самых «весомых» правил. Все это и есть каскадность.

Таблица веса (числа) для каждого селектора:

Тип селектора Описание селектора Вес (число)
* универсальный селектор 0
div тег 1
:first-letter псевдо-элемент 1
.text класс 10
:hover псевдо-класс 10
[атрибут="значение"] селектор атрибута 10
#content селектор по id 100
style="color:red;" стили в style атрибуте 1000
!important суффикс увеличения веса 10000

Из правил с одинаковым весом выбираются те, которые ближе к концу HTML страницы (ниже в коде).

Пример подсчета веса (вес представляет из себя число):

#content .text p { color:red; } /* 100 + 10 + 1 = 111 */
.text p { color:blue; }         /* 10 + 1 = 11 */

Тег <p> внутри элемента .text получит стиль color:red;, а не color:blue;, потому что число 111 больше чем 11.

Теперь давайте посчитаем веса на примере:

* {}                        /* =   0 */
li {}                       /* =   1 */
li::first-line {}           /* =   2 */
ul li {}                    /* =   2 */
ul ol + li {}               /* =   3 */
ul li.red {}                /* =  12 */
li.red.level {}             /* =  21 */
li:not(.red){}              /* =  11 */
li:not(.red):not(.green){}  /* =  11 */

#t34 {}                     /* = 100 */

#content #wrap {}           /* = 200 */

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

Трюк с увеличением веса. Допустим у нас есть один селектор в правиле, но нам нужно увеличить приоритет стилей, при этом не добавляя каких-то дополнительных селекторов. Сделать это можно просто продублировав селектор или добавишь селектор атрибута или псевдо-класса:

.class.class { color:blue; } /* сильнее чем .class */
.class { color:red; }

img[src] {  } /* вес = 11 */

Приоритет @media

Медиа правила @media ( max-width:500px ){ } не участвуют в подсчете приоритета (веса).

Поэтому они всегда должны располагаться ниже всех остальных правил, чтобы перебивать предыдущие правила с таким же весом (приоритетом).

Правильно:

.section { width:100%; }

@media ( max-width:500px ) {
	.section { width:50%; }
}

Неправильно:

@media ( max-width: 500px ) {
	.section { width:50%; }
}

.section { width:100%; }