Новые спецификации CSS-селекторов
Привычные нам CSS-селекторы 3 уровня стали рекомендацией W3C еще в 2011-м (почти одновременно с CSS2.1), а черновик селекторов 4 уровня был опубликован еще в 2013-м и очень долго не менялся. Но на этой неделе рабочая группа CSS спохватилась и показала, что работа над селекторами не заброшена. С перерывом в два дня обе спецификации обновились: 30 января — старая, а 1 февраля — новая.
В старой спецификации фактически исправлена лишь одна ошибка (применимость селекторов вида :nth-*
к корневому элементу). Но поскольку из-за этой ошибки пришлось менять набор тестов к спецификации и заново проверять, как его проходят браузеры, формально ее «понизили в статусе» до кандидата в рекомендации. Впрочем, это уже неважно — основная работа идет над селекторами 4 уровня.
Новый же черновик переработан почти до неузнаваемости — все статьи про новые селекторы, ссылающиеся на версию 2013 года, можно выбрасывать. Изменилась терминология, сам язык спецификации стал точнее и строже. Даже те, кто вместе с нами следили за новинками редакторского черновика и его первыми реализациями в браузерах, найдут в новой редакции немало сюрпризов.
Активизацию работы над селекторами во многом подтолкнуло недавнее решение разработчиков Chrome реализовать (вслед за Safari) некоторые из новых селекторов — как минимум, :matches()
. Как часто бывает, в последний момент у многих стали появляться идеи дальнейший улучшений, и прямо сейчас на Гитхабе обсуждается (порой с жаром) немало ишью про селекторы. В частности, пока так и не придумали названия новому аналогу :matches()
с нулевой специфичностью. Так что если не хотите, чтобы в браузерах навеки закрепилось неудачное, на ваш взгляд, решение — присоединяйтесь и выдвигайте свои аргументы, именно сейчас они могут оказаться определяющими. А мы постараемся и дальше держать вас в курсе текущих новоCSSтей и знакомить с самыми интересными новинками, так что следите за нашими обновлениями!
P.S. Это тоже может быть интересно:
Учитывая, что всякие CSSNext и т.п. раскрывают `:matches()` в отдельный селекторы, а не `:-*-any()`, то, непонятно, зачем вообще нужен `:something()`?.. Тем более, что есть еще `:is()` (аль как там его сейчас называют?), который, в теории, может сбрасывать эту саму специфичность у чего угодно. Safari, с одной стороны, подтолкнул всех к принятию решения, выкатив поддержку `:matches`, но, с другой стороны, прошло уже несколько лет и теперь это только проблем создает из-за уже имеющейся реализации.
:something() и :is() — это одно и то же. Название :is() не прижилось, а подходящей для всех замены пока не придумали. Вот для текущего черновика и поставили название-заглушку, по которому сразу понятно, что оно временное и его надо заменить на что-то нормальное:)
Да, `is` / `as` / `when` (который почему-то у всех ассоциируется со временем %), видимо. из-за селекторов времени к субтитрам) и прочие. На самом деле из всего обсуждения мне больше всего понравилось именно ваше предложение: https://github.com/w3c/csswg-drafts/issues/2143#issuecomment-354832935. Возможно, его стоит проработать с точки зрения синтаксиса (`:matches(as as 0,0,0)` (тег `as` вполне себе может существовать)), но плюс в том, что можно ввести поддержку `:matches()` уже сейчас, позже добавив вторую часть из предложения Таба. Осталось только решить, будет ли добавлять сам `matches()` себя к специфичности селектора, аль растворится по аналогии с тем, как это происходит когда его «растворяет» препроцессор.
В обсуждении на Github’е многие оперируют тем, что очень сложно в наши дни что-то переименовать, так как есть реализация в Safari, поддержка инструментами разработки, различные пособия, книги и прочее, где описан именно `:matches()`. Но это никогда не было стандартом, крайне мало используется и, в любом случае, можно объявить устаревшим, добавив новое имя, более простое (короткое) и с большими возможностями, чтобы не иметь `:matches()`, который по-разному работает в разных браузерах. Как правильно заметили, градиенты умудрились переименовать имея поддержку во всех браузерах, хоть это и было кощунством по мнению Таба, но это прошло вполне себе безболезненно. Непонятно, что мешает сделать тоже самое и с `:matches()`, у которого поддержка 0.0000n?..
А как же ссылка? :)
https://www.w3.org/TR/selectors-4/
Упс! Спасибо, действительно упустил!
(Но нам всё равно, думаю, лучше следить за редакторским черновиком, https://drafts.csswg.org/selectors-4/ — именно туда вносятся актуальные исправления, и именно на него ориентируются разработчики браузеров. Публикация в TR скорее ценна как индикатор того, что консорциум снова всерьез взялся за селекторы, не «забил» на них:)
Спасибо, буду иметь в виду.
https://bugs.chromium.org/p/chromium/issues/detail?id=568705 — вот, собственно, и ответ Blink’а. `:matches()` со сложными селекторами внутри (в Canary работает). Попробовал, к специфичности ничего не прибавляет. Теперь баг закрыт, ожидаем в Stable-ветке.
Ого! Оперативно, ай да Виктория Су! Но теперь поменять определение в спеке будет еще труднее:)
У разработчиков Blink’а свое видение:
https://www.chromestatus.com/feature/5445716612743168
https://www.chromestatus.com/feature/4600991135563776
Но, мало ли, друг все же они обращают внимание на дискуссии в Github.
Справедливости ради, с блинковской страницы для :is ссылка на редакторский черновик ведет на раздел, который сейчас озаглавлен этим временным :something. Думаю, они оставили :is просто как исторически первое название для этой штуки, и скорее всего поменяют у себя, когда новое название (хоть какое-нибудь) утвердят.
То есть, разработчикам ближе обнулять специфичность, чем задавать её явно, вроде div:matches(#foo, as 0, 1, 0, .bar as 1, 0, 0) {…} ?
Разработчикам браузеров, видимо, это действительно проще. Явно указывать очень соблазнительно, но пока не очень понятно как…
Есть ещё пару моментов, которые хотелось бы прояснить:
возможность применять больше/меньше и больше равно/ меньше равно в медиавыражениях планируют применять?
Будут ли использовать переменные не только в блоке деклораций, но и для селекторов? (в частности, в тех же медиавыражениях)
Ну и такая, в принципе, простая вещь, как использование двойных скобок (по-сути — одинарных, поскольку скобки, для записи условий, это — синтаксис, правило оформления, и они не несут в себе основную функцию скобок — группировку).
Что-нибудь вроде такого:
(min-width: 800px) and (min-width: 50em) and ((max-width: 1000px), (max-width: 62.5em))
Без скобок это почти что бессмыслица, как минимум max-width из второго условия, нивелирует min-width из первого.
А со скобками получается следующее: при изменении браузерного шрифта в любую сторону, из двух минимумов или двух максимумов, будет выбрано наибольшее (если в em шире чем в пикселях, то будут использоваться em, если в пикселях шире — то пиксели).
Немного меняем, получаем наименьшее:
((min-width: 800px), (min-width: 50em)) and (max-width: 1000px) and (max-width: 62.5em)
Зачем выбирать наименьшее, сходу придумать сложно, а вот где выбирается большее из двух значений, вероятно может пригодится, если часть элементов (например графических) задано в пикселях, а часть — в em (шрифты и их отступы, например).
Тогда мы можем быть уверенными что при изменении браузерного шрифта ничего не уедет(можно конечно всё жёстко задавать в пикселях, но если мы хотим оставить пользователю менять не только масштаб целиком, но и шрифты, то такую возможность нужно предусмотреть в коде).
Ну это, понятно, пример, можно не согласиться, что это целесообразно, но смысл именно тот, что в выражении медиазапросов, появляется гибкость…