eurobyte.ru - мощные сервера с Дата-центрами в Нидерландах и Москве. От 159 ₽/мес.

CSS Селекторы (полный список)

В этой статье я постараюсь понятно объяснить что такое CSS селекторы и как использовать каждый из них. Здесь описаны все селекторы, которые нужно знать при работе с CSS.

CSS селектор — это то что позволяет выбирать нужный элемент в HTML документе, чтобы потом применить к этому элементу CSS стили (свойства).

Список селекторов

Селектор Пример Описание
* * Все элементы.
#id #firstname Элемент с id="firstname".
.class .intro Все элементы с class="intro".
.class1.class2 .name1.name2 Все элементы с class="name1 name2".
.class1 .class2 .name1 .name2 Все элементы с class="name2" у которых родитель с class="name1".
tag p Все <p> элементы.
tag.class p.intro Все <p> элементы с class="intro".
tag, tag div, p Все <div> и все <p> элементы.
tag tag div p Все <p> внутри всех <div>.
tag > tag div > p Все <p> прямой родитель которых <div>.
tag + tag div + p <p> который находятся сразу после <div>.
tag ~ tag div ~ p Все <p> которые находятся после <div>.
[attribute] [target] Все элементы с target="что-либо".
[attribute = value] [target=_blank] Все элементы с target="_blank".
[attribute ^= value] a[href^="https"] Каждый <a> атрибут href которого начинается с "https".
[attribute $= value] a[href$=".pdf"] Каждый <a> атрибут href которого заканчивается ".pdf".
[attribute *= value] a[href*="w3schools"] Каждый <a> атрибут href которого содержит подстроку "w3schools".
[attribute ~= value] [title~=flower] Все элементы в атрибуте title которых есть слово "flower".
[attribute |= value] [lang|=en] Все элементы атрибут lang которых начинается с "en".
[attr=value i] [type="email" i] Выберет оба: <input TYPE="EMAIL"> и <input type="email">.
:active a:active Активная ссылка.
::after p::after Вставляет псевод-элемент в начале каждого <p> элемента.
::before p::before Вставляет псевод-элемент в конце каждого <p> элемента.
::backdrop dialog::backdrop Cтилизует фоновую часть модального элемента.
:checked input:checked Все выбранные <input type="checkbox"> элементы.
:default input:default Все <input> элементы.
:disabled input:disabled Все <input disabled> элементы.
:empty p:empty Все пустые <p>, в которых нет пробелом, текста или других элементов.
:enabled input:enabled Все активные (не disabled) элементы <input>.
:first-child p:first-child Первый элемент в списке родительского элемента.
:first-of-type p:first-of-type Первый <p> элемент в списке родительского элемента.
::first-letter p::first-letter Первая буква каждого <p> элемента.
::first-line p::first-line Первая линия каждого <p> элемента.
:focus input:focus <input> в котором находится курсор.
:focus-visible a:focus-visible Фокус сработает, только если на кнопку перешли с клавиатуры через TAB.
:focus-within div:focus-within Сработает на блоке, когда его внутренний элемент находится в фокусе.
:hover a:hover Сслыка на которую наведена мышка.
:in-range input:in-range Все <input> со значением в пределах указанного в min/max диапазона.
:out-of-range input:out-of-range Все <input> со значением за пределами указанного в min/max диапазона.
:indeterminate input:indeterminate Все <input> в статусе indeterminate.
:invalid input:invalid Все <input> с недопустимым значением.
:lang(language) p:lang(it) Все <p> с lang="it".
:last-child p:last-child Последний элемент в списке родительского элемента.
:last-of-type p:last-of-type Последний <p> в списке родительского элемента.
:link a:link Все непосещенные ссылки.
:not(selector) :not(p) Все не <p> элементы.
:not(:only-child) div:not(:only-child) Все <div> внутри которых больше одного элемента.
:nth-child(n) p:nth-child(2) Второй элемент в списке родительского элемента.
:nth-of-type(n) p:nth-of-type(2) Второй <p> в списке родительского элемента.
:nth-last-child(n) p:nth-last-child(2) Второй элемент в списке родительского элемента (счет идет с конца).
:nth-last-of-type(n) p:nth-last-of-type(2) Второй <p> в списке родительского элемента (счет идет с конца).
:only-child p:only-child Единственный <p> у родителя (других элементов быть не может).
:only-of-type p:only-of-type Один <p> у родителя (других элементы могут быть).
:optional input:optional Все <input> у которых нет артибута "required".
:required input:required Все <input> у которых указан атрибут "required".
:out-of-range input:out-of-range Все <input> со значением выходящим за указанный рэндж.
::placeholder input::placeholder Все <input> у которых указан атрибут "placeholder".
:read-only input:read-only Все <input> у которых указан атрибут "readonly".
:read-write input:read-write Все <input> у которых не указан атрибут "readonly".
:root :root Корен документа.
::selection ::selection Выберет текущее выделение текста мышкой.
:target #news:target Выберет элемент с id="news" когда к нему пришил по клику.
:valid input:valid Все <input> с валидным значением.
:visited a:visited Все посещенные ссылки.
:where() :where(.foo, .bar) a Тоже что и .foo a, .bar a, но ВЕС селектора в скобках не учитывается.
:is() :is(.foo, .bar) a Тоже что и .foo a, .bar a. Удобен для записи многих селекторов компактно.
:has() div:has(.foo, .bar) DIV, в котором есть элемент с классом foo или bar.
:scope :scope > .foo Прямые потомки .foo для текущего контекста.
ns|E svg|a a в SVG namespace.
A || B col.price || td Все td из колонки col.price.

Описание CSS селекторов

*

Выбирает абсолютно все элементы. Например, такой код обнуляет внутренние и внешние отступы у всех элементов на странице:

* { margin:0; padding:0; }

* можно использовать в связке с другими селекторами. Например, выделим все дочерние элементы #container сплошной черной рамкой шириной 1px.

#container * { border: 1px solid black; }

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

.class

Выбирает элемент у которого есть атрибут class с указанным значением: class="myclass".

Название класса, может состоять из латинских букв (a-zA-Z), цифр (0-9), символа дефиса и подчеркивания (- _).

Следующий код устанавливает красный цвет текста для всех элементов с классом error -

<div class="error">
.error { color: red; }

У одного элемента может быть несколько классов (через пробел): <div class="error myclass">.

#id

Выбирает элемент у которого есть атрибут id с указанным значением: id="myid".

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

Идентификатор должен состоять из латинских букв (a-zA-Z), цифр (0-9), символа дефиса или подчеркивания: - _. Начинается он только с буквы!

Следующий код устанавливает ширину и отступ элемента с идентификатором:

<div id="container">
#container { width: 960px; margin: auto; }

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

tag

Селектор HTML тега. Применяться ко всем указанным элементам в документе. Часто используется для задания цвета, фона, шрифта и др.

Следующий код задает цвет текста для всех ссылок и отступы для UL списков:

a { color: red; }
ul { margin-left: 0; }

X, Y

Объединяет несколько селекторов, так чтобы указать всем выбранным селекторам одинаковые стили.

Следующий код задает цвет текста для заголовков h2 и ссылок в теге LI:

h2,
li a { color: red; }

X Y

Выбирает элементы Y, которые являются дочерними к X. Может состоять из нескольких селекторов: X Y Z. Сначала обязательно указывается родитель, а после него дочерние элементы. Их количество может быть любым. Свойства стилей будут применены только к последнему элементу.

Например, следующий код выбирает любой элемент <а>, являющийся потомком элемента <li>: (<li><a href="ссылка">текст</a></li>):

li a { text-decoration: none; }

Это правило можно сочетать с идентификаторами и классами: body.opera a{ color:blue; }.

Х > Y

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

Пример:

.parent > li{ border: 1px solid red; }

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

<ul class="parent">
	<li> список1
		<ul class="child">
			<li>список11</li>
			<li>список12</li>
		</ul>
	</li><!-- затронет -->
	<li>список2</li><!-- затронет -->
	<li>список3</li><!-- затронет -->
</ul>

Это правило не коснется <ul class="child">.

Демо >

Х ~ Y

Выбирает все элементы Y, которые расположены после X (на том же уровне). По поведению похож на X + Y. Разница в том, что будут выбраны все следующие элементы, а не только первый.

Например, в указанном коде будут выбраны все элементы p, которые расположены после div:

div ~ p { color: red; }

Окрасит "текст 2" и "текст 3":

<div>текст</div>
<p>текст 2</p><!-- color: red; -->
<p>текст 3</p><!-- color: red; -->

Демо →

Х + Y

Выбирает первый элемент Y, который находится после X (не вложен, а рядом). Стили будут применяться только к первому элементу Y.

Например, следующий код устанавливает красный цвет текста в абзаце p, который расположен сразу после div:

div + p { color: red; }

Получим:

<div>текст</div>
<p>текст 2</p><!-- color: red; -->
<p>текст 3</p>

Демо →

Выбирает элементы (обычно это поля формы или ссылки) в зависимости от их состояния.

  • a:link — выбирает обычную (не посещенную) ссылку. Обычно этот селектор записывается просто как a.
  • a:visited — выбирает уже посещенную ссылку.
  • a:hover — выбирает ссылку на которую наведена мышка (под курсором).
  • a:active — выбирает активную ссылку (на которую был сделан клик, пока еще никуда не кликали или когда на ссылку переключились при передвижении табом с клавиатуры).
  • a:focus — выбирает активную ссылку (на которую кликнули, но еще не отпустили кнопку мышки).
a:link   { color: red; }    /* можно просто а{  } */ /* все не посещенные ссылки */
a:visted { color: purple; } /* все посещенные ссылки */
a:hover  { color: green; }  /* ссылка под курсором */
a:active { color: blue; }   /* нажатая ссылка */
a:focus  { color: dark; }   /* ссылка в момент нажатия */

[attr]

Выбирает элементы, которые содержат указанный атрибут. Селектор атрибутов.

a[title] { color: green; }

Окрасит только "текст":

<a href="" title="описание">текст</a>
<a href="">текст 2</a>

[attr = value]

Выбирает элементы, у которых есть атрибут с указанным значением. Селектор атрибутов с точным значением.

a[href="http://example.com"] { color: red; }

Окрасит только "текст":

<a href="http://example.com">текст</a><!-- color: red; -->
<a href="http://example.com/article">текст 2</a>

[attr *= value]

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

a[href*="example"] { color: red; }

Окрасит "текст" и "текст 2":

<a href="http://example.com">текст</a><!-- color: red; -->
<a href="http://example.com/article">текст 2</a><!-- color: red; -->
<a href="http://xxx.ru/article">текст 2</a>

[attr ^= value]

Выбирает элементы, у которых значение атрибута начинается с указанной строки. Селектор атрибутов со значением в начале.

a[href^="http"] {
   background: url(path/to/external/icon.png) no-repeat;
   padding-left: 10px;
}

Установит фоновую картинку только для "текст":

<a href="http://example.com">текст</a>
<a href="/article">текст 2</a>

[attr $= value]

Выбирает элементы, у которых значение атрибута заканчивается на указанную строку. Селектор атрибутов со значением в конце.

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

a[href$=".jpg"] { color: red; }

Выберет ссылки a, ссылающиеся на изображения формата .jpg. Окрасит только "текст":

<a href="http://example.com/foto.jpg">текст</a>
<a href="http://example.com/foto2.png">текст 2</a>

[attr ~= value]

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

Он чем-то похож на *=, разница вот в чем:

  • *= — ищет home в любом месте значения. Найдет homeland.
  • ~= — ищет home разделеный пробелом. Найдет home land.
a[data-info ~= "external"] { color: red; }

a[data-info ~= "image"] { border: 1px solid black; }

Отработает так:

<a href="http://example.com" data-info="external">текст</a><!-- окрасит в красный -->

<a href="http://nettuts.com">текст 2</a><!-- не тронет -->

<a href="http://example.com" data-info="external image">текст 3</a><!-- окрасит и установит рамку -->

<a href="http://example.com" data-info="image">текст 4</a><!-- установит рамку -->

Об этом селекторе не многие знают, а ведь он иногда очень удобен.

[attr |= value]

Выбирает элементы, у которых значение атрибута равно указанной строке или начинается с неё.

Пример: [lang |= ru] - элементы с атрибутом lang, значение которого равно ru или начинается с ru-, например "ru-RU". Но он практически не используется и его заменяет комбинация: [lang = ru], [lang ^= ru-].

[attr=value i]

Флаги в атрибутных селекторах (Attribute flags).

  • [attr=value i] - Сравнение значения атрибута без учёта регистра (ASCII case-insensitive).
  • [attr=value s] - Сравнение строго с учётом регистра (case-sensitive), даже если документ/язык мог бы трактовать иначе.

Примеры:

<input TYPE="EMAIL">
<input type="email">
[type="email"] { outline: 2px solid red; }     /* совпадёт только со вторым */
[type="email" i] { outline: 2px solid green; } /* совпадёт с обоими */

Пример с s:

<div data-id="AbC"></div>
<div data-id="abc"></div>
[data-id="AbC" s] { border: 1px solid; } /* совпадёт только с AbC */

:root

Спецификация

Псевдо-класс, который "выбирает" корневой элемент документа.

Для HTML "выбирает" <html> элемент и идентичен селектору по тегу html. Для DOM дерева в JS "выбирает" document элемент.

Cпецифичность :root выше чем у селектора html. Потому что для :root применяется специфичность класса (10), для html специфичность тега (1).

Часто используется для объявления CSS Переменных:

:root {
  --main-color: hotpink;
  --pane-padding: 5px 42px;
}

:target

Выделяет активный якорь в HTML. Допустим у нас ссылка ссылается на внутренний якорь <a href="#anchor"> на странице, тогда при клике по этой ссылке этот селектор выделить элемент имеющий атрибут id="anchor".

:target { color: red; }

Получим:

<a href="#anchor1">Перейти на якорь 1</a>
<a href="#anchor2">Перейти на якорь 2</a>

<!-- При клике по этим ссылкам выберется соответствующий элемент ниже -->

<p id="anchor1">Элемент 1</p>
<p id="anchor2">Элемент 2</p>

MDN

:checked

Стилизует выбранные radio / checkbox. Может использоваться с тегом input или option или без них: input:checked, option:checked или :checked.

Например, следующий код выделяет сплошной черной рамкой в 1px область возле включенного флажка:

input[type=radio]:checked { border:1px solid black; }

:default

Выбирает элемент формы, который считается элементом по умолчанию. Работает с тегами <button>, <input>, <option>.

<form>
	<input type="submit"><!-- будет выбран -->
	<input type="submit">
	<input type="reset">
</form>
  • <option> считается дефолтным (:default), если это элемент с атрибутом selected или первый enabled (NOT disabled) элемент по порядку DOM элементов. Для <select multiple> каждый selected элемент будет считаться дефолтным.

  • <input type="checkbox"> и <input type="radio"> считаются дефолтными, если они выбраны (имеют атрибут checked).

  • <button> считается дефолтной, если это базовая кнопка сабмита формы (<form>) — это первая в форме кнопка по порядку DOM элементов. Это также справедливо и для типов <input type="submit">.

:disabled

Выбирает любой disabled (отключенный) элемент.

Элемент считается отключенным, когда с ним нельзя взаимодействовать (выбрать, кликнуть, сфокусироваться, вписать что-либо и т.д.). Если элемент не disabled, то на нём по-умолчанию установлен статус enabled.

Примеры

Установим цвет фона для всех отключенных полей формы с типом text: <input type="text">:

<form action="#">
	<legend>Shipping address</legend>
	<input type="text" placeholder="Name">
	<input type="text" placeholder="Address">
	<input type="text" placeholder="Zip Code">
</form>
input[type="text"]:disabled {
	background: #dddddd;
}

Установим цвет фона элементов <select class="country" disabled> — все отключенные элементы SELECT с классом COUNTRY:

select.country:disabled {
	background: #dddddd;
}

:enabled

Выбирает включенный (активный) элемент.

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

Примеры

Установим белый цвет фона для всех активных (enabled) элементов <input> и серый для всех неактивных (disabled):

<form action="#">
	<legend>Shipping address</legend>
	<input type="text" placeholder="Name" disabled="disabled">
	<input type="text" placeholder="Address">
	<input type="text" placeholder="Zip Code">
</form>
input[type="text"]:enabled {
	background: #fff;
}

input[type="text"]:disabled {
	background: #dddddd;
}

:empty

Спецификация

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

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

.box {
	background: red;
	height: 200px;
	width: 200px;
}

.box:empty {
	background: lime;
}
<div class="box"><!-- пустой --></div>
<div class="box">Я буду красным</div>
<div class="box">
	<!-- Я буду красным, так как перед комментарием стоят пробелы -->
</div>

::before

Псевдо-элемент. X::before добавляет псевдо-элемент в начало X (внутрь тега).

Работает только вместе со свойством content:'', которое указывает содержание добавленного элемента. content нужно указывать даже если содержание пустое (content:'') - элемент всегда должен хоть что-то содержать.

Например с помощью таких стилей, можно указать значок для LI списка:

li::before {
	content: '-';
	display: inline-block;
	margin-right: .5em;
}

Можно использовать одно двоеточие :before. Более правильно писать два - ::before. Такая запись подчеркивает, что это псевдо-элемент, а не селектор.

::after

Псевдо-элемент. X:after добавляет псевдо-элемент в конец X (внутрь тега).

Работает только вместе со свойством content:'', которое указывает содержание добавленного элемента. content нужно указывать даже если содержание пустое (content:'') - элемент всегда должен хоть что-то содержать.

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

.clear::after {
	content: '';
	display: table;
	clear: both;
}

Можно использовать одно двоеточие :after. Более правильно писать два - ::after. Такая запись подчеркивает, что это псевдо-элемент, а не селектор.

::backdrop

Псевдокласс ::backdrop стилизует фоновую часть модального элемента, когда он открыт.

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

<dialog open>HTML Модального окна</dialog>
dialog::backdrop {
	background-color: rgba(0, 0, 0, 0.5);
}

::backdrop работает только с интерактивными элементами:

  1. <dialog> (при открытии)
  2. <iframe> (в полноэкранном режиме)
  3. <video> (в полноэкранном режиме)
  4. <html> или <body> (в полноэкранном режиме документа)

Для обычных элементов, таких как <div>, ::backdrop не применим.

Альтернатива

::backdrop имеет баг в firefox и может быть заменен так:

.modal {
	box-shadow: 0 0 0 100vw rgb(0 0 0 / 0.5); /* огромная тень */
}

:focus

Выбирает активный HTML элемент, тот который находится в фокусе.

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

Пример. При перемещении курсора в поле <input type="text"> его фон будет изменен на желтый:

input:focus {
  background-color: yellow;
}

Пример. Стили применяться к любой ссылке <a> на которую был сдела клик:

a:focus {
  outline: 2px solid yellow;
}

Пример. При перемещении курсора в поле <input type="text"> его ширина будет постепенно увеличиваться со 100 до 250 пикселей:

input[type=text] {
  width: 100px;
  transition: ease-in-out, width .35s ease-in-out;
}

input[type=text]:focus {
  width: 250px;
}

:focus-visible

Применяется, когда элемент соответствует псевдоклассу :focus и браузер считает, что фокус должен быть "подсвечен".

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

:focus-within

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

Другими словами, он представляет элемент, который сам соответствует псевдо-классу :focus или имеет потомка, который соответствует :focus.

Включает потомков в теневых деревьях Shadow DOM.

Этот селектор полезен, например, для выделения всего контейнера <form>, когда пользователь фокусируется на одном из его полей <input>.

Примеры:

Этот пример Выбирает <div>, когда фокусируется один из его потомков:

div:focus-within {
  background: cyan;
}

Еще пример с формой:

<form>
  <label for="given_name">Given Name:</label>
  <input id="given_name" type="text">
  <br>
  <label for="family_name">Family Name:</label>
  <input id="family_name" type="text">
</form>
form {
  border: 1px solid;
  color: gray;
  padding: 4px;
}

form:focus-within {
  background: #ff8;
  color: black;
}

input {
  margin: 4px;
}

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

:hover

Срабатывает при наведении мышки на элемент, когда курсор над элементом. Может применяться для любых элементов (div, span) - не только для ссылок <a>.

Пример. При наведении мышкой под ссылкой будет появляться черная линия толщиной 1px (замена свойству underline):

a:hover {  border-bottom: 1px solid black; }

В следующем коде показано изменение цвета фона при наведении на элемент <div>:

div:hover { background: #e3e3e3; }

:in-range

Выбирает все элементы <input> value которого находится в заданном диапазоне. Диапазон задается атрибутами min, max или min и max.

У <input> тега должны быть указаны атрибуты min и/или max!

Смотрите также :out-of-range.

<input name="amount" type="number" min="2" max="6" value="4">
<input name="amount" type="number" min="2" value="4">
<input name="amount" type="number" max="6" value="4">

<input name="dep" type="date" min="2022-01-01" max="2025-12-31" value="2023-05-05">
input:in-range {
	background-color: green;
}

:out-of-range

Выбирает все элементы <input min="1" max="50"> со значением, которое находится за пределами указанного диапазона.

У <input> тега должны быть указаны атрибуты min и/или max!

Смотрите также :in-range.

<input name="amount" type="number" min="2" max="6" value="10">
<input name="amount" type="number" max="20" value="4">

<input name="dep" type="date" min="2022-01-01" max="2025-12-31" value="2027-05-05">
input:out-of-range {
	background-color: tomato;
}

:not(selector)

Выбирает элементы, которые не содержат указанного селектора. Вместо "selector" может быть любой селектор, кроме псевдо-элементов (:first-letter). Двойное отрицание запрещено: :not(:not(...)).

Следующий код выбирает для стилизации все элементы, кроме элемента p:

*:not(p) { color: green; }

В этом примере выбираются все элементы li, у которых нет класса .last:

ul li:not(.last) { color: blue; }

Выберет "элемент 1" и "элемент 2":

<ul>
	<li>элемент 1</li>
	<li>элемент 2</li>
	<li class="last">элемент 3</li>
</ul>

::first-line, ::first-letter

  • ::first-line стилизует начальную (первую) строку.
  • ::first-letter стилизует начальную (первую) букву. Изменяются только шрифт, цвет текста, фон и т.д. привязан к множеству параметров: ширина окна браузера, язык, шрифт и т.п.

Эти селекторы принято записывать с двойным двоеточием ::first-line, но можно и с одним :first-line.

#1 Выбираем первую букву в параграфе

Применит указанные стили для всех начальных букв всех абзацев в документе.

p::first-letter {
	float: left;
	font-size: 2em;
	font-weight: bold;
	font-family: cursive;
	padding-right: 2px;
}

#2 Выбираем первую строку в абзаце

Применит указанные стили для всех начальных строк всех абзацев в документе.

p::first-line {
	font-weight: bold;
	font-size: 1.2em;
}

:nth-child(n)

X:nth-child(n) выбирает каждый "n-ый" элемент Х, который находится на одном уровне с X. Считает все элементы на уровне X (неважно какой у элемента тип X). Под типом подразумевается тег элемента (div, span, li), а не его класс.

Возможные значения n:

  • odd — нечетные.
  • even — четные.
  • число — порядковый номер с 1.
  • выражение с n An+BA и B целые числа, n — счетчик от 0 до 999...

Используйте :nth-last-child(), чтобы делать аналогичные выборки но с конца.

Также есть похожий селектор :nth-of-type(n). Разница между ними в том, что X:nth-child(n) считает все элементы на одном уровне не важно какой Х, а Х:nth-of-type(n) считает все элементы на одном уровне, но только такие же как и Х. Например:

<h1>Заголовок</h1>
<p>Первый параграф.</p><!-- p:nth-child(2) -->
<p>Второй параграф.</p><!-- p:nth-of-type(2) -->

Пример с n = odd и n = even

Раскрасим четные и нечетные параграфы в разные цвета:

p:nth-child( odd ) {
	background: red;
}
p:nth-child( even ) {
	background: blue;
}

Получим:

<h1>Заголовок</h1>
<p>Первый параграф.</p><!-- blue -->
<p>Второй параграф.</p><!-- red -->
<p>Третий параграф.</p><!-- blue -->

Пример с n = число

Установит красным цветом второй элемент:

p:nth-child(2) { color: red; }

Окрасит "Второй параграф.":

<h1>Заголовок</h1>
<p>Первый параграф.</p><!-- red -->
<p>Второй параграф.</p>
<p>Третий параграф.</p>

Пример с n = выражение

Используя микро-синтаксис An+B - :nth-child(An+B) можно делать разную выборку:

Где:

  • A - это число, которое будет умножаться на n.
  • n - это счетчик от 0-999 - { An+B; n = 0, 1, 2, ... }.
  • B - это число (отступ).

Примеры:

  • :nth-child(2): второй элемент (указана только "A").
  • :nth-child(2n): все чётные элементы (2, 4, 6, 8 и так далее).
  • :nth-child(2n+1): все нечётные элементы (1, 3, 5, 7 и так далее).
  • :nth-child(5n+1): 1 (=(5×0)+1), 6 (=(5×1)+1), 11 (=(5×2)+1) и так далее.
  • :nth-child(5n+2): 2 (=(5×0)+2), 7 (=(5×1)+2), 12 (=(5×2)+2) и так далее.
  • :nth-child(3n+4) - 4, 7, 10, 13 ...

Параметр A в An+B можно опустить:

  • :nth-child(n+3): все элементы, начиная с третьего (3, 4, 5...).
  • :nth-child(-n+5): все элементы до пятого (1, 2, 3, 4, 5).

Объединив несколько :nth-child(), можно выбирать диапазоны элементов:

:nth-child(n+3):nth-child(-n+5): все элементы с третьего по пятый (3, 4, 5).

Аналоги:

  • :nth-child(odd) можно заменить на :nth-child(2n+1) - 1, 3, 5, 7 ...
  • :nth-child(even) можно заменить на :nth-child(2n) - 2, 4, 6, 8 ...
  • :first-child можно заменить на :nth-child(0n+1) или :nth-child(1).

Пример: Обратимся к каждому третьему элементу на уровне текущего элемента P:

p:nth-child(3n) { background: red; }

Получим:

<h1>Заголовок</h1>
<p>Параграф 1</p>
<p>Параграф 2</p><!-- background: red -->
<p>Параграф 3</p>
<p>Параграф 4</p>
<p>Параграф 5</p><!-- background: red -->
<p>Параграф 6</p>
<p>Параграф 7</p>
<p>Параграф 8</p><!-- background: red -->
<p>Параграф 9</p>

:nth-last-child(n)

Работает точно также как и :nth-child(n) только отсчет идет не сверху (с начала), а снизу (с конца).

n может быть:

  • odd — нечетные.
  • even — четные.
  • число — порядковый номер с 1.
  • выражение с n an+ba и b целые числа, n — счетчик от 0 до 999...
  • смотреть на примере >

Следующий код установит красным цветом второй с конца параграф:

li:nth-last-child(2) { color: red; }

Окрасит "Второй параграф.":

<h1>Заголовок</h1>
<p>Первый параграф.</p>
<p>Второй параграф.</p><!-- red -->
<p>Третий параграф.</p>

Еще примеры смотрите в предыдущем селекторе :nth-child(n).

:nth-child(An+B of S) и :nth-last-child(An+B of S)

В CSS Selectors Level 4 появилась возможность передавать список селекторов в :nth-child() и :nth-last-child().

Когда указывается S, логика An+B применяется только к элементам, которые соответствуют указанному селектору S. Это означает, что элементы сначала будут отфильтрованы по указанному селектору и только потом будет применена логика An+B.

Например селектор :nth-child(2 of .foo) выберет второй элемент с классом .foo.

div :nth-child(2 of .foo) { color: red; }
<div>
	<h1>Заголовок</h1>
	<p class="foo">Первый параграф.</p>
	<p>Второй параграф.</p>
	<p class="foo">Третий параграф.</p><!-- red -->
</div>

Заметьте, что S — это список селекторов (из может быть несколько, разделённых запятой). Например:

:nth-child(4 of .highlight, .sale)

Пример с зебра-таблицей

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

tr:nth-child(even) {
	background-color: lightgrey;
}

Все работает хорошо, до тех пор пока таблицы статичные. Проблема возникает при динамическом скрытии строк таблицы. Например, если скрыть 4,5,7 строки (см картинку), то видимыми останутся те, у которых одинаковый цвет фона:

Чтобы это исправить, можно использовать :nth-child(An+B of S), исключив скрытые строки из An+B логики:

tr:nth-child(even of :not([hidden])) {
	background-color: lightgrey;
}

:nth-of-type(n)

Выбирает элемент по номеру указанному в "n". X:nth-of-type начинает отсчет от первого элемента типа X находящегося на одном уровне. Под типом подразумевается именно тег элемента (div, span, li), а не его класс.

Заметка: есть такой же селектор :nth-child(n) разница между ними в том, что X:nth-of-type(n) выберет только элементы типа Х находящиеся на одном уровне, а X:nth-child(n) считает все элементы всех типов на одном уровне, не важно какой тип указан в Х. Например:

<h1>Заголовок</h1>
<p>Первый параграф.</p><!-- p:nth-child(2) -->
<p>Второй параграф.</p><!-- p:nth-of-type(2) -->

n может быть:

  • odd — нечетные.
  • even — четные.
  • число — порядковый номер с 1.
  • выражение с n an+ba и b целые числа, n — счетчик от 0 до 999...
  • смотреть на примере >

#1 n = add / even

Раскрасим четные и нечетные параграфы в разные цвета. Считает именно параграфы без h1, как это делает :nth-child:

p:nth-of-type(odd)  { background: red; }
p:nth-of-type(even) { background: blue; }

Получим:

<h1>Заголовок</h1>
<p>Первый параграф.</p><!-- red -->
<p>Второй параграф.</p><!-- blue -->
<p>Третий параграф.</p><!-- red -->

#2 n = число

Установит красным цветом второй элемент:

li:nth-of-type(2) { color: red; }

Окрасит "Второй параграф.":

<h1>Заголовок</h1>
<p>Первый параграф.</p>
<p>Второй параграф.</p><!-- red -->
<p>Третий параграф.</p>

#3 n = выражение

Формула выражения: an + b, где "a" - число, которое будет умножаться на n, "n" - счетчик от 0-999, "b" - число, отступ. { an + b; n = 0, 1, 2, ... }

  • в селекторе :nth-of-type(2) указана только "а".
  • :nth-of-type(odd) можно заменить на :nth-of-type(2n+1) - 2, 4, 6, 8 ...
  • :nth-of-type(even) можно заменить на :nth-of-type(2n) - 1, 3, 5, 7 ...
  • :nth-of-type(3n+4) - 4, 7, 10, 13 ...
  • :first-of-type можно заменить на :nth-of-type(0n+1) или просто :nth-of-type(1)

Например: обратимся к каждому третьему элементу p на текущем уровне, где расположены p:

p:nth-of-type(3n) { background: red; }

Получим:

<h1>Заголовок</h1>
<p>Параграф 1</p>
<p>Параграф 2</p>
<p>Параграф 3</p><!-- background: red -->
<p>Параграф 4</p>
<p>Параграф 5</p>
<p>Параграф 6</p><!-- background: red -->
<p>Параграф 7</p>
<p>Параграф 8</p>
<p>Параграф 9</p><!-- background: red -->

:nth-last-of-type(n)

Выбирает элемент по номеру указанному в n. X:nth-last-of-type(n) Начинает отсчет от последнего элемента X находящегося на одном уровне.

Это такой же селектор как и :nth-of-type(n) только считает наоборот - с конца.

Например: обратимся к каждому третьему элементу p с конца, на текущем уровне, где расположены p:

 p:nth-last-of-type(3n) { background: red; }

Получим:

<h1>Заголовок</h1>
<p>Параграф 1</p><!-- background: red -->
<p>Параграф 2</p>
<p>Параграф 3</p>
<p>Параграф 4</p><!-- background: red -->
<p>Параграф 5</p>
<p>Параграф 6</p>
<p>Параграф 7</p><!-- background: red -->
<p>Параграф 8</p>
<p>Параграф 9</p>

Еще примеры смотрите в предыдущем селекторе :nth-of-type(n).

:first-child

X:first-child Выбирает первый элемент который находится на одном уровне с Х. Отсчет начинается с любого элемента не обязательно Х.

X:first-child это тоже самое что X:nth-child(1)

#1 Пример: обратимся к первому элементу в блоке #container

#container div:first-child{ color:red; }

Получим:

<div id="container">
	<div>элемент 1</div><!-- color:red; -->
	<div>элемент 2</div>
</div>

А вот так не выделит ничего:

<div id="container">
	<h1>Заголовок</h1>
	<div>элемент 1</div><!-- не выделит -->
	<div>элемент 2</div>
</div>

#2 Обнуление границы

:first-child иногда используется для обнуления свойства border на граничных элементах списка. Следущий код обнулит значение верхней границы элемента li, являющимся дочерним по отношению к элементу ul.

ul li:first-child { border-top: none; }

:last-child

X:last-child Выбирает первый с конца элемент который находится на одном уровне с Х. Отсчет начинается с любого элемента не обязательно X.

X:last-child это тоже самое что X:nth-last-child(1)

#1 Пример: обратимся к первому с конца элементу в блоке #container

#container div:last-child{ color:red; }

Получим:

<div id="container">
	<div>элемент 1</div>
	<div>элемент 2</div><!-- color:red; -->
</div>

А вот так ничего не выделит (потому что мы говорим покрасить DIV, который является последним элементов в блоке, а тут последний это P):

<div id="container">
	<div>элемент 1</div>
	<div>элемент 2</div><!-- не выделит -->
	<p>параграф</p>
</div>

Однако если не указать тег, то будет выбран последний элемент:

#container :last-child{ color:red; }
/* или */
#container *:last-child{ color:red; }
<div id="container">
	<div>элемент 1</div>
	<div>элемент 2</div>
	<p>параграф</p><!-- color:red; -->
</div>

#2 Покрасим последний элемент li в списке ul в зеленый:

ul > li:last-child { color: green; }

Получим:

<ul>
	<li>список 1</li>
	<li>список 2</li>
	<li>список 3</li><!-- color: green; -->
</ul>

:first-of-type, :last-of-type

Выбирает первый / последний элемент с таким же тегом что и X, который находится на одном уровне с X. Считает только теги X.

X:first-of-type это тоже самое что X:nth-of-type(1)

#1 Пример: обратимся к первому элементу div в блоке #container

#container div:first-of-type{ color:red; }

Получим:

<div id="container">
	<h1>Заголовок</h1>
	<div>элемент 1</div><!-- color:red; -->
	<div>элемент 2</div>
</div>

#2 Обнуление границы

:first-of-type часто используется для обнуления свойства border на граничных элементах списка:

ul li:first-of-type { border-top: none; }

Получим:

<ul>
	<span>текст</span>
	<li>элемент 1</li><!-- border-top: none; -->
	<li>элемент 2</li>
	<li>элемент 3</li>
</ul>

:only-child

X:only-child Выбирает элемент X, который единственный на уровне X. При подсчете элементов название тега X НЕ учитывается.

Другими словами: выбирает дочерние элементы X только, когда у родителя количество всех дочерних элементов (неважно какой тип) равно 1.

Выберем элемент, если он единственный в блоке:

p:only-child { background: red; }

Получим:

<div>
	<p>параграф</p><!-- background: red; -->
</div>

<div>
	<span>параграф</span><!-- не выберет, потому что X=p а не span -->
</div>

<div>
	<p>текст</p><!-- не выберет, потому что на этом уровне 2 элемента -->
	<span>параграф</span>
</div>

:not(:only-child)

:only-child с отрицанием :not() - это комбинация двух псевдо-селекторов.

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

li:not(:only-of-type) {
  font-size: 1.25em;
}

В результате если у нас один элемент он НЕ будет выбран:

<ul>
	<li></li><!-- не будет выбран -->
</ul>

А если больше одного, то будут выбраны все:

<ul>
	<li></li><!-- будет выбран -->
	<li></li><!-- будет выбран -->
</ul>

:only-of-type

X:only-of-type Выбирает элемент X, который единственный на уровне X (не имеет соседей). При подсчете элементов учитывается название тега X.

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

Например:

p:only-of-type { background: red; }

Получим:

<div>
	<p>параграф</p><!-- background: red; -->
</div>

<div>
	<span>параграф</span><!-- не выделится, потому что X=p а не span -->
</div>

<div>
	<span>параграф</span>
	<p>текст</p><!-- background: red; -->
</div>

#1 Выберем ul только с одним элементом в списке.

ul > li:only-of-type { font-weight: bold; }

Другой вариант: можно ul > li:only-child, потому что обычно в списках ul находятся только li теги.

:is()

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

Например:

.block .block__title,
.block .block__subtitle {
	color: tomato;
}

/* можно записать так */
.block :is(.block__title, .block__subtitle) {
	color: tomato;
}

Еще пример:

input:is(:hover, :focus) {
	color: blue;
}

Вес (специфичность) у :is()

:is() сохраняет вес (специфичность) селектора указанного в списке.
Также будет взят вес самого сильного селектора из списка. Например:

.content :is(h1, h2, #h3) {
	color: tomato; // вес `.content h2` будет как у `.content #h3`
}

Разница между :is() и :where()

Разница в том, что :is() учитывает специфичность селектора (он берет специфичность (вес) наиболее специфичного селектора из списка), в то время как :where() не накладывает весь на селектор - имеет нулевой - специфичность указанных селекторов в списке равна 0.

Смотрите видео, где Кевин подробно показывает чем отличаются псевдо-классы: :is() :where() :has():

:where()

Тоже самое что :is(), только будет нулевой вес (специфичность) у всех селекторов в списке. Это убийца веса селекторов.

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

:where(.content) :is( h1, h2, h3 ) {
	margin: 1em 0; // вес этого свойства будет 1 (селектор тега)
}

Теперь если мы где-то ниже использует такой селектор для изменения свойства color он будет работать (перебьет стиль):

h1 {
	margin: 2em 0;
}

:has()

Позволяет выбрать элемент, если в нем есть вложенный элемент указанный в списке :has().

Например:

/*
Добавит паддинг к элементу ``.content``, только
если в нем есть картинка (img элемент)
*/
.content:has(img) {
	padding: 3rem;
}

Еще пример:

/*
Применяет стили к h1, только если есть элемент абзаца,
который непосредственно следует за h1
*/
h1:has(+ p) {
  margin-bottom: 0;
}

Еще пример:

<label>
	<span>Phone</span>
	<input type="text" name="phone">
</label>
input { color: black; }
span:has(+ input:focus) { color: red; }

Теперь, когда мы сфокусируемся в input цвет предыдущего элемента span перекрасится в красный!

Видео по :has()

:scope

:scope — это псевдо-класс, которые позволяет выбрать элемент, который является текущим контекстом для селекторов, которые следуют после :scope.

Элемент(ы), которые выбираются с помощью :scope, зависят от контекста, в котором он используется:

  • На верхнем уровне :scope эквивалентен :root, который в обычном HTML-документе соответствует элементу <html>.

  • При использовании в вызовах DOM API — таких как querySelector(), querySelectorAll(), matches() или Element.closest():scope соответствует элементу, на котором был вызван метод.

  • Внутри блока @scope, :scope соответствует определенному корню области видимости этого блока. Это позволяет применять стили к корню области видимости внутри самого блока @scope.

Например:

<div class="container">
  <div class="box">
	<p>Text</p>
  </div>
</div>
const container = document.querySelector('.container');
const box = container.querySelector(':scope > .box');
console.log(box); // Найдет .box, который является прямым потомком .container

Еще пример:

<ul class="list">
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
const list = document.querySelector('.list');
const items = list.querySelectorAll(':scope > li');
console.log(items); // Вернет только непосредственных потомков li внутри .list

:scope особенно полезен для уточнения вложенных селекторов и предотвращения выбора элементов вне текущего контекста.

ns|E

Namespace selectors (селекторы пространств имён). Используются в XML-документах и там, где реально есть namespaces (например, SVG внутри XML). В обычном HTML они почти не нужны, но для SVG иногда встречаются.

Синтаксис:

  • ns|E - Выбирает элемент E в namespace с префиксом ns.
  • *|E - Выбирает элемент E в любом namespace (включая “без namespace”).
  • |E - Выбирает элемент E без namespace.

Пример с @namespace:

@namespace svg url("http://www.w3.org/2000/svg");

svg|a { stroke: currentColor; }
svg|circle { fill: red; }

Пример “любой namespace”:

*|a { text-decoration: underline; } /* a в HTML и в SVG */

Пример “только без namespace”:

|a { color: blue; } /* только обычный HTML <a>, не svg|a */

A || B

Column combinator (комбинатор колонок). Выбирает элементы B, которые находятся в той же табличной колонке, что и A. Работает через табличную семантику (<table>, <colgroup>, <col>).

Идея: помечаете колонку через <col>, а стилите все ячейки (td/th) этой колонки.

<table>
  <colgroup>
	<col class="name">
	<col class="price">
	<col class="stock">
  </colgroup>

  <tr> <th>Товар</th>  <th>Цена</th> <th>Наличие</th> </tr>
  <tr> <td>Apple</td>  <td>10</td>   <td>Да</td>      </tr>
  <tr> <td>Banana</td> <td>7</td>    <td>Нет</td>     </tr>
</table>
col.price || td,
col.price || th {
	font-weight: 700;
}

Это означает: “все td/th, которые принадлежат той же колонке, что и col.price”.

:nth-child подробнее

Чтобы быстро и точно понять как работают псевдо-селекторы типа :first-child. Я создал спец. страницу. Там же можно подобрать нужный для себя селектор этого типа, под конкретную задачу.

Смотреть «Наглядное пособие»

Задачка

У нас есть код:

<div>
	<p>параграф</p>
	<ul>
	   <li>Список 1 </li>
	   <li>Список 2 </li>
	</ul>

	<ul>
	   <li>Список 3 </li>
	   <li>Список 4 </li>
	</ul>
</div>

Как обратиться к "Список 2"?

Решение 1

ul:first-of-type > li:nth-child(2) {
	font-weight: bold;
}

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

Решение 2

Использование соседних селекторов.

p + ul li:last-child {
	font-weight: bold;
}

Браузер находит ul, следующий сразу за p, затем находит его последний дочерний элемент.

Решение 3

Это решение пожалуй самое правильное, потому что если между ul или li попадут другие теги, этот пример все равно будет выбирать нужный нам li:

ul:first-of-type li:nth-last-of-type(1) {
	font-weight: bold;
}

Браузер выбирает первый ul (именно ul), затем находит первый с конца элемент li (именно li).

Считаем элементы в блоке с помощью nth-child

Полезная статья на Хабре - количественные CSS селекторы, учит считать элементы с помощью nth-child. Например, нужно выделить первый элемент, только, если в блоке 6 элементов указанного типа. Или, нужно выделить все элементы блока, если в блоке всего 6 элементов.

Несколько примеров без объяснений:

Первый элемент, только если всего их 6:

li:nth-last-child(6):first-child {
  color: tomato;
}

// с использование :has()
.parent:has(> li:nth-last-child(6)):first-child {
  color: tomato;
}

Все элементы в блоке, только если всего их 6:

li:nth-last-child(6):first-child,
li:nth-last-child(6):first-child ~ li {
  color: tomato;
}

// с использование :has()
.parent:has(> li:nth-last-child(6)) li {
  color: tomato;
}

Используя обратный к :nth-child(n+6) селект :nth-last-child(n+6) мы сможем выделить все элементы «от шестого с конца и до самого первого с начала».

Все элементы кроме 5 последних, только если всего в блоке 6 или больше элементов:

li:nth-last-child(n+6) {
  color: tomato;
}

Все элементы, только если всего в блоке 6 или больше элементов:

li:nth-last-child(n+6),
li:nth-last-child(n+6) ~ li {
  color: tomato;
}

Все элементы, только если всего в блоке 6 или меньше элементов:

li:nth-last-child(-n+6):first-child,
li:nth-last-child(-n+6):first-child ~ li {
  color: tomato;
}

Все элементы указанного тега (p), только если всего в блоке 6 или больше элементов в этим тегом (p):

p:nth-last-of-type(n+6),
p:nth-last-of-type(n+6) ~ p {
  color: tomato;
}

Выбор диапазона элементов

Допустим, у вас есть список из 20 элементов и нужно выбрать элементы с 7 по 14 включительно. Это можно сделать вот так:

ol li:nth-child(n+7):nth-child(-n+14) {
  background: lightpink;
}

25 комментариев
Полезные - 4 Все