Логика приоритета CSS

В этом примере:

http://jsfiddle.net/Ja29K/

<style>
  /* Default links */
  a {
    color: #0F0; /* Green */
  }

  /* Header links */
  #header a {
    color: #F00; /* Red */
  }

  /* Login link */
  #login {
    color: #00F; /* Blue */
  }
</style>

<header id="header">
  <p><a href="#">header link</a> is red</p>
  <p><a id="login" href="#">login link</a> is not blue</p>
</header>

Разве не логично, что ссылка для входа должна быть синего цвета?

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

Чтобы рассчитать специфичность селектора, я создал таблицу для каждого селектора:

A = количество встроенных стилей: 0
B = количество идентификаторов: 0
C = количество классов: 0< br> D = Количество элементов: 0

Таким образом, элемент входа имеет 3 коллизии, связанных с его цветом: a, #header a, #login

элемент (A, B, C, D)

a (0, 0, 0, 1) = 1
#header a (0, 1, 0, 1) = 101
#логин (0, 1, 0, 0) = 100

Селектор «#header a» выигрывает, потому что у него самый большой балл.

Но

Если мы изменим селектор "#login" на "a#login", мы получим:
a#login (0, 1, 0, 1) = 101
Селектор " #header a" проигрывает, потому что при ничьей побеждает последний, который был объявлен.

Итак, что я не могу понять:

Поскольку селектор «#header a» относится ко многим элементам, а селектор ID (например, #login) ссылается только на один элемент, логично, что мы хотим применить объявления селектора ID к этому элементу, верно? Я действительно не могу понять эту логику приоритета CSS, потому что я думаю, что селектор ID должен быть в основном наиболее конкретным из возможных, как и встроенные стили.

P.S.: Извините за мой плохой английский :)


person André Abreu    schedule 20.08.2012    source источник
comment
может быть связано или нет, но если у вас одинаковая специфика, всегда побеждает последний.   -  person Jawad    schedule 21.08.2012
comment
@ Джавад, ОП, знает это ... прочитай, плз ...   -  person Christoph    schedule 21.08.2012
comment
@ Кристоф: да, я вижу. Может быть, поэтому я только прокомментировал.   -  person Jawad    schedule 21.08.2012
comment
(0, 0, 0, 1) не равно 1, а (0, 1, 0, 1) не равно 101. Система специфичности работает иначе.   -  person BoltClock    schedule 29.09.2012


Ответы (6)


Вы не можете видеть «специфичность» в смысле того, какой селектор нацелен на наименьшее количество элементов, а просто в том, что является наиболее важным.

Конечно, можно было бы сделать правила еще более сложными, различая такие вещи, как #header a или a#login. Однако это только добавило бы путаницы во всю систему.
Также, скорее всего, этим (c/w) можно было бы злоупотреблять следующим образом: header#header a — это добавило бы более высокой специфичности, но также могло бы нацеливаться на большее количество элементов.

На мой взгляд, это не добавит ценности системе, а только усложнит ее.

При написании CSS всегда следует стараться, чтобы правила были как можно короче из-за проблем с производительностью. Если вам нужно перезаписать правило, у вас все еще есть возможность добавить еще один id или class — в дополнение к обычному каскадированию этого действительно более чем достаточно.

person Christoph    schedule 20.08.2012
comment
@chirstoph Не видит специфичности в том смысле, какой селектор нацелен на наименьшее количество элементов, но если существует один селектор, нацеленный только на один элемент, просто примените его! Так же, как встроенные стили :) - person André Abreu; 21.08.2012
comment
когда я говорю об одном селекторе, предназначенном только для одного элемента, я говорю об идентификаторе селектора. - person André Abreu; 21.08.2012
comment
@André Тег или селектор класса также могут быть нацелены только на один элемент, в зависимости от разметки. Поскольку всегда оцениваются все части селектора, ключевой селектор не имеет дополнительного веса в том, насколько конкретный селектор. Я согласен, иногда это раздражает, но это то, что определяет спецификация. - person Christoph; 21.08.2012
comment
Спецификация даже не определяет термин «ключевой селектор». Однако он определяет термин субъекта селектора, который похож, но не совсем такой же. - person BoltClock; 29.09.2012

Нет, по логике селекторов это не так.

#header a более конкретен, чем #login. Если вы уменьшите свой селектор #header a до #header, то селектор заголовка и селектор логина будут иметь одинаковую специфичность, и будет использоваться правило, которое было выражено последним (в вашем заказе цвет от логина). То же самое было бы верно, если бы вы увеличили специфичность селектора входа в систему, добавив к нему имя тега.

person devstruck    schedule 20.08.2012
comment
Еще одна лучшая практика — использовать #header #login в качестве последнего правила, чтобы оно отменяло правило #header a. - person behnam; 21.08.2012
comment
Проблема заключается в предположении, что селектор с одним идентификатором является более конкретным, чем селектор идентификатора тега. Селекторы должны иметь возможность работать независимо от того, как разработчик решит организовать свою DOM. Единственное, что знает браузер, это то, что и #login, и #header относятся к одному конкретному элементу DOM с отмеченным атрибутом id. #header a относится к подмножеству правила на основе идентификатора и, следовательно, является более конкретным, чем любое применимое (одиночное) правило на основе идентификатора. - person devstruck; 21.08.2012
comment
@AndréAbreu Не могли бы вы указать, где мой аргумент не может это объяснить? - person devstruck; 21.08.2012
comment
@AndréAbreu, потому что (1, 0, 1) больше, чем (1, 0, 0) по определению. - person behnam; 21.08.2012
comment
@André #login a более конкретен, чем #login, хотя последний может относиться только к одному элементу. Конкретная терминология подразумевает более строгое подмножество элементов, поэтому #login должно быть более конкретным. - person Christoph; 21.08.2012
comment
@post_erasmus Если у меня есть header#header a и a#login, браузеры знают, что a#login относится к элементу ссылки, но header#header a все равно выигрывает :) - person André Abreu; 21.08.2012
comment
@behnam Я знаю это, просто не могу понять, почему такая логика. - person André Abreu; 21.08.2012
comment
@AndréAbreu По вашей логике селектор для тега <body/> следует считать столь же конкретным, как и селектор идентификатора, потому что тег body может встречаться только один раз на странице. Однако, помимо определения того, к каким элементам модели DOM следует применить данное правило, селекторам все равно, какой тег, класс или идентификатор они используют для получения показателя специфичности. Это сделало бы реализацию CSS (как для разработчиков веб-сайтов, так и для разработчиков веб-браузеров) гораздо более сложной. При разработке систем, которые будут использоваться другими, простота и универсальность — это очень, очень хорошие вещи. - person devstruck; 21.08.2012
comment
@post_erasmus Спасибо за ваш комментарий. Я не думаю, что тег ‹body/› должен быть таким же конкретным, как селектор идентификатора. Селекторы идентификаторов предназначены для синглтонов, а селекторы тегов — нет (конечно, за исключением некоторых тегов, таких как тело). Я думаю, что селекторы ID должны иметь ту же силу, что и встроенные селекторы. Я думаю, что более сложно добавить больше веса (например, #login) к вашему селектору идентификатора, чтобы иметь приоритет, верно? Я согласен с вами, я знаю, что реализация CSS должна быть простой, как и все остальное, но я думаю, что это просто своего рода логика. - person André Abreu; 21.08.2012
comment
@Christoph: #login не ограничивается одним элементом. Он просто говорит о любом элементе с идентификатором login независимо от того, уникален он или нет. Поскольку #login a имеет сопровождающий его селектор типа, не совсем корректно говорить, что #login является более конкретным. Комбинаторы также не имеют отношения к специфичности (хотя иногда это подразумевается). - person BoltClock; 29.09.2012
comment
@post_erasmus: Правильно. Тип исходного документа совершенно не имеет значения при вычислении специфичности селектора, потому что мы говорим о селекторах CSS, а не HTML. Хотя верно то, что мы пишем селекторы и применяем правила, основанные на предположениях о структуре HTML, строго говоря, это не более чем предположения, тогда как технически природа исходного документа не имеет отношения к специфичности селекторов. - person BoltClock; 29.09.2012

Похоже, вы знакомы с концепцией специфичности, которая подробно описана как часть w3. css спецификации. С точки зрения алгоритма, значения специфичности селектора в объявлении правила являются взвешенными или непозиционными. Это означает, что #header a и a#login имеют одинаковую специфичность, а это означает, что если элемент подходит для обоих правил, последнее будет иметь приоритет.

Лично мне потребовалось гораздо больше времени, чтобы смириться с тем, что селекторы имеют семантическую специфичность, но не имеют вычислительной ценности. Например, ul li и ul>li имеют одинаковый вес, хотя последнее «кажется» более конкретным!

Я считаю, что любому, кто имеет опыт функционального программирования, проще сравнивать специфичность в виде четырехбайтных значений (на самом деле это близко к тому, как это реализовано в основных браузерах — значительно переполняет значение при использовании более 256 селекторов одинакового веса :)

person Oleg    schedule 20.08.2012

Это просто зависит от специфики - будьте более конкретными, и это сработает для вас:

header a#login {
 color: #00F; /* Blue */
}​
person Billy Moat    schedule 20.08.2012
comment
Или используйте !important :-) Хотя это помогает ситуации, на самом деле это не отвечает на вопрос. Идентификатор (#) - это, по сути, самая конкретная вещь из возможных. - person Imp; 21.08.2012
comment
@Imp !important — очень плохой выбор, и его не следует использовать в таблицах стилей. - person Christoph; 21.08.2012
comment
!important не нужно использовать вне таблиц стилей. Но в некоторых случаях это полезно. Например: если вы хотите, чтобы .required было красным в любом месте страницы, даже если более конкретный стиль окрашивает его в черный цвет. - person Blazemonger; 21.08.2012
comment
@Blazemonger хорошо, и тогда вам нужен один элемент, имеющий класс .require, чтобы иметь зеленый шрифт. Вы увеличиваете специфичность селектора, но ничего не происходит из-за начального !important, поэтому вы добавляете еще один !important, который ведет к другому важному, который ведет... в конце буквально каждое из ваших правил имеет !important, и вы возвращаетесь к точке, где вам просто нужно было написать чистый CSS в первую очередь. - person Christoph; 21.08.2012
comment
@ Кристоф Я не могу представить себе сценарий, подобный тому, который вы только что описали. - person Blazemonger; 21.08.2012

ОП, возможно, вы могли подумать, что CSS сначала обрабатывает первый аргумент (#header и #login), и только после этого обрабатывает второй аргумент (a в «#header a»).

Таким образом, в первом процессе он становится красным, а затем синим, но во втором процессе он заменяется красным из-за «а» во втором аргументе.

person Andrew G.    schedule 20.08.2012
comment
правила обрабатываются rtl и оцениваются все его части, поэтому то, что вы пишете, не правильно. - person Christoph; 21.08.2012
comment
Да, ты прав.. Сегодня узнал кое-что новое. Спасибо! css-tricks.com/efficiently-rendering-css - person Andrew G.; 21.08.2012

Все, что нужно, чтобы исправить это, — изменить #login на a#login, чтобы DOM знал, что эта команда специфична для ссылки.

#header a более конкретен, чем просто #login, потому что он указывает на конкретный элемент в DOM, а не просто на случайный идентификатор.

person Ammi J Embry    schedule 20.08.2012