Pull to refresh

Взвешиваем селекторы CSS

Reading time 4 min
Views 85K
Ближе к двум часам ночи в голову в месте с мыслями о вечном приходят не менее вечные вопросы — «в чём смысл жизни ?», «зачем вообще человеку спать ?» или «Какого чёрта эта #%^$ не работает ?» и чем ближе утро, тем сильнее начинает волновать именно этот самый последний вопрос.

Чуть ниже я расскажу о том какого чёрта сss селекторы иногда не ведут себя так, как нам кажется правильным, и о том как они на самом деле должны себя вести.


Глава один – идём направо!


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

Итак, взвешиваем — сначала представим пару рядов из 8 чисел:

0,1,0,0,0,0,0,0

1,0,0,0,0,0,0,0


Знакомьтесь — так в числах выглядят некоторые два селектора, чтобы никто ни о чем не догадался назову их условно «верхний» и «нижний»

Чтобы узнать какой из них тяжелее, нужно выполнить следующие действия и ничего не перепутать:
  1. Смотрим на крайние левые числа
  2. Выбираем из них большее. — именно этот селектор и будет самым тяжелым
  3. Если числа одинаковые, сдвигаемся на число вправо и повторяем инструкции из пункта 2.
  4. Если все числа одинаковые то применяются стили из селектора который был объявлен последним


Самая страшная тайна


Если вы это прочитаете, от вас навсегда уйдет душевный покой, но по крайней мере вы сможете спать по ночам.

Раскрывая самую страшную тайну я расскажу, как собственно превратить обычный селектор в такие понятные и красивые цифры? Всё как всегда очень просто:

  1. Теги. за каждый тег в селекторе можно накинуть в самое правое число единичку:

    a – это 0,0,0,0,0,0,0,1
    div a – это  0,0,0,0,0,0,0,2
    

  2. Классы, за каждый класс или псевдокласс в селекторе можно накинуть по единичке во второе число справа

    .head .logo – это  0,0,0,0,0,0,2,0
    .logo.big  –    0,0,0,0,0,0,2,0
    div:first-child – 0,0,0,0,0,0,1,1
    .logog > .big – и это тоже 0,0,0,0,0,0,2,0
    
    

    Да, вы все верно поняли. Css селектор плевать хотел на все эти ваши изыски типа пробелов или «>».
  3. За каждый ID в селекторе добавляем по единичке в третье справа число.

    #head – это  0,0,0,0,0,1,0,0
    #head  #logo –  тоже  0,0,0,0,0,2,0,0
    


Я думаю суть вы уловили, теперь можно приступать к небольшой викторине, чтобы это проверить:

Викторина


<head>
    <title></title>
    <style>
        span p
        {
            background-color: gray;
        }
        html p
        {
            background-color: red;
        }
    </style>
</head>
<body>
    <div>
        <span><p>?</p></span>
    </div>
</body>

Вопрос: Какого цвета бэкграунд будет в абзаце?
Ответ: Правильно, красного, потому что селектор не волнует что вам там кажется, и расстояние между тэгами его не интересует. А так как вес тэгов равен – применится последний.

<head>
    <title></title>
    <style>
        div.test1
        {
            background-color: gray;
        }
        div > .test1
        {
            background-color: yellow;
        }
        
        div .test1
        {
            background-color: red
        }
    </style>
</head>
<body>
<div>
    <div class='test1'>?</div>
</div>
</body>

Вопрос: Какого цвета бэкграунд будет в нашем диве?
Ответ: Правильно, красного, потому что при измерении веса глубоко все равно поставили вы там пробел между классами, знак больше или написали их вплотную. Вес у всех этих селекторов одинаковый, а значит применится последний.

<head>
    <title></title>
    <style>
        #id1 div
        {
            background-color: gray;
        }

        #id2
        {
            background-color: red
        }
    </style>
</head>
<body>
<div id="id1">
    <div id="id2">?</div>
</div>
</body>

Вопрос: Все тот же.
Ответ: А ответ, для разнообразия другой: наш див будет серым. Потому что как я уже упоминал выше селектору абсолютно безразлично что вы там имели ввиду. У первого селектора вес больше, и никого не волнует что скорее всего ожидали вы не такого поведения.

Продолжаем раскрывать секреты


У нас осталось еще так много чисел, и наверняка так хочется узнать что же все они значат – продолжаем раскрывать секреты.
  1. Селектор * абсолютно невесомый, то есть совсем.
  2. Селектор атрибутов это самый обычный псевдокласс и весит он столько же сколько и обычные классы
  3. Любой инлайновый стиль написанный в атрибуте style=”” элемента автоматически получает приоритет0,0,0,0,1,0,0,0, что сразу делает его очень крутым.
  4. А следующие четыре цифры это все наши старые знакомые только с атрибутом !important

    div
    {
        background-color: gray !important;
    }
    
    Имеет вес при определении свойства background-color -  0,0,0,1,0,0,0,0
    
    .header 
    {
        background-color: gray !important;
    }
    
    0,0,1,0,0,0,0,0
    
    


Все мы любим викторины


<head>
    <title></title>
    <style>
    a.class1
    {
        color: blue;
    }
    a[href="#"]
    {
        color: green;
    }
    a[href^="#"] 
    {
        color: red;
    }
    </style>
</head>
<body>
<a class="class1" href="#">?</a>
</div>
</body>


Вопрос: Какого цвета будет знак вопроса в ссылке?
Ответ: Красного, неважно что селектор на точное совпадение атрибута выглядит более специфичным, чем селектор который выбирает все что «начинается с». Вес они имеют одинаковый.

<head>
    <title></title>
    <style>
        #id1
        {
            background-color: gray !important;
        }
    </style>
</head>
<body>
<div id="id1" style="background-color: red;">?</div>
</body>


Вопрос: Мой оригинальный запатентованный вопрос.
Ответ: !important круче всего, даже круче чем инлайн стили – так что бам-бам-бам – серого!

Исходники всех тестов лежат тут

P.S. немного порно

<head>
    <title></title>
    <style>
        #id1
        {
            background-color: gray !important;
        }
    </style>
</head>
<body>
<div id="id1" style="background-color: red !important;">red</div>
</body>
Tags:
Hubs:
+44
Comments 39
Comments Comments 39

Articles