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". |
: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 для текущего контекста. |
Описание 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 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:visited, a:hover, a:active, a:focus
Выбирает элементы (обычно это поля формы или ссылки) в зависимости от их состояния.
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-].
: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>
: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 работает только с интерактивными элементами:
<dialog>
(при открытии)<iframe>
(в полноэкранном режиме)<video>
(в полноэкранном режиме)<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), а не его класс.
-
Интерактивное тестирование :nth селектора.
- Интерактивный генератор :nth селектора
Возможные значения n
:
odd
— нечетные.even
— четные.число
— порядковый номер с 1.выражение с n
An+B
— A и 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+b
— a и 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+b
— a и 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 особенно полезен для уточнения вложенных селекторов и предотвращения выбора элементов вне текущего контекста.
Селекторы :nth-child наглядно
Чтобы быстро и точно понять как работают псевдо-селекторы типа :first-child. Я создал спец. страницу. Там же можно подобрать нужный для себя селектор этого типа, под конкретную задачу.
Немного практики
#1 Сложное выделение
У нас есть такой код:
<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; }