Комплексные селекторы

Комментарии

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

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

CSS3 принёс новые селекторы, открывая целый новый мир возможностей и улучшений существующей практики. Здесь мы обсудим селекторы, как старые так и новые, а также как наилучшим образом их использовать.

Типовые селекторы

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

Селектор типа идентифицирует элемент, основанный на его типе, в частности, как этот элемент объявлен в HTML. Селектор класса идентифицирует элемент, основанный на значении атрибута class, который может повторно применяться к нескольким элементам по мере необходимости и помогает делиться популярными стилями. И, наконец, идентификатор определяет элемент, основанный на значении атрибута id, который является уникальным и должен быть использован на странице только один раз.

CSS

h1 {...}
.tagline {...}
#intro {...}

HTML

<section id="intro">
  <h1>...</h1>
  <h2 class="tagline">...</h2>
</section>
Обзор типовых селекторов
ПримерНазваниеОписание
h1Селектор типаВыбирает элемент по его типу.
.taglineКлассВыбирает элемент по значению атрибута class, который может быть использован повторно несколько раз на одной странице.
#introИдентификаторВыбирает элемент по значению атрибута id, который является уникальным и должен использоваться только один раз на странице.

Дочерние селекторы

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

Селектор потомка

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

Селектор article h2 является селектором потомка и выбирает только элементы <h2>, которые находятся внутри элемента <article>. Обратите внимание, независимо от того, где живёт элемент <h2>, пока он находится внутри элемента <article>, он всегда будет выбран. Кроме того, любой элемент <h2> за пределами элемента <article> не будет выбран.

Ниже приведены заголовки, из которых выбраны строки 3 и 5.

CSS

article h2 {...}

HTML

<h2>...</h2>
<article>
  <h2>Этот заголовок будет выбран</h2>
  <div>
    <h2>Этот заголовок будет выбран</h2>
  </div>
</article>

Прямой дочерний селектор

Порой селекторы потомка заходят слишком далеко, выбирая больше, чем хотелось бы. Иногда должны быть выбраны только прямые дети родительского элемента, а не каждый экземпляр элемента вложенный глубоко внутри предка. В этом случае может быть использован прямой дочерний селектор путём размещения знака больше (>) между родительским и дочерним элементом в селекторе.

Например, article > p является прямым дочерним селектором только когда элементы <p> находятся непосредственно внутри элемента <article>. Любой элемент <р> размещённый вне элемента <article> или вложенный внутри другого элемента, кроме <article>, не будет выбран.

Ниже, абзац на строке 3, является единственным прямым потомком его родителя <article>, поэтому и выбран.

CSS

article > p {...}

HTML

<p>...</p>
<article>
  <p>Этот абзац будет выбран</p>
  <div>
    <p>...</p>
  </div>
</article>
Обзор дочерних селекторов
ПримерНазваниеОписание
article h2Селектор потомкаВыбирает элемент, который находится в любом месте внутри определённого предка.
article > pПрямой дочерний селекторВыбирает элемент, который находится непосредственно внутри определённого родителя.

Родственные селекторы

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

Общий родственный селектор

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

Селектор h2 ~ p — это общий родственный селектор, он ищет элементы <p>, которые следуют после любых элементов <h2> в том же родителе. Чтобы элемент <p> был выбран, он должен идти после любого элемента <h2>.

Абзацы в строках 5 и 9 выбраны, поскольку они идут после заголовка в дереве документа и у них тот же родитель, что и у родственного заголовка.

CSS

h2 ~ p {...}

HTML

<p>...</p>
<section>
  <p>...</p>
  <h2>...</h2>
  <p>Этот абзац будет выбран</p>
  <div>
    <p>...</p>
  </div>
  <p>Этот абзац будет выбран</p>
</section>

Соседние селекторы

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

Взглянем на соседний селектор h2 + p. Будут выбраны только элементы <p> идущие непосредственно после элементов <h2>. У обоих также должен быть один и тот же родительский элемент.

Абзац на строке 5 выбирается, так как непосредственно следует после его родственного заголовка и у них один общий родительский элемент.

CSS

h2 + p {...}

HTML

<p>...</p>
<section>
  <p>...</p>
  <h2>...</h2>
  <p>Этот абзац будет выбран</p>
  <div>
    <p>...</p>
  </div>
  <p>...</p>
</section>

Пример соседних селекторов

HTML

<input type="checkbox" id="toggle">
<label for="toggle">&#9776;</label>
<nav>
  <ul>
    <li><a href="#">Главная</a></li>
    <li><a href="#">О нас</a></li>
    <li><a href="#">Услуги</a></li>
    <li><a href="#">Контакты</a></li>
  </ul>
</nav>

CSS

input {
  display: none;
}
label,
ul {
  border: 1px solid #cecfd5;
  border-radius: 6px;
}
label {
  color: #0087cc;
  cursor: pointer;
  display: inline-block;
  font-size: 18px;
  padding: 5px 9px;
  transition: all .15s ease;
}
label:hover {
  color: #ff7b29;
}
input:checked + label {
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
  color: #9799a7;
}
nav {
  max-height: 0;
  overflow: hidden;
  transition: all .15s ease;
}
input:checked ~ nav {
  max-height: 500px;
}
ul {
  list-style: none;
  margin: 8px 0 0 0;
  padding: 0;
  width: 100px;
}
li {
  border-bottom: 1px solid #cecfd5;
}
li:last-child {
  border-bottom: 0;
}
a {
  color: #0087cc;
  display: block;
  padding: 6px 12px;
  text-decoration: none;
}
a:hover {
  color: #ff7b29;
}
Обзор родственных селекторов
ПримерНазваниеОписание
h2 ~ pОбщий родственный селекторВыбирает элемент, который следует в любом месте после предыдущего элемента, и оба элемента имеют одного общего предка.
h2 + pСоседний селекторВыбирает элемент, который следует непосредственно после предыдущего элемента, и оба элемента имеют одного общего предка.

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

Некоторые рассмотренные ранее типовые селекторы также могут быть определены как селекторы атрибутов, в котором элемент выбирается на основе значения class или id. Эти селекторы атрибутов class и id широко используются и довольно мощные, но это лишь начало. Другие селекторы атрибутов появились в последние годы, в частности, сделали большой скачок вперед вместе с CSS3. Теперь элементы могут быть выбраны на основе того, присутствует ли атрибут и какое значение он содержит.

Селектор наличия атрибута

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

CSS

a[target] {...}

HTML

<a href="#" target="_blank">...</a>

Селектор атрибута =

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

CSS

a[href="http://google.com/"] {...}

HTML

<a href="http://google.com/">...</a>

Селектор атрибута *=

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

CSS

a[href*="login"] {...}

HTML

<a href="/login.php">...</a>

Селектор атрибута ^=

В дополнение к выбору элемента на основе того, что значение атрибута содержит указанный текст, можно также выбрать элемент, основанный на том, с чего начинается значение атрибута. Использование символа циркумфлекса (^) в квадратных скобках селектора между именем атрибута и знаком равенства означает, что значение атрибута должно начинаться с указанного текста.

CSS

a[href^="https://"] {...}

HTML

<a href="https://chase.com/">...</a>

Селектор атрибута $=

Противоположностью предыдущего селектора является селектор атрибутов, где значение оканчивается определённым текстом. Вместо использования символа ^ применяется знак доллара ($) в квадратных скобках селектора между именем атрибута и знаком равенства. Использование знака доллара означает, что значение атрибута должно заканчиваться указанным текстом.

CSS

a[href$=".pdf"] {...}

HTML

<a href="/docs/menu.pdf">...</a>

Селектор атрибута ~=

Иногда значения атрибутов могут быть расположены через пробел друг от друга, в которых только одно из слов должно подходить для создания выборки. В этом случае использование символа тильды (~) в квадратных скобках селектора между именем атрибута и знаком равенства означает значение атрибута разделённое пробелами, из которых одно слово точно соответствует указанному значению.

CSS

a[rel~="tag"] {...}

HTML

<a href="#" rel="tag nofollow">...</a>

Селектор атрибута |=

Когда значение атрибута разделено дефисом, а не пробелами, может быть использован символ вертикальной линии (|) в квадратных скобках селектора между именем атрибута и знаком равенства. Вертикальная линия означает, что значение атрибута может быть разделено дефисом, однако слова должны начинаться с указанного значения.

CSS

a[lang|="en"] {...}

HTML

<a href="#" lang="en-US">...</a>

Пример селекторов атрибутов

HTML

<ul>
  <li><a href="#.pdf">PDF-документ</a></li>
  <li><a href="#.doc">Word-документ</a></li>
  <li><a href="#.jpg">Изображение</a></li>
  <li><a href="#.mp3">Аудио</a></li>
  <li><a href="#.mp4">Видео</a></li>
</ul>

CSS

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
a {
  background-position: 0 50%;
  background-repeat: no-repeat;
  color: #0087cc;
  padding-left: 22px;
  text-decoration: none;
}
a:hover {
  color: #ff7b29;
}
a[href$=".pdf"] {
  background-image: url("images/pdf.png");
}
a[href$=".doc"] {
  background-image: url("images/doc.png");
}
a[href$=".jpg"] {
  background-image: url("images/image.png");
}
a[href$=".mp3"] {
  background-image: url("images/audio.png");
}
a[href$=".mp4"] {
  background-image: url("images/video.png");
}
Обзор селекторов атрибутов
ПримерНазваниеОписание
a[target]Селектор наличия атрибутаВыбирает элемент если данный атрибут присутствует.
a[href="http://google.com/"]Селектор атрибута =Выбирает элемент, если значение данного атрибута в точности соответствует указанному.
a[href*="login"]Селектор атрибута *=Выбирает элемент, если значение данного атрибута содержит по крайней мере один экземпляр указанного текста.
a[href^="https://"]Селектор атрибута ^=Выбирает элемент, если значение данного атрибута начинается с указанного текста.
a[href$=".pdf"]Селектор атрибута $=Выбирает элемент, если значение данного атрибута заканчивается указанным текстом.
a[rel~="tag"]Селектор атрибута ~=Выбирает элемент, если значение данного атрибута разделено пробелами и точно совпадает с одним указанным словом.
a[lang|="en"]Селектор атрибута |=Выбирает элемент, если значение данного атрибута разделено дефисом и начинается с указанного слова.

Псевдоклассы

Псевдоклассы похожи на обычные классы в HTML, однако они непосредственно не указаны в разметке, вместо этого они поселяются динамически как результат действий пользователя или структуры документа. Наиболее распространённый псевдокласс, и его вы, вероятно, видели раньше, это :hover. Обратите внимание, что этот псевдокласс начинается с двоеточия (:), как и все остальные псевдоклассы.

Псевдоклассы ссылок

Некоторые основные псевдоклассы включают в себя два псевдокласса, вращающихся вокруг ссылок. Это псевдоклассы :link и :visited и они определяют, что ссылка была или не была посещена. Чтобы задать стиль ссылки, которая ещё не была посещена, в игру вступает псевдокласс :link, а псевдокласс :visited задаёт стиль ссылок, которые пользователь уже посетил на основе их истории просмотра.

a:link {...}
a:visited {…}

Псевдоклассы действия пользователя

К элементу могут динамически применяться основанные на действиях пользователей разные псевдоклассы, которые включают в себя :hover, :active и :focus. Псевдокласс :hover применяется к элементу, когда пользователь двигает курсор над элементом, наиболее часто это используется со ссылками. Псевдокласс :active применяется к элементу, когда пользователь приводит в действие элемент, например, при щелчке по нему. И, наконец, псевдокласс :focus применяется к элементу, когда пользователь сделал элемент точкой внимания страницы, часто с помощью клавишы Tab, переходя от одного элемента к другому.

a:hover {...}
a:active {...}
a:focus {...}

Псевдоклассы состояния интерфейса

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

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

input:enabled {...}
input:disabled {...}

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

input:checked {...}
input:indeterminate {…}

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

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

:first-child, :last-child и :only-child

Первые структурные псевдоклассы, которые вам скорее всего попадутся, это :first-child, :last-child и :only-child. Псевдокласс :first-child выберет элемент, если это первый ребёнок в родителе, в то время как псевдокласс :last-child выберет элемент, если он последний в родителе. Эти псевдоклассы идеально подходят для выбора первого или последнего элемента в списке и др. Кроме того, :only-child выберет элемент, если он является единственным элементом в родителе. В качестве альтернативы, псевдокласс :only-child может быть записан как :first-child:last-child, однако у :only-child ниже специфичность.

Здесь селектор li:first-child определяет первый пункт списка, в то время как li:last-child определяет последний пункт списка, таким образом, выбираются строки 2 и 10. Селектор div:only-child ищет <div>, который является единственным ребёнком в родительском элементе, без каких-либо других родственных элементов. В этом случае выбирается строка 4, т. к. это единственный <div> в данном пункте списка.

CSS

li:first-child {...}
li:last-child {...}
div:only-child {...}

HTML

<ul>
  <li>Этот пункт будет выбран</li>
  <li>
    <div>Этот div будет выбран</div>
  </li>
  <li>
    <div>...</div>
    <div>...</div>
  </li>
  <li>Этот пункт будет выбран</li>
</ul>

:first-of-type, :last-of-type и :only-of-type

Нахождение первого, последнего и единственного ребёнка у родителя очень полезно и часто только это и требуется. Однако иногда вы хотите выбрать только первого, последнего или единственного ребёнка определённого типа элемента. К примеру, вы желаете выбрать только первый или последний абзац внутри статьи или, возможно, только изображение в статье. К счастью, в этом помогают псевдоклассы :first-of-type, :last-of-type и :only-of-type.

Псевдокласс :first-of-type выберет первый элемент своего типа внутри родителя, в то время как псевдокласс :last-of-type выберет последний элемент этого типа внутри родителя. Псевдокласс :only-of-type выберет элемент, если он является единственным такого типа в родителе.

В приведённом ниже примере псевдоклассы p:first-of-type и p:last-of-type выберут, соответственно, первый и последний абзацы в статье, независимо от того, являются ли они на самом деле первыми или последними детьми в статье. Строки 3 и 6 выбраны этими селекторами. Селектор img:only-of-type определяет изображение в строке 5, как единственное изображение появляющееся в статье.

CSS

p:first-of-type {...}
p:last-of-type {...}
img:only-of-type {...}

HTML

<article>
  <h1>...</h1>
  <p>Этот абзац будет выбран</p>
  <p>...</p>
  <img src="#"><!-- Это изображение будет выбрано -->
  <p>Этот абзац будет выбран</p>
  <h6>...</h6>
</article>

Наконец, есть несколько псевдоклассов структуры и положения, которые выбирают элементы, основанные на номере или алгебраическом выражении. Эти псевдоклассы включают в себя :nth-child(n), :nth-last-child(n), :nth-of-type(n) и :nth-last-of-type(n). Все эти уникальные псевдоклассы начинаются с nth и принимают число или выражение внутри круглых скобок, которое обозначается символом n.

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

Использование чисел и выражений в псевдоклассах

Как уже упоминалось, использование конкретного числа в псевдоклассе вычисляет с начала или с конца дерева документа и выбирает один соответствующий элемент. Например, селектор li:nth-child(4) выберет четвёртый пункт в списке. Подсчёт начинается с первого пункта списка и увеличивается на единицу для каждого пункта списка, пока, наконец, не обнаружит четвёртый пункт и выберет его. При указании конкретного числа оно должно быть положительным.

Выражения для псевдоклассов бывают в формате an, an+b, an-b, n+b, -n+b и -an+b. То же самое выражение может быть переведено и читаться как (a×n)±b. Переменная a обозначает множитель, с учётом которого будут вычисляться элементы, в то время как переменная b обозначает, откуда будет начинаться или происходить отсчёт.

Например, селектор li:nth-child(3n) будет определять каждый третий элемент пункта списка. Использование этого выражения соответствует 3×0, 3×1, 3×2 и так далее. Как вы можете видеть, результаты этого выражения выбирают третий, шестой и каждый элемент кратный трём.

Кроме того, в качестве значений могут быть использованы ключевые слова odd и even. Как и следовало ожидать, они будут выбирать, соответственно, нечётные или чётные элементы. Если ключевые слова не привлекают, то выражение 2n+1 выберет все нечётные элементы, а выражение 2n выберет все чётные элементы.

Селектор li:nth-child(4n+7) определит каждый четвёртый пункт списка, начиная с седьмого пункта. Опять же, использование этого выражения эквивалентно (4×0)+7, (4×1)+7, (4×2)+7 и так далее. Результаты этого выражения приведут к выбору седьмого, одиннадцатого, пятнадцатого и каждого четвёртого элемента.

При использовании аргумента n без числа впереди, переменная a расценивается как равная 1. Селектор li:nth-child(n+5) выберет каждый пункт списка, начиная с пятого, оставив первые четыре пункта списка не выбранными. В выражении это разбирается как (1×0)+5, (1×1)+5, (1×2)+5 и так далее.

Для создания более сложных вещей могут быть задействованы отрицательные числа. Например, селектор li:nth-child(6n-4) будет отсчитывать каждый шестой пункт списка, начиная с -4, выбрав второй, восьмой, четырнадцатый пункты списка и так далее. Тот же селектор li:nth-child(6n-4) также может быть записан как li:nth-child(6n+2), без использования отрицательной переменной b.

Отрицательная переменная или отрицательный аргумент n должен сопровождаться положительной переменной b. Когда аргументу n предшествует отрицательная переменная a, то переменная b определяет, насколько высоко будет достигнут отсчёт. Например, селектор li:nth-child(-3n+12) выберет каждый третий пункт списка в первых двенадцати пунктах. Селектор li:nth-child(-n+9) выберет первые девять пунктов списка, так как переменная a без заявленного числа по умолчанию равна -1.

:nth-child(n) и :nth-last-child(n)

При общем понимании того, как работают числа и выражения в псевдоклассах, давайте взглянем на полезные псевдоклассы, где эти числа и выражения могут использоваться, первыми из которых являются :nth-child(n) и :nth-last-child(n). Эти псевдоклассы работают похоже на :first-child и :last-child, в том смысле что они рассматривают и считают все элементы в родителе и выбирают только определённый элемент. :nth-child(n) работает с начала дерева документа, а :nth-last-child(n) работает с конца дерева документа.

Используя псевдокласс :nth-child(n) давайте взглянем на селектор li:nth-child(3n). Он определяет каждый третий пункт списка, таким образом, будут выбраны строки 4 и 7.

CSS

li:nth-child(3n) {…}

HTML

<ul>
  <li>...</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
</ul>

Использование другого выражения в псевдоклассе :nth-child(n) даст другую выборку. Селектор li:nth-child(2n+3), к примеру, определит каждый второй пункт списка, начиная с третьего. В результате будут выбраны пункты в строках 4 и 6.

CSS

li:nth-child(2n+3) {...}

HTML

<ul>
  <li>...</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
</ul>

Очередное изменение выражения, на этот раз с отрицательным значением, даст новый выбор. Здесь селектор li:nth-child(-n+4) определяет четыре верхних пункта списка, оставляя остальные пункты не выделенными, таким образом будут выбраны строки со 1 по 4.

CSS

li:nth-child(-n+4) {...}

HTML

<ul>
  <li>Этот пункт будет выбран</li>
  <li>Этот пункт будет выбран</li>
  <li>Этот пункт будет выбран</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>...</li>
</ul>

Добавление отрицательного числа перед аргументом n снова изменяет выбор. Здесь селектор li:nth-child(-2n+5) определяет каждый второй пункт списка из первых пяти пунктов, таким образом, будут выбраны пункты в строках 2, 4 и 6.

CSS

li:nth-child(-2n+5) {...}

HTML

<ul>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
</ul>

Изменение псевдокласса :nth-child(n) на :nth-last-child(n) переключает направление счёта, теперь подсчёт начинается с конца дерева документа. Селектор li:nth-last-child(3n+2), к примеру, определяет каждый третий пункт списка, начиная со второго по последний, двигаясь по направлению к началу списка. Здесь выбраны пункты списка в строках 3 и 6.

CSS

li:nth-last-child(3n+2) {...}

HTML

<ul>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
  <li>...</li>
  <li>Этот пункт будет выбран</li>
  <li>...</li>
</ul>

:nth-of-type(n) и :nth-last-of-type(n)

Псевдоклассы :nth-of-type(n) и :nth-last-of-type(n) очень похожи на :nth-child(n) и :nth-last-child(n), однако вместо того чтобы считать каждый элемент внутри родителя псевдоклассы :nth-of-type(n) и :nth-last-of-type(n) учитывают только элементы своего собственного типа. Например, при подсчете абзацев в статье, псевдоклассы :nth-of-type(n) и :nth-last-of-type(n) пропустят любые заголовки, <div> или разные элементы, которые не являются абзацами, в то время как :nth-child(n) и :nth-last-child(n) будут считать каждый элемент, независимо от его типа, выбирая только те из них, которые соответствуют элементу в указанном селекторе. Кроме того, все те же возможные выражения, применяемые в :nth-child(n) и :nth-last-child(n) также доступны в псевдоклассах :nth-of-type(n) и :nth-last-of-type(n).

Используя псевдокласс :nth-of-type(n) в селекторе p:nth-of-type(3n) мы можем определить каждый третий абзац в родителе, независимо от других родственных элементов внутри родителя. Здесь выбираются абзацы в строках 5 и 9.

CSS

p:nth-of-type(3n) {...}

HTML

<article>
  <h1>...</h1>
  <p>...</p>
  <p>...</p>
  <p>Этот абзац будет выбран</p>
  <h2>...</h2>
  <p>...</p>
  <p>...</p>
  <p>Этот абзац будет выбран</p>
</article>

Как и с псевдоклассами :nth-child(n) и :nth-last-child(n), основное различие между :nth-of-type(n) и :nth-last-of-type(n) состоит в том, что :nth-of-type(n) считает элементы с начала дерева документа, а :nth-last-of-type(n) считает элементы с конца дерева документа.

Используя псевдокласс :nth-last-of-type(n) мы можем записать селектор p:nth-last-of-type(2n+1), который определяет каждый второй абзац с конца родительского элемента, начиная с последнего абзаца. Здесь выбираются абзацы в строках 4, 7 и 9.

CSS

p:nth-last-of-type(2n+1) {...}

HTML

<article>
  <h1>...</h1>
  <p>...</p>
  <p>Этот абзац будет выбран</p>
  <p>...</p>
  <h2>...</h2>
  <p>Этот абзац будет выбран</p>
  <p>...</p>
  <p>Этот абзац будет выбран</p>
</article>

Псевдокласс :target

Псевдокласс :target используется для стилизации элементов, когда значение атрибута id совпадает с указателем фрагмента URI. Такой фрагмент в URI распознаётся с помощью символа решётки (#) и того, что непосредственно следует за ним. Адрес http://example.com/index.html#hello включает в себя указатель hello. Когда он совпадает со значением атрибута id у элемента на странице, к примеру, <section id="hello">, то этот элемент может быть идентифицирован и стилизован с помощью псевдокласса :target. Указатель фрагмента наиболее часто встречаются при использовании на странице ссылки или ссылки на другую часть той же страницы.

Взгляните на приведённый ниже код. Если пользователь хотел бы посетить страницу с указателем фрагмента #hello, то раздел с тем же значением атрибута id будет стилизован соответствующим образом с помощью псевдокласса :target. Если указатель фрагмента URI изменился и совпадает со значением атрибута id другого раздела, то новый раздел может быть стилизован с помощью того же селектора и псевдокласса, что и ранее.

CSS

section:target {...}

HTML

<section id="hello">...</section>

Псевдокласс :empty

Псевдокласс :empty позволяет выбрать элементы, которые не содержат детей или текст. Комментарии, инструкции по обработке и пустой текст не считаются детьми и не рассматриваются как таковые.

Использование псевдокласса div:empty определит <div> без детей или текста. Ниже выбраны <div> в строках 2 и 3, поскольку они совершенно пустые. Даже несмотря на то, что второй <div> содержит комментарий, он не считается ребёнком, таким образом оставляя <div> пустым. Первый <div> содержит текст, третий содержит один пробел, а последний содержит дочерний элемент <strong>, таким образом, они все исключены и не выбраны.

CSS

div:empty {...}

HTML

<div>Привет</div>
<div><!-- Скоро появится --></div><!-- Этот div будет выбран -->
<div></div><!-- Этот div будет выбран -->
<div> </div>
<div><strong></strong></div>

Псевдокласс :not

Псевдокласс :not(x) принимает аргумент и отфильтровывает выборку, которая будет сделана. Селектор p:not(.intro) использует псевдокласс :not для определения каждого абзаца без класса intro. Элемент абзаца определяется в начале селектора, затем следует псевдокласс :not(x). Внутри скобок идёт селектор отрицания, в данном случае класс intro.

Ниже оба селектора div:not(.awesome) и :not(div) используют псевдокласс :not(x). Селектор div:not(.awesome) определяет любой <div> без класса awesome, в то время как селектор :not(div) определяет элемент, который не является <div>. В результате выбирается <div> в строке 1, а также два раздела в строках 3 и 4. Единственный не выбранный элемент это <div> с классом awesome, так как он выходит за пределы двух псевдоклассов.

CSS

div:not(.awesome) {...}
:not(div) {...}

HTML

<div>Этот div будет выбран</div>
<div class="awesome">...</div>
<section>Этот раздел будет выбран</section>
<section class="awesome">Этот раздел будет выбран</section>

Пример с псевдоклассами

HTML

<table>
  <thead>
    <tr>
      <th>Номер</th>
      <th>Игрок</th>
      <th>Позиция</th>
      <th>Рост</th>
      <th>Вес</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>8</td>
      <td>Марко Белинелли</td>
      <td>G</td>
      <td>6-5</td>
      <td>195</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Карлос Бузер</td>
      <td>F</td>
      <td>6-9</td>
      <td>266</td>
    </tr>
    ...
  </tbody>
</table>

CSS

table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}
th,
td {
  padding: 6px 15px;
}
th {
  background: #42444e;
  color: #fff;
  text-align: left;
}
tr:first-child th:first-child {
  border-top-left-radius: 6px;
}
tr:first-child th:last-child {
  border-top-right-radius: 6px;
}
td {
  border-right: 1px solid #c6c9cc;
  border-bottom: 1px solid #c6c9cc;
}
td:first-child {
  border-left: 1px solid #c6c9cc;
}
tr:nth-child(even) td {
  background: #eaeaed;
}
tr:last-child td:first-child {
  border-bottom-left-radius: 6px;
}
tr:last-child td:last-child {
  border-bottom-right-radius: 6px;
}
Обзор псевдоклассов
ПримерНазваниеОписание
a:linkПсевдокласс ссылокВыбирает ссылки, которые не были просмотрены пользователем.
a:visitedПсевдокласс ссылокВыбирает ссылки, которые были посещены пользователем.
a:hoverПсевдокласс действияВыбирает элемент, когда пользователь наводит на него курсор.
a:activeПсевдокласс действияВыбирает элемент, когда пользователь активирует его.
a:focusПсевдокласс действияВыбирает элемент, когда пользователь сделал его точкой внимания.
input:enabledПсевдокласс состоянияВыбирает элемент в доступном состоянии.
input:disabledПсевдокласс состоянияВыбирает элемент в отключенном состоянии, посредством атрибута disabled.
input:checkedПсевдокласс состоянияВыбирает флажок или переключатель, который был помечен.
input:indeterminateПсевдокласс состоянияВыбирает флажок или переключатель, который не был помечен или не помечен, оставляя его в неопределённом состоянии.
li:first-childСтруктурный псевдоклассВыбирает первый элемент в родителе.
li:last-childСтруктурный псевдоклассВыбирает последний элемент в родителе.
div:only-childСтруктурный псевдоклассВыбирает единственный элемент в родителе.
p:first-of-typeСтруктурный псевдоклассВыбирает первый элемент своего типа в родителе.
p:last-of-typeСтруктурный псевдоклассВыбирает последний элемент своего типа в родителе.
img:only-of-typeСтруктурный псевдоклассВыбирает единственный элемент своего типа в родителе.
li:nth-child(2n+3)Структурный псевдоклассВыбирает элемент, который соответствует заданному числу или выражению, считая все элементы с начала дерева документа.
li:nth-last-child(3n+2)Структурный псевдоклассВыбирает элемент, который соответствует заданному числу или выражению, считая все элементы с конца дерева документа.
p:nth-of-type(3n)Структурный псевдоклассВыбирает элемент, который соответствует заданному числу или выражению, считая только элементы этого типа с начала дерева документа.
p:nth-last-of-type(2n+1)Структурный псевдоклассВыбирает элемент, который соответствует заданному числу или выражению, считая только элементы этого типа с конца дерева документа.
section:targetПсевдокласс :targetВыбирает элемент, у которого значение атрибута id совпадает с указателем фрагмента URI.
div:emptyПсевдокласс :emptyВыбирает элемент, который не содержит каких-либо детей или текста.
div:not(.awesome)Псевдокласс :notВыбирает элемент не представленный заявленным аргументом.

Псевдоэлементы

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

Текстовые псевдоэлементы

Первыми реализованными псевдоэлементами были текстовые псевдоэлементы :first-letter и :first-line. Псевдоэлемент :first-letter определяет первую букву текста внутри элемента, в то время как :first-line определяет первую строку текста внутри элемента.

В демонстрации ниже первая буква абзаца с классом alpha задана большим размером шрифта и оранжевым цветом, так же как и первая строка абзаца с классом bravo. Эта выборка сделана с помощью текстовых псевдоклассов :first-letter и :first-line, соответственно.

CSS

.alpha:first-letter,
.bravo:first-line {
  color: #ff7b29;
  font-size: 18px;
}

HTML

<p class="alpha">Lorem ipsum dolor...</p>
<p class="bravo">Integer eget enim...</p>

Демонстрация текстовых псевдоэлементов

Псевдоэлементы, генерируемые содержимое

Псевдоэлементы :before и :after создают новые строчные псевдоэлементы только внутри выбранного элемента. Чаще всего эти псевдоэлементы используются в сочетании со свойством content, чтобы добавить незначительную информацию на страницу, однако, это не всегда так. Дополнительное применение этих псевдоэлементов может добавить компоненты пользовательского интерфейса на страницу без необходимости загромождать документ несемантическими элементами.

Псевдоэлемент :before создаёт псевдоэлемент до или впереди выбранного элемента, в то время как :after создаёт псевдоэлемент после или позади выбранного элемента. Эти псевдоэлементы выводятся вложенными внутри выбранного элемента, а не за его пределами. Ниже псевдоэлемент :after используется для отображения значения атрибута href у ссылок в круглых скобках после самой ссылки. Такая информация полезна, но, в конечном итоге, не всякий браузер поддерживает эти псевдоэлементы.

CSS

a:after {
  color: #9799a7;
  content: " (" attr(href) ")";
  font-size: 11px;
}

HTML

<a href="http://google.com">Искать в Интернете</a>
<a href="http://learn.shayhowe.com">Изучите, как создать сайт</a>

Демонстрация псевдоэлементов, генерируемых содержимое

Псевдоэлемент ::selection

Псевдоэлемент ::selection определяет выделенную пользователем часть документа. Выделение затем может быть стилизовано, но только с помощью свойств color, background, background-color и text-shadow. Стоит отметить, что свойство background-image игнорируется. В то же время сокращённое свойство background может быть использовано для добавления цвета, но любые изображения будут игнорироваться.

Двоеточие (:) и двойное двоеточие (::)

Псевдоэлемент ::selection был добавлен в CSS3 в попытке отделить псевдоклассы от псевдоэлементов с помощью двойного двоеточия, которое было добавлено к псевдоэлементам. К счастью, большинство браузеров будут поддерживать оба значения, одиночные или двойные двоеточия у псевдоэлементов, однако псевдоэлемент ::selection всегда должен начинаться с двойного двоеточия.

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

::-moz-selection {
  background: #ff7b29;
}
::selection {
  background: #ff7b29;
}

Демонстрация псевдоэлементов

HTML

<a class="arrow" href="#">Продолжить чтение</a>

CSS

.arrow {
  background: #2db34a;
  color: #fff;
  display: inline-block;
  height: 30px;
  line-height: 30px;
  padding: 0 12px;
  position: relative;
  text-decoration: none;
}
.arrow:before,
.arrow:after {
  content: "";
  height: 0;
  position: absolute;
  width: 0;
}
.arrow:before {
  border-bottom: 15px solid #2db34a;
  border-left: 15px solid transparent;
  border-top: 15px solid #2db34a;
  left: -15px;
}
.arrow:after {
  border-bottom: 15px solid transparent;
  border-left: 15px solid #2db34a;
  border-top: 15px solid transparent;
  right: -15px;
}
.arrow:hover {
  background: #ff7b29;
}
.arrow:hover:before {
  border-bottom: 15px solid #ff7b29;
  border-top: 15px solid #ff7b29;
}
.arrow:hover:after {
  border-left: 15px solid #ff7b29;
}
Обзор псевдоэлементов
ПримерНазваниеОписание
.alpha:first-letterТекстовый псевдоэлементВыбирает первую букву текста внутри элемента.
.bravo:first-lineТекстовый псевдоэлементВыбирает первую строку текста внутри элемента.
div:beforeГенерируемое содержимоеСоздаёт псевдоэлемент внутри выбранного элемента в его начале.
a:afterГенерируемое содержимоеСоздаёт псевдоэлемент внутри выбранного элемента в его конце.
::selectionПсевдоэлемент ::selectionВыбирает часть документа, который был выделен с помощью действий пользователя.

Поддержка селекторов в браузерах

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

CSS3.info предлагает инструмент CSS3 Selectors Test, который будет информировать вас о том, какие селекторы поддерживаются браузером. Также неплохой идеей будет проверить поддержку браузера непосредственно в нём.

Кроме того, Selectivizr, утилита JavaScript, обеспечивает великолепную поддержку этих селекторов в Internet Explorer 6-8. Больше поддержки при необходимости может также предложить jQuery selectors.

Скорость и производительность селекторов

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

Ресурсы и ссылки

Автор: Шэй Хоу
Последнее изменение: 16.10.2016
Редакторы: Влад Мержевич

Рекомендуем