GrabDuck

Будущее поколение CSS-селекторов: Уровень 4

:

16 июня 2015

Будущее CSS-селекторов также кажется светлым благодаря спецификации селекторов 4 уровня, которая сейчас находится на этапе рабочего проекта, и редакторского проекта той же спецификации, который пока еще находится в процессе (редакторский проект в основном рассматривается как более авторитетный).

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

:read-only и :read-write

Эти селекторы довольно очевидны. Любой элемент, который пользователь может редактировать, находится в состоянии read-write (чтение-запись). В остальных случаях элемент находится в состоянии read-only (только чтение).

Посмотрите на следующий код HTML:

<input type=\"text\" readonly>
<input type=\"text\" disabled>
<input type=\"text\">
<div contenteditable></div>

А теперь давайте рассмотрим его в CSS:

:read-only {
  outline: solid 1px blue;
}
:read-write {
  outline: solid 1px red;
}

Вот подробное описание того, что этот CSS делает по отношению к HTML:

  • Первые два элемента будут иметь синие рамки, так как они установлены в HTML как readonly (только чтение) и disabled (отключен) соответственно;
    • Третий элемент будет иметь красную рамку, потому что его можно редактировать (read-write чтение-запись), как и все поля ввода по умолчанию. Элемент textarea будет таким же;
    • Последний элемент (div) будет иметь красную рамку из-за свойства contenteditable.

В CSS я использую эти селекторы универсально (т.е. не применяя их к определенным элементам). Это означает, что красные рамки будут применяться ко всем элементам div, span и прочим изначально нередактируемым элементам. Более вероятно, что они будут использоваться в отдельных элементах форм, или элементах с определенным классом, если быть более точным.

Псевдо-класс :read-write указывается в редакторском проекте как at-risk, поэтому его могут удалить.

Поддержка браузеров для :read-only и :read-write

Chrome, Opera, Firefox, Safari.

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

Псевдо-класс опции по умолчанию: :default

Псевдо-класс :default подбирает элементы, которые определяются как по умолчанию по отношению к набору, частью которого они являются. Например, элемент button является по умолчанию кнопкой отправки формы или стандартным выбранным элементом в наборе переключателей. Также у вас может быть несколько элементов по умолчанию в одной группе, как показано в этом сниппете HTML:

<input type=\"checkbox\" value =\"f\" name=\"group\" checked> Fruits
<input type=\"checkbox\" value =\"v\" name=\"group\"> Vegetables
<input type=\"checkbox\" value =\"m\" name=\"group\" checked> Meats
<input type=\"checkbox\" value =\"p\" name=\"group\" checked> Poultry
<input type=\"checkbox\" value =\"n\" name=\"group\"> Nuts
<input type=\"checkbox\" value =\"b\" name=\"group\"> Breads

А теперь давайте совместим этот HTML со следующим CSS:

input[type=checkbox]:default {
  outline: solid 1px hotpink;
}

В данном случае все элементы со свойством checked будут обведены рамкой.

Поддержка браузеров для :default

Chrome, Opera, Firefox, Safari.

Как показано в демо, браузеры WebKit/Blink не создают рамку вокруг чекбоксов по умолчанию , даже несмотря на то, что должны это делать. Это похоже на баг. А вот Firefox ведет себя правильно.

Псевдо-классы допустимости: :valid и :invalid

Эти псевдо-классы полезны в HTML-формах, так как они дают визуальные подсказки что касается допустимости данных, вводимых пользователями, что обычно делается с помощью JavaScript.

В качестве примера, если в вашей форме есть следующее поле:

Email: <input type=\"email\" required>

Обратите внимание, что поле требует, чтобы введенные данные были допустимым адресом электронной почты. Дальше вы можете сделать следующее:

input[type=email]:invalid {
  outline: red solid 1px;
}
input[type=email]:valid {
  outline: lightgreen solid 1px;
}

В приведенном выше CSS поле ввода адреса электронной почты будет очерчено красной рамкой еще до того, как пользователь начнет что-то вводить. Как только пользователь введет допустимый адрес, рамка станет зеленой.

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

Несколько примечаний по этим селекторам:

  • Интересно, что допустимость также можно применять к самому элементу формы, отображая, верны ли все поля;
    • Это не работает на общих элементах, таких как div или p, так как у этих элементов нет возможности указывать ожидаемые форматы данных;
    • Стандартный тип ввода text , который не требует определенного формата, будет valid (допустимым) по умолчанию, но станет invalid (недопустимым), если на нем будет установлено свойство required.

Поддержка браузеров для :valid и :invalid

Все браузеры, включая IE10+.

Псевдо-классы диапазона: :in-range и :out-of-range

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

Так, ваш HTML будет выглядеть подобным образом:

<input type=\"date\"
min=\"1994-01-01\" max=\"2015-03-01\"
value=\"1993-01-01\">

Обратите внимание на значение по умолчанию 1993-01-01 , которое выходит за рамки допустимого диапазона. После этого вы можете оформлять ввод динамичным образом, основываясь на данных по умолчанию или любых введенных данных, например, таким образом:

input[type=date]:in-range {
  outline: lightgreen solid 1px;
}
input[type=date]:out-of-range {
  outline: red solid 1px;
}

Несколько замечаний по этим селекторам:

  • Их можно использовать для таких типов ввода, как number, datetime, datetime-local, month, week, и любых других, которые допускают диапазоны.
    • Технически они также работают с типом ввода range (диапазон), но я не думаю, что есть возможность сделать такой элемент out of range (вне диапазона), поэтому возможность использовать их в этом случае ограничена.
    • Что касается остальных псевдо-классов, эти селекторы будут работать только на тех элементах, у которых есть возможность определять допустимый диапазон.

Поддержка браузеров для :in-range и out-of-range

Opera, Chrome, Firefox, Safari.

Псевдо-классы опциональности: :required и :optional

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

<div>
  <label for=\"name\">name:</label>
  <input type=\"text\" id=\"name\" required>
  <span class=\"msg\"></span>
</div>
<div>
  <label for=\"email\">Email:</label>
  <input type=\"email\" id=\"email\" required>
  <span class=\"msg\"></span>
</div>
<div>
  <label for=\"address\">Address:</label>
  <input type=\"text\" id=\"address\">
  <span class=\"msg\"></span>
</div>

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

input:required ~ .msg:after {
  content: '*';
  color: red;
}
input:optional ~ .msg:after {
  content: '(optional)';
}

Здесь используется общий одноуровневый комбинатор для добавления красной звездочки рядом с каждым обязательным полем и добавляю слово optional (опционально) в круглых скобках рядом с каждым необязательным полем.

Здесь используются добавленные мной дополнительные элементы. Если вы предпочитаете не использовать дополнительные элементы, вы можете либо добавить их динамически с помощью JavaScript, или применить стиль непосредственно к самому полю ввода. Но учтите, что нельзя использовать псевдо-элементы с полями ввода формы, поэтому в таком случае вам придется применять другой тип стилей.

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

Все браузеры.

Нечувствительные к регистру селекторы свойств: i

В CSS по умолчанию селекторы свойств чувствительны к регистру. Таким образом, например, если вы выбираете все элементы со значениями href, которые заканчиваются на pdf , значения href, которые заканчиваются на PDF (верхний регистр), выбираться не будут.

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

a[href$=\"pdf\" i] {
  color: red;
}

Теперь селектор свойства будет выбирать все ссылки href, указывающие на PDF-файлы, вне зависимости от того, написано ли расширение .pdf в нижнем, верхнем или даже смешанном регистре.

Поддержка браузеров для нечувствительных к регистру селекторов свойств:

Opera

Псевдо-класс :blan

Псевдо-класс :blank это что-то вроде более красивого брата :empty, о котором я рассказывал в прошлой статье. Благодаря :empty вы можете выбирать элемент, основываясь на том, что в нем нет дочерних элементов, будь то элементы, текстовые узлы или даже узлы пробелов. Поэтому, благодаря :empty элемент не будет считаться пустым, даже если содержит один пробел и ничего больше.

Псевдо-класс :blank, однако, выбирает элемент, если в нем нет текста или других дочерних элементов, вне зависимости от пробелов. Поэтому он может содержать пробелы, разрывы строки и пр., и при этом все равно будет подходить.

Вот небольшой пример HTML:

<p></p>
<p> </p>

Обратите внимание, что первый элемент абзаца полностью пуст, а во втором есть один знак пробела. Вот CSS:

p:blank {
  outline: solid 1px red;
}
p:empty {
  border: solid 1px green;
}

В данном случае мы применяем красную рамку к элементам blank , и зеленую рамку к элементам empty . Псевдо-класс :empty выберет только первый элемент, потому что он полностью пустой. Псевдо-класс :blank подойдет к обоим, так как они оба пустые в отношении текста и элементов. Возможно, запомнить разницу будет довольно сложно, так как названия звучат слишком похоже, поэтому в спецификации это указывается как проблема. Поэтому, возможно, что название этого селектора изменят. Также, как указывается в спецификации, существует аналогичная версия этого селектора только для Mozilla.

Поддержка браузеров для :blank

Нет

Псевдо-класс подбора элементов: :matches()

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

В примере, взятом из MDN, у вас может получиться следующий поверхностно-многословный CSS, который будет пытаться оформить стили для главных заголовков, помещенных в различные контексты:

section section h1, section article h1,
section aside h1, section nav h1,
article section h1, article article h1, 
article aside h1, article nav h1,
aside section h1, aside article h1,
aside aside h1, aside nav h1,
nav section h1, nav article h1, 
nav aside h1, nav nav h1, {
  font-size: 20px;
}

Благодаря :matches() это можно упростить до:

:matches(section, article, aside, nav)
:matches(section, article, aside, nav) h1 {
  font-size: 20px;
}

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

Примечания по :matches():

  • В спецификациях, поддерживаемых префиксами -moz- и -webkit-, это называлось :any.
    • Как указывает CSS-Tricks, принцип здесь похож на вложении селекторов в препроцессорах.
    • Аргумент селектора должен быть простым селектором (т.е. он не может быть псевдо-элементом и он не может использовать другой комбинатор, кроме дочернего).

Поддержка браузеров для :matches()

Нет, хотя в WebKit/Blink и Mozilla есть собственные аналоги.

Псевдо-класс отношений: :has()

Псевдо-класс :has похож на .has() в jQuery , но имеет более широкие возможности. Покажем на примерах, что он может. Обратите внимание на комментарии в этом коде, которые объясняют, что выбирает каждый пример:

/* Элементы раздела, которые включают footer */
section:has(footer) {
  background: #ccc;
}
/* Любой элемент, содержащий элемент p с классом \"alert\" */
:has(p.alert) {
  background-color: red;
}
/* элемент img с абзацем, который идет сразу за ним. */
img:has(+p) {
  color: red;
}
/* элемент списка с ul в качестве непосредственного дочернего элемента */
li:has(> ul) {
  color: red;
}

Как вы видите, название has (имеет) не то же самое, что contains (содержит) (что описывает, как работает метод jQuery); также оно может означать имеет в качестве непосредственного дочернего элемента , имеет определенный элемент, следующий за ним и пр.

Примечание: Псевдо-класс :has входит в редакторский проект, но не входит в рабочий проект. Также этот селектор можно использовать только через JavaScript (вроде querySelectorAll), но не с CSS. См. Dynamic vs Static Selector Profiles (Динамические и статические профили селекторов) в спецификациях.

Поддержка браузеров для :has()

Нет.

Псевдо-класс гиперссылок: :any-link

Этот селектор работает как упрощение оформления любого элемента, который может принимать свойство href. Он включает элементы a, area и link. Его также можно использовать в качестве общего упрощения для следующего:

:link, :visited {
  color: #555;
}

То есть, вместо этого, вы напишете следующее:

:any-link {
  color: #555;
}

Но, как уже говорилось, это может также действовать на другие элементы, а не только на анкоры (a), поэтому пользу этого селектора может быть трудно уловить.

Следует отметить, что рабочий проект включает селектор под названием :local-link, который удалили из редакторского проекта.

Поддержка браузеров для :any-link

Chrome, Opera и Firefox (с префиксами разработчиков).

Псевдо-класс фокуса на обобщенный ввод: :focus-within

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

Вот небольшой пример HTML:

<div>
  <label for=\"email\">Email:</label>
  <input type=\"email\" id=\"email\">
</div>

Таким образом, вы можете написать следующий CSS:

input:focus-within {
  outline: yellow solid 1px;
}

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

Поддержка браузеров для :focus-within

Нет.

Псевдо-класс перетаскивания: :drop и :drop()

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

Селектор :drop позволяет создавать стиль для области отпускания (места, где элемент отпускается) в течение времени, пока пользователь перетаскивает (или несет) элемент, который он отпустит.

.spot {
  background: #ccc;
}
.spot:drop {
  background: hotpink;
}

Приведенный выше CSS применит нейтральный серый фон для элемента .spot, пока пользователь его не тянет. Но когда пользователь начнет тащить элемент .spot, фоновый цвет изменится и будет таким, пока элемент не отпустят.

Чередующийся синтаксис :drop() принимает одно или несколько из следующих значений ключевых слов:

  1. active: Отображает текущую цель размещения перетаскиваемого элемента.
    1. valid: Отображает, допустима ли цель размещения по отношению к перетаскиваемому элементу (например, если цель принимает только файлы, остальные элементы будут недопустимы)
    2. invalid: В противовес предыдущему, позволяет вам оформлять цель размещения, если она недопустима по отношению к перетаскиваемому элементу.

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

Важные примечания:

  • Версия рабочего проекта спецификаций включает абсолютно другой набор псевдо-классов, поэтому эти классы пока еще в состоянии изменения.
    • Синтаксис drop() является рисковым, поэтому его могут удалить.

Поддержка браузеров для :drop и :drop()

Нет.

Приз зрительских симпатий

Кроме описанных выше функций, существует еще несколько новых, которые я не буду описывать подробно, но которые тоже следует упомянуть:

  • Комбинатор столбцов (||), для определения отношений между ячейками и столбцами в таблицах и сетках.
    • Псевдо-классы :nth-column() и :nth-last-column() для выделения отдельных столбцов в таблицах и сетках.
    • Селектор узлов атрибутов attr(), который является первым селектором не для элементов.
    • Альтернативная версия наследованного комбинатора, представленная >> (вместо простого символа пробела)
    • Псевдо-класс :user-error для оформления поля, в которое пользователь ввел неверные данные.
    • Пространства имен, определенные правилом at @namespace.
    • Псевдо-класс :dir(), который позволяет выбирать элементы, основываясь на их направленности (например, ltr).
    • Псевдо-класс :scope, который представляет область или ориентир для выбора элементов.
    • Временные псевдо-классы :current, :past и :future для фокусирования на элементы в процессе изменения времени, например, субтитры в видео-записях.
    • Псевдо-класс :placeholder-shown для оформления замещающего текста в элементах формы.