Pull to refresh

Что нового в CSS селекторах 4-го уровня?

Reading time 6 min
Views 61K
Это перевод поста "What's new in CSS selectors 4". Он показался мне интересным, и я решил перенести его на хабрахабр. P.S. Это мой первый перевод, не судите строго, и если увидите какие-то недочёты и ошибки — напишите пожалуйста в личку, я постараюсь исправить ошибки. Далее, со слов автора.

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

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

Так что же нас ожидает нового?


ПРОФИЛИ СЕЛЕКТОРОВ

CSS-селекторы отныне разделены на две группы: быстрая и полная. Быстрые селекторы — это те селекторы, которые подходят для динамического CSS-движка. Полная группа селекторов подходит для использования в тех ситуациях, в которых быстрая выборка данных не настолько важна, например, при использовании их через document.querySelector.

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


:HAS

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

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

// Любая секция, в которой есть заголовок
section:has(h1, h2, h3, h4, h5, h6)


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

// Выберем параграфы, которые не имеют чего-либо, не являющегося изображением
p
  :has(img)             // имеет изображение
  :not(:has(:not(img))) // не имеет внутри чего-либо, не являющегося изображением


Можно даже выбрать те элементы, которые имеют определённое количество потомков (в данном примере, пять):

// Сайдбар с пятью элементами внутри
div.sidebar
    :has(*:nth-child(5))       // Имеет пять потомков
    :not(:has(*:nth-child(6))) // Но не шестого


Предостережение: на данный момент, селектор :has не считается быстрым, что означает, что он может оказаться недоступен для использования в файлах стилей. Но, так как еще никто не реализовал на практике данный селектор, вопрос его производительности остаётся открытым. Если разработчики браузеров смогут сделать его реализацию быстрой, вполне возможно, что он будет доступен для использования как один из основных инструментов.

В предыдущей версии спецификации этот раздел был помечен восклицательным знаком и назывался «выбором субъекта селектора» — он имел другой синтаксис, который в настоящее время упразднён.

:MATCHES

:matches — это стандартизация :moz-any и :webkit-any, которая какое-то время присутствовала в браузерских префиксах. Это позволяет автору стиля объединить похожие правила. Например, это может быть полезно для объединения сгенерированного посредством SCSS/SASS вывода, вроде такого:

  body > .layout > .body > .content .post p a.image.standard:first-child:nth-last-child(4) ~ a.image.standard, 
  body > .layout > .body > .content .post p a.image.standard:first-child:nth-last-child(4), 
  body > .layout > .body > .content .post li a.image.standard:first-child:nth-last-child(4) ~ a.image.standard, 
  body > .layout > .body > .content .post li a.image.standard:first-child:nth-last-child(4), 
  body > .layout > .body > .content .page p a.image.standard:first-child:nth-last-child(4) ~ a.image.standard, 
  body > .layout > .body > .content .page p a.image.standard:first-child:nth-last-child(4), 
  body > .layout > .body > .content .page li a.image.standard:first-child:nth-last-child(4) ~ a.image.standard, 
  body > .layout > .body > .content .page li a.image.standard:first-child:nth-last-child(4) {
       ....
}

в несколько более поддающийся контролю вариант:
body > .layout > .body > .content 
    :matches(.post, .page) 
    :matches(p, li) 
    :matches(a.image.standard:first-child:nth-last-child(4), 
             a.image.standard:first-child:nth-last-child(4) ~ a.image.standard), 
       ....
}

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

:NTH-CHILD(AN+B [OF S])

В то время как :nth-of-type существует с начала тысячелетия, CSS-селекторы четвёртого уровня добавляют возможность произвести фильтрацию, основанную на селекторе:
div :nth-child(2 of .widget)

Селектор S используется для определения индекса, и он не зависит от селектора, находящегося слева от псевдо-класса. Как написано в спецификации, если вы заранее знаете тип элемента, селектор :nth-of-type может быть преобразован в :nth-child(… of S), подобно этому:
img:nth-of-type(2) => :nth-child(2 of img)

Разница между этим селектором и :nth-of-type небольшая, но она важна. Для :nth-of-type, каждый элемент — указали ли вы для него селектор, или же нет — имеет неявный индекс для себя среди своих собратьев с тем же именем тэга. Выражение :nth-child(n of S) создает новый счётчик каждый раз, когда вы используете новый селектор.

Это создаёт потенциал для возможных багов в новых селекторах. Так как селектор внутри псевдо-класса :nth-child не зависит от селектора слева от него, вы можете случайно пропустить часть вашего запроса, если укажете в левом селекторе всё как следует, но забудете указать всё необходимое внутри :nth-child. Например:
tr:nth-child(2n of [disabled])

Данное правило может не работать так, как вы ожидаете от него, если другие не-tr элементы будут иметь атрибут «disabled».

В прошлой версии спецификации данная возможность называлась как селектор :nth-match.

:NOT()

В то время, когда вы использовали какое-то время :not, теперь вы можете перечислить внутри него несколько аргументов, чтобы сохранить несколько байт и ввести:
// Эквивалентно следующему:
//    :not(h1):not(h2):not(h3)...
:not(h1, h2, h3, h4, h5, h6)


КОМБИНАТОР ПОТОМКОВ (>>)

Комбинатор потомков присутствует в CSS с самого начала в виде пробела ( ), но теперь он имеет явную версию:
// Эквивалентно следующему:
//    p img { ... }
p >> img { ... }

Причина добавления данного правила заключается в организации моста между прямым потомком (>) и оператором для прозрачного DOM (>>>).

КОМБИНАТОР СТОЛБЦА (||) И :NTH-COLUMN

CSS-селекторы четвёртого уровня добавляют операции со столбцами, которые позволяют разработчикам стилей более простым способом изменять дизайн определённых столбцов в таблице. Текущий подход в задании стилей для таблиц требует использования :nth-child, который не всегда совпадает со столбцами таблиц при использовании атрибутов colspan.

При использовании нового комбинатора столбца, вы можете задать стиль ячейкам таблицы, которые находятся в том же столбце, что и заданный элемент col:

// Следующий пример делает ячейки C, E и G жёлтыми
// (пример взят из спецификации CSS-селекторов 4-й версии)
col.selected || td {
  background: yellow;
  color: white;
  font-weight: bold;
}

<table>
  <col span="2">
  <col class="selected">
  <tr><td>A <td>B <td>C
  <tr><td colspan="2">D <td>E
  <tr><td>F <td colspan="2">G
</table>

Как альтернативный вариант, автор может использовать :nth-column и :nth-last-column для задания стилей ячейкам. В любом случае, если ячейка охватывает несколько столбцов, этот селектор затронет любой из них.

:PLACEHOLDER-SHOWN

Одно небольшое дополнение к языку селектора — это :placeholder-shown. Он соответствует input-элементу, если и только если он отображает текст из своего placeholder-атрибута.

:ANY-LINK

:any-link — это еще одно маленькое дополнение. Оно объявлено для соответствия любому из свойств :link или :visited.
// Эквивалентно следующему:
//    a:link, a:visited { ... } 
a:any-link { ... }


ВЫВОДЫ

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

Если у вас возникло желание поиграться с данными селекторами, вы должны дождаться, пока разработчики браузеров догонят спецификацию, или использовать некоторые ранние реализации. :matches доступна как :moz-any и :webkit-any, а ночные сборки WebKit'а имеют раннюю поддержку :nth-child селекторов через активацию по флагу.

Поскольку это черновой вариант, наименования псевдоклассов могут измениться без предупреждения. Следите за спецификациями для получения более подробной информации.
Tags:
Hubs:
+50
Comments 33
Comments Comments 33

Articles