CSS селекторы 4-го уровня
В этой статье рассказывается про селекторы 4 уровня в CSS, которые уже можно частично применять в разработке, про которые ещё мало кто знает и про те, которые только ожидают часа своего всеобщего признания. Но в любом случае знание и понимание этого материала значительно упростит ваш процесс работы как в настоящем, так и в будущем.
Селекторы это основная часть 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 года, однако, я оставил в покое некоторые селекторы, которые скорее всего исчезнут или изменятся, ну или если по ним вообще нет никакой информации, в том числе и о поддержки другими браузерами:
Но вам определенно нужно за ними следить, так же как и за другими селекторами 4-го уровня.