Расчет значения специфичности. Понимание веса CSS-селекторов. Селекторы Классов. CSS

Скачать на Телефон 13.04.2019

Допустим, у Вас есть несколько селекторов которые ссылаются на один и тот же элемент:

Открыв HTML страницу где элемент span находится внутри элемента div мы увидим подчеркнутый текст. А если мы пойдем дальше и с помощью плагина Firebug посмотрим стили вложенного элемента, мы увидим следующее:

Div span { text-decoration:underline; } span { text-decoration:none; }

Сразу же возникает вопрос о причине такого поведения. Ведь второй селектор должен перекрывать первый учитывая каскадность стилей. Данный пример как нельзя четко показывает что такое специфичность селекторов.

Правила специфичности

Специфичность селекторов (selector"s specificity) определяет их приоритетность в таблице стилей. Чем специфичнее селектор, тем выше его приоритет.

В спецификации по CSS 2.1 этой теме посвящен небольшой раздел. Существует 4 правила по которым вычисляется специфичность селекторов:

  1. Самый высокий приоритет имеет атрибут style . Это правило перекрывает все селекторы описанные в стилях.
  2. Второе место занимает присутствие ID в селекторе(#some-id).
  3. Далее идут все атрибуты(в том числе и атрибут class ) и псевдоклассы(pseudo-classes) в селекторе.
  4. Самый низкий приоритет у селекторов с именами элементов и псевдоэлементами(pseudo-elements).

Все 4 правила сводятся в одну систему a-b-c-d (где а - наивысший приоритет) и образуют специфичность.

Селектор Специфичность a-b-c-d Правило №
* 0-0-0-0 -
li 0-0-0-1 4
li:first-line 0-0-0-2 4
ul li 0-0-0-2 4
ul ol+li 0-0-0-3 4
form + * 0-0-1-1 3, 4
table tr td.second 0-0-1-3 3, 4
h2.block.title. 0-0-2-1 3, 4
#xyz 0-1-0-0 2
style=" " 1-0-0-0 1

Пример специфичности - правило №1:

content

Текст внутри элемента p будет отображаться синим цветом независимо от селектора с айди(id), где также указано свойство color со значением red . Правило номер 1 всегда перекрывает все селекторы и имеет наивысшую приоритетность.

Правило №2:

  • first
  • second

Несмотря на то что селектор с id указан в стилях сверху, именно он повлияет на отображение документа, так как более специфичен нежели селектор с классом second .

Правило №3:

Текст внутри поля ввода будет отображаться жирным, а второй селектор определит стили только для кнопки отправки запроса.

Вернемся к первому примеру этой статьи - правило №4:

div span { text-decoration:underline; } span { text-decoration:none; }

Первый селектор выигрывает у второго потому что включает в себя 2 последних правила специфичности, в то время как второй - всего одно. Чтобы убрать декорирование текста в данном случае следует использовать класс или более специфичный селектор:

Div span { text-decoration:underline; } body span { text-decoration:none; }

Теперь селекторы имеют одинаковый вес(0-0-0-2 = 0-0-0-2) касательно специфичности. Второй селектор просто перекроет свойство первого так как описан ниже.

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

Вот и все о чем я хотел рассказать. Надеюсь, что статья была вам интересна.

--
Владислав Razor Чапюк, апрель 2009

Как и любая моя статья, эта начинается с введения. Дабы не говорить на разных языках, начнём с самых основ в мире CSS, то есть с терминологии. Чувствую себя преподавателем в университете - как же это круто.

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

Селектор - это строка, представляющая собой формальное описание структуры, на основе которого выбирается элемент или группа элементов в дереве документа и применяется объявленный блок свойств.

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

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

Вес селекторов

Нет, здесь не идёт речь об их реальном весе (его нет), а также о количестве символов. Такой вес нельзя измерить весами, так как он не вещественен в обычном понимании и вообще не существует в нашем с вами мире людей. Зато он есть в виде нулей и единиц. Получается, что селектор можно взвесить, используя некую систему, о которой мы и будем говорить дальше.

Что такое вес селектора?

Вес селектора - это условные четыре позиции x, x, x, x , которые заполняются нулями и единицами в соответствии с содержимым селектора. Каждая из позиций имеет своё содержимое:

  • Инлайн стили
  • Идентификаторы
  • Классы, атрибуты и псевдоклассы
  • Теги и псевдоэлементы

Как это читать?

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

Как заполнять?

H1 { color: #777; }

В этом примере селектором выступает заголовок h1 , который состоит из одного тега. Получается, что напротив столбца «тег» мы ставим единичку. Получается следующая картина: 0, 0, 0, 1 .

Всё это замечательно, но в реальных проектах встречается разве что в ядре стилей или normalize , а это значит, что нужно усложнить задачу.

#main .container article.post > header h1.giga { color: #777; }

Пример получился хардкорнее, чем предыдущий и в реальной жизни достоин премии «самого избыточного селектора». Такая избыточность должна преследоваться по закону, но подробнее на эту тему мы поговорим в отдельной части статьи. Окей, вернёмся к примеру и немного поработаем весами.

Давайте начнём слева, так как в начале стоит единственный идентификатор #main . Далее мы видим три класса.container , .post и.giga , а также три тега article , header и h1 . Для ещё большей наглядности я распишу это в виде этапов:

// Селектор #main .container article.post > header h1.giga // Начальный вес 0, 0, 0, 0 // Идентификаторы #main 0, 1, 0, 0 // Классы, атрибуты и псевдоклассы.container 0, 1, 1, 0 .post 0, 1, 2, 0 .giga 0, 1, 3, 0 // Теги и псевдоэлементы article 0, 1, 3, 1 header 0, 1, 3, 2 h1 0, 1, 3, 3 // Итог #main .container article.post > header h1.giga => 0, 1, 3, 3

Давайте напишем какой-нибудь безбашенный селектор, который я, надеюсь, никогда не увижу ни у кого в коде:

// Селектор body.page-posts #main .container article.post ul.list-unstyled > li:first-child h2.article-title:hover { color: #333; } // Начальный вес 0, 0, 0, 0 // Идентификаторы #main 0, 1, 0, 0 // Классы, атрибуты и псевдоклассы.page-posts 0, 1, 1, 0 .container 0, 1, 2, 0 .post 0, 1, 3, 0 .list-unstyled 0, 1, 4, 0:first-child 0, 1, 5, 0 .article-title 0, 1, 6, 0:hover 0, 1, 7, 0 // Теги и псевдоэлементы body 0, 1, 7, 1 article 0, 1, 7, 2 ul 0, 1, 7, 3 li 0, 1, 7, 4 h2 0, 1, 7, 5 // Итог body.page-posts #main .container article.post ul.list-unstyled > li:first-child h2.article-title:hover => 0, 1, 7, 5

Ну и напоследок, для полного понимания темы, будет пример с атрибутами и псевдоэлементами.

// Селектор.main:before { content: "3 .column.size-1of3"; } // Начальный вес 0, 0, 0, 0 // Идентификаторы 0, 0, 0, 0 // Классы, атрибуты и псевдоклассы.main 0, 0, 1, 0 0, 0, 2, 0 // Теги и псевдоэлементы:before 0, 0, 2, 1 // Итог.main:before => 0, 0, 2, 1

Вот такие вот дела.

На самом деле, тема очень простая, но очень важная на практике для посредственного (минимального) понимания того, как браузер определяет какой блок объявлений необходимо применить к тому или иному элементу на странице.

А что, если вес селекторов одинаковый?

Допустим, что у вас есть два или несколько селекторов так или иначе указывающих на один и тот же элемент. И вот так сложилось, что вы посчитали или просто взглянули на них, и вес оказался одинаковым. Не стоит отчаиваться, просто блок объявлений последнего селектора в вашем CSS-коде из этой группы и будет применяться к элементу. Как-то так. Мне кажется это логичным. Прямо как в поговорке «кто не успел, тот опоздал», но наоборот: «кто опоздал, тот и успел».

Зачем это нужно?

Это очень интересный момент, ибо понять какой блок объявлений будет применяться к элементу, можно и без расчёта веса селектора, то есть просто посмотрев на него и слегка подумав. Однако, глазомер может подвести, а вот машина не подведёт, посчитает вес и испортит вёрстку. Ошибка, конечно, не машины, а прослойки между компьютером и стулом, но это уже совсем другая история.

Ещё одним применением такого вот расчёта являются сервисы или скрипты, которые строят диаграммы специфичности CSS. Это может быть очень удобно для анализа и оценки избыточности вашего кода.

Интересным фактом будет то, что единственный раз, когда мне приходилось считать вес селектора, был тестом от Mail.ru на какой-то сертификат. Если интересно, то я поищу этот тест у себя в истории.

Ох, специально для вас у меня есть сервис, на который я наткнулся при подготовке к изложению этого материала: Specificity Calculator - это простой и эффективный калькулятор веса селекторов.

Специфичность селекторов

Раз уж зашла речь про вес CSS-селекторов, то неизбежно задумываешься о том, как бы его оценить: когда нужно ему худеть, а когда наоборот - поправляться. Как и у человека, у селекторов всё таки есть оптимальный вес.

Так сложилось, что многие веб-разработчики считают оптимальной специфичностью селекторов три вложения. Максимальной специфичностью селекторов называется пять вложений и рекомендуется стараться это число не превышать. Разумеется, вложений может быть и больше, так как в жизни всякое бывает. Хотя, лучше всего, если вы всё таки будете соблюдать эту рекомендацию хотя бы косвенно. Такой подход вам поможет сэкономить время в будущем.

Хорошо, всё это замечательно, но причём тут вес? - да очень просто, он напрямую от этого зависит. Чем больше вложений, тем больше вес. Логично, однако.

Оценить ваш CSS-код можно с помощью ресурса CSS Specificity Graph Generator . По предложенному вами CSS-коду строится интерактивный график специфичности вашего кода, на котором можно визуально определить проблемные участки ваших стилей.

Выводы

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

Аббревиатура CSS расшифровывается как Cascading Style Sheets (каскадные таблицы стилей), где одним из ключевых слов выступает «каскад». Под каскадом в данном случае понимается одновременное применение разных стилевых правил к элементам документа - с помощью подключения нескольких стилевых файлов, наследования свойств и других методов. Чтобы в подобной ситуации браузер понимал, какое в итоге правило применять к элементу, и не возникало конфликтов в поведении разных браузеров, введены некоторые приоритеты.

Ниже приведены приоритеты браузеров, которыми они руководствуются при обработке стилевых правил. Чем выше в списке находится пункт, тем ниже его приоритет, и наоборот.

  1. Стиль браузера.
  2. Стиль автора.
  3. Стиль пользователя.
  4. Стиль автора с добавлением!important.
  5. Стиль пользователя с добавлением!important.

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

Как задавать пользовательский стиль рассказывалось в (см. рис. 1.3 и 1.4).

!important

Ключевое слово !important играет роль в том случае, когда пользователи подключают свою собственную таблицу стилей. Если возникает противоречие, когда стиль автора страницы и пользователя для одного и того же элемента не совпадает, то !important позволяет повысить приоритет стиля или его важность, иными словами.

При использовании пользовательской таблицы стилей или одновременном применении разного стиля автора и пользователя к одному и тому же селектору, браузер руководствуется следующим алгоритмом.

  • !important добавлен в авторский стиль - будет применяться стиль автора.
  • !important добавлен в пользовательский стиль - будет применяться стиль пользователя.
  • !important нет как в авторском стиле, так и стиле пользователя - будет применяться стиль пользователя.
  • !important содержится в авторском стиле и стиле пользователя - будет применяться стиль пользователя.

Синтаксис применения !important следующий.

Свойство: значение!important

Вначале пишется желаемое стилевое свойство, затем через двоеточие его значение и в конце после пробела указывается ключевое слово !important .

Повышение важности требуется не только для регулирования приоритета между авторской и пользовательской таблицей стилей, но и для повышения специфичности определенного селектора.

Специфичность

Если к одному элементу одновременно применяются противоречивые стилевые правила, то более высокий приоритет имеет правило, у которого значение специфичности селектора больше. Специфичность это некоторая условная величина, вычисляемая следующим образом. За каждый идентификатор (в дальнейшем будем обозначать их количество через a) начисляется 100, за каждый класс и псевдокласс (b) начисляется 10, за каждый селектор тега и псевдоэлемент (c) начисляется 1. Складывая указанные значения в определённом порядке, получим значение специфичности для данного селектора.

* {} /* a=0 b=0 c=0 -> специфичность = 0 */ li {} /* a=0 b=0 c=1 -> специфичность = 1 */ li:first-line {} /* a=0 b=0 c=2 -> специфичность = 2 */ ul li {} /* a=0 b=0 c=2 -> специфичность = 2 */ ul ol+li {} /* a=0 b=0 c=3 -> специфичность = 3 */ ul li.red {} /* a=0 b=1 c=2 -> специфичность = 12 */ li.red.level {} /* a=0 b=2 c=1 -> специфичность = 21 */ #t34 {} /* a=1 b=0 c=0 -> специфичность = 100 */ #content #wrap {} /* a=2 b=0 c=0 -> специфичность = 200 */

Встроенный стиль, добавляемый к тегу через атрибут style , имеет специфичность 1000, поэтому всегда перекрывает связанные и глобальные стили. Однако добавление !important перекрывает в том числе и встроенные стили.

Если два селектора имеют одинаковую специфичность, то применяться будет тот стиль, что указан в коде ниже.

В примере 19.1 показано, как влияет специфичность на стиль элементов списка.

Пример 19.1. Цвет списка

HTML5 CSS 2.1 IE Cr Op Sa Fx

Список

В данном примере цвет текста списка задан зелёным, а второй пункт списка с помощью класса two выделен красным цветом. Вычисляем специфичность селектора #menu ul li - один идентификатор (100) и два тега (2) в сумме дают значение 102, а селектор .two будет иметь значение специфичности 10, что явно меньше. Поэтому текст окрашиваться красным цветом не будет. Чтобы исправить ситуацию, необходимо либо понизить специфичность первого селектора, либо повысить специфичность второго (пример 19.2).

Пример 19.2. Изменение специфичности

/* Понижаем специфичность первого селектора */ ul li {...} /* Убираем идентификатор */ .two {...} /* Повышаем специфичность второго селектора */ #menu ul li {...} #menu .two {...} /* Добавляем идентификатор */ #menu ul li {...} .two { color: red !important; } /* Добавляем!important */

Добавление идентификатора используется не только для изменения специфичности селектора, но и для применения стиля только к указанному списку. Поэтому понижение специфичности за счёт убирания идентификатора применяется редко, в основном, повышается специфичность нужного селектора.

Вопросы для проверки

1. Какая специфичность будет у селектора table.forum tr:hover p?

2. Какая специфичность будет у селектора #catalog .col3 .height div?


Chris Coyier

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

В качестве примера возьмем обычный неупорядоченный список, представляющий три вида напитков:


  • Whiskey

  • Beer

  • Cola

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


  • Whiskey

  • Beer

  • Cola

Favorite {
color: olive;
font-weight: bold;
}

Осталось лишь посмотреть на результат работы этого кода. Но увы, мы не получили ожидаемого эффекта – текст выбранного нами напитка (Whiskey ) не будет выделен и отображается также, как и остальные элементы списка. В чем же дело?

Возможной причиной возникшей проблемы может быть другое правило, которое определено в том же CSS документе, имеющее следующий вид:

ul#drinks li {
color: black;
font-weight: normal;
font-size: 13px;
}

Именно это CSS правило содержит определения, препятствующие визуальному выделению желаемого элемента списка. В используемом документе находится два различных CSS селектора, применяемых к одному элементу (.favorite и ul#drinks li ), которые предусматривают различные значения для цвета и толщины шрифта, содержащегося в нем текста. Что касается размерности шрифта, то здесь все понятно – рассматриваемый код содержит лишь одно выражение, определяющее его значение ( font-size: 13px ), поэтому именно оно и будет использоваться. Проблема, в данном случае, заключается в том, что браузер должен определить, какому из конфликтующих правил отдать предпочтение в процессе обработки документа. Как раз для этих целей и предназначены значения CSS специфичности каждого из правил.

Большинство проблем возникает у начинающих веб-разработчиков, которые не понимают, по какому принципу производится выбор рабочего правила. Они, как правило, предполагают, что приоритетом должен обладать селектор .favorite , так как он находится ниже в структуре CSS кода или потому, что определение атрибута class="favorite" в HTML разметке документа находится ближе к текстовому содержимому интересующего нас элемента страницы (

  • ). Но все это, конечно же, заблуждения.

    Да, действительно, CSS спецификацией предусмотрено, что положение правила в структуре кода имеет значение. И то из них, которое расположено ниже, действительно обладает приоритетом, но только в том случае, если значения специфичности рассматриваемых выражений одинаковы. Вот пример:

    Favorite {
    color: olive;
    }
    .favorite {
    color: black;
    }

    В этом случае цвет шрифта выбранного элемента списка будет черным (*поскольку последнее правило переопределяет значение первого ). Но мы немного отклонились от темы.

    Здесь работает несколько иной принцип. Всякий раз, когда вы формируете селектор для CSS правила, всегда делайте его настолько специфичным (конкретным), насколько это возможно и оправданно. (*Для этого необходимо применять более сложные селекторы ). При рассмотрении простейшего примера, приведенного выше, вы, вероятно, сами догадались, что использование лишь имени класса .favorite для селектора, выбирающего требуемый напиток из списка, будет недостаточным. И это не позволит извлечь из общего списка «нужный напиток» для его дальнейшего форматирования. А если это все-таки каким-то образом сработало один раз, то нет никакой гарантии, что в будущем все пройдет так же гладко. Для достижения желаемого результата необходимо использовать более конкретный селектор:

    ul#drinks li.favorite {
    color: olive;
    font-weight: bold;
    }

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

    html body div#content ul#dirnks li.favorite {
    color: olive;
    font-weight: bold;
    }

    Такой селектор тоже допусти́м, но он слишком «захламляет» CSS код, что значительно снижает его читабельность. К тому же от такой избыточности нет никакого толку. Существует и другой способ «вычленения» требуемого элемента, путем повышения значения CSS специфичности селектора .favorite при помощи декларации ! important :

    Favorite {
    color: olive! important;
    font-weight: bold! important;
    }

    Использование декларации ! important является универсальным методом задания приоритетности CSS правилам. И с его помощью вы сможете принудительно переопределить назначенные ранее свойства элемента, но этот метод является радикальным и в некоторых случаях его использование не оправданно.

    Если использовать ключевое слово ! important не по назначению, то можно лишь усложнить себе задачу. В том случае, когда вы хорошо знакомы с определенным CSS кодом и знаете, для каких целей используется каждый, содержащийся в нем селектор, то применение декларации ! important вполне оправдано для упрощения структуры кода и повышения его читабельности. Но если же вы применяете его с целью быстрого переопределения свойств, предусмотренных другим автором, не вникая в структуру кода и принципы его работы, то это может привести к нежелательным последствиям.

    Один из классических примеров, которые я использую:

    Last-block {
    margin-right: 0! important;
    }

    Я применяю данный класс в тех случаях, когда на странице имеется несколько «плавающих» блоков (установленным свойством float , в данном случае со значением left ), которые размещаются в один ряд. При этом, назначая это имя класса для последнего в ряду блока (самого правого), я полностью исключаю ситуацию, когда он неплотно прилегает к границе контейнера, что в моем случае недопустимо. Даже если где-то в структуре CSS кода, в рамках правила с более специфичным (конкретным) селектором определены другие значения свойства margin-right для используемых блоков, то применение класса .last-block к крайним элементам позволит обнулить их. При этом мы не используем никаких дополнительных составляющих селектора, конкретизирующих его, что упрощает представление кода.

    Подсчет значения CSS специфичности.

    Рассматривая предыдущий пример, мы с вами выяснили, что наша первая попытка определения цвета и жирности шрифта для элемента списка провалилась из-за того, что мы использовали селектор лишь с одним именем класса, который имеет меньшее значение CSS специфичности и был переопределен селектором, выбирающим неупорядоченный список по его идентификатору ID, который имеет большее значение специфичности. Ключевыми значениями в данном случае являются имена классов (class) и идентификаторы элементов (ID). Очень важно знать, что CSS стандарты предусматривают существенные различия в весовых значениях специфичности для селекторов классов class и идентификаторов ID. Селекторы, использующие идентификаторы элементов, имеют безупречное преимущество над теми, в которых применяются лишь имена классов. При любом количестве имен классов в селекторе, он будет переопределен другим селектором, имеющим в своем составе один идентификатор элемента.

    Теперь давайте схематически рассмотрим метод определения и записи значений CSS специфичности селекторов:

    Другими словами:

    • Если в теге элемента предусмотрен атрибут style , то все определенные в его рамках свойства имеют максимальный приоритет (значение специфичности в этом случае получает высший разряд – 1,0,0,0 ).
    • Для каждого идентификатора элемента, используемого в рамках селектора прибавляется единица в соответствующий разряд специфичности – 0,1,0,0 .
    • Каждое имя класса, а также псевдокласса или селектор атрибута (* element ), присутствующий в селекторе правила добавляет единицу в следующий разряд специфичности – 0,0,1,0 .
    • И последний, самый младший разряд, получает по единице за каждое, присутствующее в селекторе имя элемента – 0,0,0,1 .

    Вы можете избавиться от запятых и преобразовать значения CSS специфичности в более привычную для вас форму представления значений – обычные числа: 1,0,0,0 можно представить как 1000 , что значительно больше значения 0,1,0,0 или 100 . Используемые в этом случае запятые предназначены для четкого разделения значений различных разрядов специфичности. К примеру, если в CSS селекторе используется 13 имен классов, псевдоклассов и/или селекторов атрибутов (что маловероятно), то значение специфичности в этом случае может принять вид 0,1,13,4 , что невозможно представить в десятичном виде.

  • Директива ! important , следующая непосредственно за определенным CSS свойством, априори придает максимальное значение его специфичности. Она отменяет действие даже тех свойств, которые указаны в inline -атрибуте "class" тега элемента. Единственный способ переопределения свойства с директивой ! important — это создание нового правила, содержащего то же свойство и декларацию ! important , которое находится ниже в CSS коде. К тому же, второе правило должно иметь равное или большое значение специфичности, чем первое (которое необходимо отменить). Другими словами, для директивы ! important можно определить еще один разряд в значении специфичности – 1,0,0,0,0 , хотя такой ее записи, конечно же, не существует.
  • * Исчерпывающую информацию по декларации ! important можно прочесть .

    * Примечание переводчика.

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

    Конечно, чтобы результат применения для тебя был предсказуем, ты должен научиться видеть, какое из правил одержит верх. Пришла пора разобраться, как рассчитывается специфичность.

    Как это выглядит

    Специфичность представляет собой группу из четырех чисел. Например, 0,0,0,0 или 0,0,1,2.

    Как подсчитать специфичность

    Специфичность считается по селектору. Правила подсчета очень просты:

    • каждый присутствующий в селекторе идентификатор добавляет к специфичности 0,1,0,0;
    • каждый класс, псевдокласс или атрибут добавляет к специфичности 0,0,1,0;
    • каждый элемент или псевдоэлемент добавляет к специфичности 0,0,0,1;
    • универсальный селектор и комбинаторы не учитываются.

    Давай закрепим полученные знания и поупражняемся в расчете специфичности.

    P {/*какие-то определения */} div p {/*какие-то определения */} p.note {/*какие-то определения */} form.feedbackForm input {/*какие-то определения */} #conten a:hover {/*какие-то определения */}

    Превая строка — одинокий селектор типа. Специфичность 0,0,0,1.

    Вторая строка — два селектора типа. Специфичность 0,0,0,2.

    Теретья строка — селектор типа и класса. Специфичность 0,0,1,1.

    Четвертая строка — два селектора типа, один класса и один атрибута. Специфичность 0,0,2,2.

    Пятая строка — селектор идентификатора, типа и псевдокласс. Специфичность 0,1,1,1.

    Кто победил?

    Сравниваются специфичности очень просто. Какое число больше, то определение и выиграло.

    Например:
    0,0,1,4 больше, чем 0,0,1,2.
    0,1,2,0 больше, чем 0,0,2,1.

    Учти, что первые (те, которые левее) числа всегда возьмут верх над последующими (более правыми). Они как бы находятся в более старшем разряде.

    Например, 0,1,0,0 больше, чем 0,0,8,9.

    Если тебе так удобнее, можешь мысленно отбросить запятые и рассматривать предыдущий пример, как 100>89. Только не запутайся, если какой-то из разрядов специфичности будет больше девяти (что может быть при сильно навороченном селекторе). Например, если получилась специфичность 0,1,10,14, запятые отбрасывать нельзя, а то все разряды попутаются.

    Специфичность и объявления

    Специфичность относится как бы не ко всему правилу в целом, а к каждому конкретному объявлению. Поэтому, может получиться что правило «отработает» не полностью. Например:

    Подопытный текст

    Div { color: #0f0; /* Специфичность 0,0,0,1. */ font-weight: bold; /* Специфичность 0,0,0,1. */ } .box { font-weight: normal; /* Специфичность 0,0,1,0. */ }

    Объявление из строки 2 для элемента

    отработает нормально, а объявление из строки 3 будет перебито объявлением из строки 6 (так как у него больше специфичность). Текст внутри нашего div будет зеленым, но не жирным.

    Этот простейший пример показывает насколько важно уметь считать специфичности. Во первых, всегда можно составить правильный селектор, чтобы нужное мне объявление победило. Во-вторых, если какое-то объявление не отработало, ты сразу же поймешь, почему и сэкономишь массу времени на отладке.

    Обрати внимание, что специфичность селектора идентификатора (0,1,0,0) всегда выше, чем селектора атрибута (0,0,1,0). Даже если этот атрибут — ! Поэтому:

    Form.feedback input { color: #f00; /* Специфичность 0,0,2,2. */ } #name { color: #0f0; /* Специфичность 0,1,0,0. - победа! */ }

    Встроенные стили

    По идее, кто-то уже давно должен был спросить, а зачем, собственно, в специфичности самая первая цифра? Ведь мы ее до сих пор никак не использовали!

    Все верно. Первая цифра зарезервирована для встроенных стилей. Считается, что их специфичность равна 1,0,0,0. Таким образом, встроенный стиль всегда перебивает стиль заданный во внешней или вложенной таблице стилей. Например:

    Этот текст будет зеленым

    Даже использовав селектор идентификатора, мы не перебъем встроенный стиль.

    Div#box { color: #00f; /* Специфичность 0,1,0,1. - маловато */ }

    Это что же получается? На встроенные стили нет никакой управы?

    Не волнуйся. Конечно, есть способ перебить встроенные стили (а заодно и все остальные объявления).

    Объявление!important

    Если очень нужно, можно пометить какое нибудь объявление, как важное (important). Такое объявление будет считаться заведомо победившим при сравнивании специфичностей. Да, да, в том числе победившем и встроенные стили. Давай немного изменим CSS для предыдущего примера:

    Div { color: #00f !important; /* важное объявление - сразу победа! */ }

    Даже слабенький по специфичности (0,0,0,1) селектор типа перебил встроенный стиль, ведь его объявление теперь стало важным!

    Детали применения!important хорошо описаны в нашем CSS-справочнике . Если хочешь узнать подробности — перейди по ссылке .

    Теперь, вооружившись знанием о расчете специфичности можно продолжить изучение наследования в CSS.



    Рекомендуем почитать

    Наверх