Приоритеты CSS-селекторов

Часто на собеседованиях на позицию фронтенд-разработчика или верстальщика любят давать задачки, где нужно определить как будет выглядеть тот или иной html-элемент, после применения сложных CSS селекторов. У опытных разработчиков, как правило, включается интуиция, основанная на собственных решениях и задачах. У начинающих и вовсе возникает ступор при виде сложных конструкций.

Ясное дело (я надеюсь), что современный подход БЭМ-методологии (или просто соглашение внутри команды) исключает подобные головоломки в реальных приложениях, но ход рассуждений потенциального кандидата в таких задачах дает возможность оценить уровень его понимания материала.

Но оказывается существует очень простой способ, запомнить который просто и самое интересное, что описан-то он в спецификации W3C.

Я постараюсь изложить суть своим языком.

Итак, по сути существует 4 шага:

  • Посчитать количество селекторов #ID (и запомнить это число как A);
  • посчитать количество селекторов .класса, [атрибутов], и :псевдо-классов (и запомнить как B);
  • посчитать количество селекторов ТИПА и ::псевдо-элементов в селекторе (и запомнить как C);
  • игнорировать универсальный селектор.

Замечание! Нужно просто запомнить, что все, что находится внутри псевдо-класса :not(вот здесь), считается по этим же правилам, но при этом сам псевдо-класс :not() считать не нужно. Просто игнорируем его.

А теперь соединяем полученные А-B-C вместе и смотрим какое число в результате получилось. Чем больше число, тем больше его вес.

##Примеры

1
2
3
4
5
6
7
8
9
*               /*a=0, b=0, c=0     =>  вес = 0     */
UL /*a=0, b=0, c=1 => вес = 1 */
UL LI /*a=0, b=0, c=2 => вес = 2 */
UL OL+LI /*a=0, b=0, c=3 => вес = 3 */
H1 + *[REL=up] /*a=0, b=1, c=1 => вес = 11 */
UL OL LI.red /*a=0, b=1, c=3 => вес = 13 */
LI.red.level /*a=0, b=2, c=1 => вес = 21 */
#x34y /*a=1, b=0, c=0 => вес = 100 */
#s12:not(FOO) /*a=1, b=0, c=1 => вес = 101 */