К вопросу об эволюции CSS-селекторов

Артемий Ломов

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

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

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

Первые две спецификации вне исторического контекста обсуждать уже нет смысла — ну, по крайней мере, с момента долгожданного формального утверждения CSS2.1 в статусе рекомендации . Спецификация Selectors Level 3, между тем, уже тоже стабильная рекомендация — . Первый рабочий черновик (Working Draft) спецификации Selectors Level 4 опубликован в один день с утверждением Selectors Level 3 в статусе рекомендации. Пока что спецификация селекторов четвертого уровня находится в стадии активной разработки — судя по свежему варианту ее редакторского черновика (Editor’s Draft), следующую версию рабочего черновика ждут существенные изменения.

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

Русскоязычное название Примеры Название в CSS2.1 Название в CSS3 Название в CSS4
Простой селектор
  • div — по типу элемента («по тегу»)
  • * — универсальный
  • [foo="bar"] — по атрибуту
  • .content — по классу
  • #intro — по идентификатору
  • :hover — по псевдоклассу
A simple selector A simple selector A simple selector
Последовательность простых селекторов или составной селектор div.content:hover A sequence of simple selectors A compound selector
Комбинированный селектор
  • div p
  • .menu > a:hover
  • h1 + p
A chain of simple selectors separated by combinators A chain of sequences of simple selectors separated by combinators A complex selector
Список селекторов h1, h2, h3 A group of selectors A selector list

Тот факт, что одна и та же сущность носит названия “a simple selector” и “a compound selector” в разных редакциях спецификации, уже занятен, не правда ли?..

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

Еще хотелось бы обратить внимание на то, что в спецификации Selectors Level 3 изменился синтаксис псевдоэлементов — с тем, чтобы очевидным образом разграничить собственно псевдоэлементы (по сути своей являющиеся элементами, не представленными самостоятельно в DOM-дереве) и псевдоклассы (выделяющие по тем или иным признакам подмножества элементов, являющихся реальными узлами DOM). Псевдоэлементы отныне требуется предварять двумя подряд символами двоеточия (::), а не одним, как прежде. Это условие должно строго выполняться для всех новых псевдоэлементов, тогда как в целях обеспечения совместимости с ранее созданными сайтами браузеры должны поддерживать старый вариант синтаксиса в отношении всех псевдоэлементов, описанных в CSS2.1.

К слову, пока что никаких новых псевдоэлементов не придумали — на текущий момент полный список псевдоэлементов выглядит давно знакомым: ::first-line, ::first-letter, ::before и ::after (можно и с одним двоеточием, да).