Подписывайтесь на мой твиттер, там всегда что-нибудь интересное!

CSS селекторы 4-го уровня

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

Перевод статьи CSS selectors level 4

Селекторы это основная часть CSS. Они дают вам возможность делать такие вещи, как например, выборка всех элементов определенного типа:

div {
  /* some styles to apply to all div elements */
}

Или вы можете выбрать элемент, который является замыкающим дочерним элементом своего родителя:

ul li:last-child {
  /* some styles to apply to only the last child of a list */
}

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

По факту, есть куда больше одного способа сделать это и куда более запутанные и сложные.

Для примера, сравним этот:

ul li {
  /* Styles to apply to all children */
}
ul li:last-child {
  /* Styles to reset the previous styles because they don’t apply to the last child */
}

С этим:

ul li:nth-last-child(n+2) { 
  /* Styles to apply to all children except the last one */
}

ul li это примеры селекторов первого уровня.

last-child и nth-last-child это примеры селекторов 3-го уровня.

Вы можете рассматривать уровни, как версии спецификаций CSS селекторов, в которых каждый уровень добавляет селекторы “помощнее”.

В этой статье я предоставлю вам обзор последнего поколения селекторов, а именно 4 уровня, в соответствии со спецификацией Editors’s Draft на январь 2019 года, по следующим категориям:

Логические комбинации
Селекторы атрибутов
Лингвистические псевдоклассы
Псевдоклассы положения
Пользовательские псевдоклассы
Псевдоклассы форм ввода
Древовидные псевдоклассы
Табличные селекторы

Во время написания, спецификация для селекторов 4 уровня находится в драфте. Ситуация может измениться, если они достигнут статуса официальной рекомендации и к своему сожалению, вы в итоге обнаружите, что многие селекторы либо не поддерживаются некоторыми браузерами или им нужен префикс с :-moz- или :-webkit-.

Для каждого селектора я дам ссылку на его Can I Use страничку, так что вы увидите какие браузеры его поддерживают (если это возможно), также дам краткое описание, пример и ссылку на Codepen, так что вы сможете попробовать его в действии (даже если он сейчас не работает, всё равно это может измениться в будущем).

Учитывая всё вышесказанное, давайте начнем с селекторов из категории логических комбинаций.

Логические комбинации

Эта категория включает в себя селекторы, которые комбинируют другие селекторы.

:not(selector1, selector2, …)

Поддержка браузерами

Этот селектор выделяет все элементы, кроме тех, которые не подходят по селекторам из списка, который представлен в виде аргумента. К примеру:

p:not(.beginning, .middle) {
  color: red;
}

Сделает все p элементы у которых нет классов beginning и middle красного цвета.

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

p:not(.beginning):not(.middle) {
  color: red;
}

:is(selector1, selector2, …)

Поддержка браузерами

Он выбирает элементы, которые подходят по выборке селекторов из списка аргументов. Для примера:

p:is(.beginning, .middle) {
  color: blue;
}

Сделает все элементы p у которых есть классы beginning и middle синим цветом.

Одним из самых примечательных изменений с последнего рабочего драфта является то, что селектор :matches() был переименован в :is() и убран из Safari (который был единственным браузером с его полной поддержкой), так что теперь он куда более совместимый со своей противоположностью, такой как :not().

:matches можно применять как алиас для :is(), если нужно для обратной совместимости. Хотя, :matches() ранее назывался :any(), так что многие браузеры поддерживают этот псевдокласс с префиксом:

p:-webkit-any(.beginning, .middle) {
  color: blue;
}

p:-moz-any(.beginning, .middle) {
  color: blue;
}

:where(selector1, selector2, …)

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

У него такой же синтаксис и функционал, как и у :is(), но ни сам селектор и ни какой из его аргументов влияют на его специфичность, которая всегда равна нулю.

Специфичность это “вес” CSS правила. Если два селектора применены к одному и тому же элементу, то выигрывает тот у которого наивысшая специфичность. Всё понятно. А если у нескольких правил одинаковая специфичность, то последнее правило в CSS будет применено к элементу.

Этот селектор можно использовать как фильтр или для перезаписи стилей связанных с элементом.

В спецификации приводится следующий пример:

a:not(:hover) {
  text-decoration: none;
}

nav a {
  /* Has no effect */
  text-decoration: underline;
}

/* With the new :where Level 4 selector */
a:where(:not(:hover)) {
  text-decoration: none;
}

nav a {
  /* Should work */
  text-decoration: underline;
}

:has(relativeSelector1, relativeSelector2, …)

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

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

p:has(strong, em) {
  color: red;
}

Тут всем элементам p, в которых есть <strong> или <em> теги, выставится красный свет.

Селекторы атрибутов

Эта категория включает в себя селекторы, которые работают с селекторами атрибутов.

[foo=”bar” i]

Поддержка браузерами

Этот селектор выберет тот элемент, чьё значение атрибута foo равно bar, вне зависимости от регистра.

Для примера:

p[class="text" i] {
  color: green;
}

Сделает зеленым всем элементы p, чей атрибут class имеет значения text, TEXT, text или другую комбинацию.

[foo=“bar” s]

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

Выбирает элемент, чью имя атрибута foo, точно соответствует bar, в соответствии с регистром.

Для примера:

p[class="text" s] {
  color: green;
}

Сделает зеленым все элементы p, у которых атрибут class имеет значение text (и не Text или тп).

Лингвистические псевдоклассы

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

:dir(ltr)

Поддержка браузерами

Выбирает элементы написанные слева направо, там где указана направленность написания. И напротив, :dir(rtl) выбирает элементы, которые написаны справа налево.

Для примера:

p:dir(ltr) {
  background-color: red;
}

Тут фоновый цвет выставится на красный всем элементам p, написанным слева направо.

:lang(zh, “*-hant”)

Поддержка браузерами. На время написания, версия 4-го уровня для этого селектора не поддерживалась ни одним браузером.

Выбирает элемент, отмеченный как китайский (или другой язык, просто поменяйте zh на нужный) или написанный традиционными китайскими символами (или любой другой системой символов, просто поменяйте *-hant на любой другой код символов)

На самом деле, этот селектор можно использовать с CSS2, однако, структуризация поиска по языку и разделение запятой в аргументах, являются нововведениями в селекторах 4-го уровня.

Этот селектор может принимать список из одного языка или диапазон языков, как аргумент. Если диапазон языков содержит звездочки, то они должны быть либо экранированы (:lang(es-\*)), либо указаны как строка (:lang("es-*")).

Для примера:

p:lang("*-CH") {
  background-color: red;
}

Выставит фоновый цвет красным, всем элементам p, в которых есть текст, написанный на одном из языков Швейцарии (CH указывает Швейцарию).

Псевдоклассы положения

Эта категория включает в себя селекторы, относящиеся к ссылкам.

:any-link

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

Этот селектор выделяет все элементы, у которых есть атрибут href (такие как <a> или <link>). Другими словами, все элементы, которые подходят псевдоклассам :link и :visited.

Для примера:

a:any-link {
  color: red;
}

Выдаст всем элементам a c атрибутом href, красный цвет.

:local-link

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

Этот элемент выбирает элементы, которые ссылаются на эту же страницу. Если ссылка включает в себя фрагмент настоящей ссылки, то она тоже подпадает под селектор. Если же нет, то фрагмент части ссылки настоящего URL не рассматривается.

Для примера:

a:local-link {
  text-decoration: none;
}

Этот селектор сделает все ссылки с атрибутом href, которые ссылаются на эту же страницу, без подчеркнутыми.

Пользовательские псевдоклассы (или user-action псевдоклассы)

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

:focus-within

Поддержка браузерами

Выбирает элементы, который либо подходят под псевдокласс :focus (когда элемент в фокусе), либо когда у них есть потомки, которые подходят под :focus.

Для примера, рассмотрим следующую форму:

<form>
<input type="text" id="name" placeholder="Enter your name" />
</form>

Она добавит рамку вокруг поля ввода при фокусе.

form:focus-within {
  border: 2px solid;
}

:focus-visible

Поддержка браузерами

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

Однако, разница с :focus довольно тонкая, но всё же есть.

Если :focus-visible что-то выбирает, то :focus делает это тоже, но на самом деле это не всегда так и зависит от браузера (включена ли у него отрисовка кольца фокуса) и того, как элемент попал в фокус (мышкой или клавиатурой).

У Firefox есть свой такой селектор, как псевдокласс :-moz-focusring.

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

/* Standard Level 4 selector */
:focus-visible {
  background-color: lightgray;
}

/* Level 4 selector for Firefox*/
:-moz-focusring  {
  background-color: lightgray;
}

Применится только к элементу, если на нем сфокусировались через клавиатурную навигацию (tabbing navigation).

Псевдоклассы форм ввода

Эта категория включает в себя селекторы, которые применяются к элементам имеющем отношение к формам ввода.

:read-write и :read-only

Поддержка браузерами

:read-write выбирает элементы, чьё значение можно изменить, такие каr <input> без атрибута readonly.

:read-only выбирает элементы, которые в свою очередь уже нельзя изменить, например тот же <input>, но с атрибутом readonly.

Однако, эти селекторы не просто выбирают элементы <input> или <textarea>, они выбирают любой элемент, который может быть отредактирован пользователем, например как <p> с атрибутом contenteditable со значением true.

К примеру:

:read-write {
  background-color: lightyellow;
}

:read-only {
  background-color: lightgray;
}

/* For Firefox */
:-moz-read-write {
  background-color: lightyellow;
}

:-moz-read-only {
  background-color: lightgray;
}

Тут фоновый цвет измениться для всех элементов, которые можно изменить и которые нельзя. На lightyellow и lightgrey, соответственно.

:placeholder-shown

Поддержка браузерами

Этот селектор выбирает элемент ввода, который в данный момент показывает текст плейсхолдера.

Для примера:

input:placeholder-shown {
  color: red;
}

Выставит красный текст плейсхолдеру элемента <input> (только для самого плейсхолдера).

:default

Поддержка браузерами

Выбирает элемент, который является дефолтной опцией в группе связанных элементов. Обычно он применяется к кнопкам и выбранным спискам/меню.

Для примера:

input:default {
  box-shadow: 0 0 2px 2px green;
}

input:default + label {
  color: green;
}

Задаст зеленую тень дефолтному <input> элементу и зеленый цвет его лейблу.

:indeterminate

Поддержка браузерами

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

Для примера:

input[type="radio"]:indeterminate + label {
  color: red;
}

Этот пример выдаст лейблам радио элементов в группе, красный цвет, в том случае, если в этой группе нет выбранных элементов.

:valid и :invalid

Поддержка браузерами

Они выделят элементы, чьё содержимое или значение, соответственно, валидное или наоборот, в соответствии с семантикой их валидности. Если семантика не определена (или не может быть определена), то элемент и не :valid, и не :invalid.

Пример для элемента ввода типа email:

input:invalid {
  color: red;
}

input:valid {
  color: green;
}

:in-range and :out-of-range

Поддержка браузерами

Эти селекторы применяются только к элементам, которые имеют диапазон ограничений, для примера, если у них может быть указанные минимум и максимум. Если же нигде нет таких ограничений, то элемент не является и не :in-range, и не :out-of-range.

К примеру, для <input> элемента с минимальным значением 1 и максимальным 5:

input:out-of-range {
  color: red;
}

input:in-range {
  color: green;
}

В некоторых случаях, эти селекторы будут иметь тот же эффект, что и :valid и :invalid.

:required and :optional

Поддержка браузерами для :required

Поддержка браузерами для :optional

Эти селекторы применяются к элементам формы, которые соответственно, required или optional, перед отправкой формы. Элементы, которые не являются элементами форм, являются ни чем иным, как ни тем и не другим.

Для примера:

input:optional {
  color: gray;
}

input:required {
  color: red;
}

Даст элементам с required красный цвет и опциональным элементам выдаст серый цвет.

Древовидные псевдоклассы

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

Поддержка браузерами (на момент написания, версия 4 уровня для этого селектора ничем не поддерживается).

:nth-child выбирает каждый элемент, который является N-ным дочерним элементом своего родителя. :nth-last-child делает то же самое, но ведёт счет с конца. Вы можете поиграться с :nth тестером, чтобы понять разницу и узнать больше об An+B обозначениях.

В самом начале этой статьи, я показал вам пример :nth-last-child и сказал, что это был селектор 3-го уровня. Однако, для 4-го уровня, этот селектор принимает опциональный of селектор, который отфильтровывает потомков по признаку, который подходит под этот селектор.

Вообще тут могут быть различия в том, как объявлен селектор. Для примера:

li.item:nth-child(-n+2)

Выберет первые два элемента li, но только если у них есть класс item.

Это не то же самое, что:

:nth-child(-n+2 of li.item)

Тут выберутся первые два <li> элемента, которые имеют класс item, даже если они не первые два потомка в списке.

Попробуйте (в браузере, который поддерживает этот селектор, таком как Safari):

Табличные селекторы

Эта категория включает селекторы, которые работают с колонками таблицы.

F | | E

На время написания, этот селектор вообще никем и ничем не поддерживался.

Селектор комбинирования колонок (||), выбирает элемент типа E, который представляет ячейку в таблице и принадлежит колонке, представленной элементом с типом F.

Для примера, рассмотрим следующую таблицу:

<table>
  <colgroup>
    <col span="2">
    <col class="selected">
  </colgroup>
  <tr>
    <th>ID</th>
    <th>Description</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>1</td>
    <td>Computer</td>
    <td>$999</td>
  </tr>
  <tr>
    <td>2</td>
    <td>Tablet</td>
    <td>$499</td>
  </tr>
</table>

Выдаст ярко-желтый цвет ячейкам (<td> элементам), которые относятся к selected колонке (price).

:nth-col(An+B) and :nth-last-col(An+B)

На время написания, этот селектор не поддерживается никем и ничем.

Вы можете рассматривать эти селекторы, как колоночную версию :nth-child и :nth-last-child.

:nth-col(An+B) выбирает элемент в гриде или таблице, который представляет собой ячейку колонки, у которой An+B-1 колонок перед ней, с любым положительным целым числом или нулевым значением n.

:nth-last-col(An+B) выберет элемент сетки или таблицы, который представляет собой ячейку колонки, у которой An+B-1 колонок после неё, с любым положительным или нулевым значением n.

Для примера:

col.nth-col(1) {
  background-color: lightyellow;
}

col.nth-last-col(1) {
  background-color: lightgreen;
}

Выдаст первой колонке таблицы светло-желтый фон, а также последней колонке выдаст светло-зеленый фон.

Заключение

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

Мы сейчас покрыли большинство селекторов указанных в Editor’s Draft спецификации на январь 2019 года, однако, я оставил в покое некоторые селекторы, которые скорее всего исчезнут или изменятся, ну или если по ним вообще нет никакой информации, в том числе и о поддержки другими браузерами:

:target-within

:scope

Временные псевдоклассы

:blank

:user-invalid

Но вам определенно нужно за ними следить, так же как и за другими селекторами 4-го уровня.