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

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

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

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

Таблица веса каждого элемента селектора:

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

Пример подсчета веса:

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

Сильные (по весу) стили заменяют слабые и элемент получает стили от самых «весомых» правил. Это и есть каскадность.

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

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

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

Еще примеры подсчета веса:

* {}                        /*  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 */

.foo {}                     /*  10 */
.foo[class] {}              /*  20 */
#t34 {}                     /* 100 */
#content #wrap {}           /* 200 */

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

  • продублировав селектор.
  • добавив селектор атрибута или псевдо-класса.
.class.class  { color:blue; } /* вес = 20 */
.class[class] { color:blue; } /* вес = 20 */
.class        { color:red; }  /* вес = 10 */

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%; }