В этой статье разберем понятия «CSS-селекторы» и «CSS-правила», подробно рассмотрим, для чего нужны CSS-селекторы, их виды, выявим отличие псевдоклассов от псевдоэлементов, а также продемонстрируем, как правильно комбинировать селекторы, учитывая их приоритет.
Что такое CSS-селекторы
CSS-селектор — один из основных механизмов, предназначенных для применения CSS-стилей к определенному элементу HTML-страницы. Селектор позволяет указать, какой HTML-элемент должен быть стилизован по заданным условиям, которые называют CSS-правилами.
Самый простой пример создания CSS-стиля может выглядеть следующим образом:
p { margin-top: 20px; margin-bottom: 20px; }
В этом примере p
— селектор по тегу p
(параграф), текст внутри фигурных скобок — CSS-правило. Этот код означает следующее: «Сделать всем параграфам внутренний отступ сверху и снизу 20px».
Существующие в CSS-селекторы условно разделить на три группы:
- базовые селекторы;
- псевдоклассы;
- псевдоэлементы.
Базовые селекторы
К базовым селекторам относят:
- селектор по тегу;
- селектор по классу;
- селектор идентификатору;
- селектор по атрибуту;
- универсальный селектор.
Рассмотрим каждый из них.
Селекторы по тегу
Этот тип селектора позволяет задействовать CSS-правила для указанного тега. В нижеприведенном примере текст для всех заголовков второго уровня H2 на странице окрашивается в серый цвет и приобретает полужирное начертание.
h2 { color: gray; font-weight: bold; }
Селекторы по классу
Селекторы класса обозначаются в CSS с точкой в начале названия класса. В HTML класс применяется к элементу с помощью атрибута class
. Пример ниже говорит, что любой элемент с классом .section
, независимо от количества таких элементов, будет иметь внутренние отступы слева и справа в 30px.
.section { padding-left: 30px; padding-right: 30px; }
Селекторы по идентификатору
Чтобы элемент мог быть стилизован по идентификатору, этому элементу необходимо добавить атрибут id
. В CSS идентификатор прописывается в виде имени с добавленной впереди решеткой #
.
На практике идентификаторы лучше не использовать для стилизации элементов. Это уникальные атрибуты, каждый из которых должен использоваться на странице один раз. Такая их особенность может усложнить верстку.
Идентификаторы довольно удобно применять с JavaScript кодом. Например, чтобы повесить на уникальный элемент документа js-событие. В этом случае атрибут
id
будет кстати.
Придадим стили к элементу с идентификатором #card, добавив немного тени.
#card { box-shadow: 5px 5px 5px #ccc; }
Селекторы по атрибуту
Также можно добавлять стили к элементам по названию их атрибутов — селектор прописывается в квадратных скобках []
. Существуют различные вариации такой стилизации:
Селектор | Применяется к элементам, у которых |
---|---|
[attr] | установлен атрибут attr |
[attr="somevalue"] | есть атрибут attr , имеющий значение somevalue |
[attr^="some"] | существует атрибут attr , значение которого начинается с some (например, somevalue ) |
[attr|="somevalue"] | примененный атрибут attr имеет значение, либо равное somevalue , либо начинающееся с somevalue- (например, somevalue-first ) |
[attr*="somevalue"] | установлен атрибут attr со значением, содержащим подстроку somevalue (например, startsomevalueend ) |
[attr~="somevalue"] | применен атрибут attr с несколькими разделенными пробелом значениями, одно из которых равно somevalue (например, [attr~="somevalue anothervalue"] ) |
[attr$="value"] | есть атрибут attr , заканчивающийся на value (например, somevalue ) |
Примеры:
/* Серая рамка для всех изображений, имеющих атрибут alt */ img[alt] { border: 1px solid #ccc; } /* Всем картинкам, атрибут title которых содержит значение "Натюрморт", установлена максимальная ширина 200px */ img[title="Натюрморт"] { max-width: 200px; } /* Элементы с классом, значение которого начинается с "row", растягиваются на всю ширину родительского блока */ [class^="row"] { max-width: 100%; } /* Внутренний отступ элементам, содержащим класс "col" или начинающийся с "col-" */ [class|="col"] { padding: 10px 20px; } /* Ссылки, ведущие на ресурс, имеющий в названии строку "somedomain", — зеленого цвета */ a[href*="somedomain"] { color: green; } /* Элемент с атрибутом data-main, одно из значений которого "comment", будет иметь тень */ [data-main~="comment"] { box-shadow: 2px 2px 5px #000; } /* Если у элемента установлен атрибут rel со значением, заканчивающимся на "external", то текст содержимого окрасится в красный цвет */ [rel$="external"] { color: red; }
Универсальный селектор
Селектор, который задает CSS-стили абсолютно всем элементам на HTML странице, называется универсальным и обозначается звездочкой *
.
В практике он используется, например, для установления алгоритма расчета высоты и ширины элементов (CSS-правило box-sizing), общего шрифта и начертания текста на странице или сброса стандартных стилей браузера.
По умолчанию браузеры добавляют отступы к некоторым элементам документа. Чтобы их обнулить, используем универсальный селектор:
* { margin: 0; padding: 0; }
Псевдоклассы
С помощью псевдоклассов можно применять CSS-стили к элементам, в зависимости от их динамического состояния или порядка в структуре DOM-дерева документа. К примеру, часто можно видеть на сайтах изменение стиля кнопки при наведении на нее курсора мыши или чередование цвета строк в таблице — такие эффекты реализуются через псевдоклассы.
Чтобы задать CSS-стиль с помощью псевдокласса, селектору, указывающему на элемент, добавляется название псевдокласса через двоеточие: «селектор:псевдокласс».
Псевдоклассы условно можно разделить на две группы:
- псевдоклассы состояния элементов;
- псевдоклассы структуры.
Рассмотрим каждую из групп подробнее.
Псевдоклассы состояния элементов
Среди этой группы можно выделить небольшую подгруппу псевдоклассов, которые относятся исключительно к ссылкам — это :link
, :visited
и :active
. А также существует подгруппа классов состояния, которые используют для форм: :enabled
, :disabled
, :checked
, :default
, :valid
, :invalid
, :required
, :optional
, in-range
, out-of-range
.
Описание основных псевдоклассов состояния представлено в нижеследующей таблице.
Псевдокласс | К каким элементам применяются стили |
---|---|
:link | Ссылки, по которым пользователь еще не совершил переход |
:visited | Ссылки, по которым уже переходили |
:active | Ссылки в момент нажатия на нее кнопки мыши (когда пользователь отпускает кнопку, в этот момент стили уже не применяются) |
:hover | Элемент при наведении на него курсора |
:focus | Элемент, находящийся в фокусе. Состояние фокуса элемент получает, например, при нажатии кнопки мыши поле формы. Переключать фокус элементов на странице можно с помощью табуляции (клавиша tab) |
:enabled | Элемент формы, над которым возможно производить действия, то есть он не деактивирован (отсутствует атрибут disabled ) |
:disabled | Элемент формы, над которым нельзя производить каких-либо действий (у него установлен атрибут disabled ) |
:checked | Чекбокс или радиокнопка, которые выбраны в определенный момент |
:default | Элемент формы, установленный по умолчанию в группе подобных элементов |
:valid | Элемент формы, который проходит валидацию в браузере |
:invalid | Элемент формы, который не проходит валидацию в браузере |
:required | Элемент формы, обязательный для заполнения, имеющий атрибут required |
:optional | Элемент формы, необязательный для заполнения, который не имеет атрибута required |
:in-range | Элемент формы, содержащий введенное значение, которое находится в установленных с помощью атрибутов min и max пределах |
:out-of-range | Элемент формы, содержащий введенное значение, которое находится вне установленных с помощью атрибутов min и max пределов |
Рассмотрим примеры с каждым из вышеприведенных псевдоклассов состояния.
/* Цвет ссылок, по которым еще не переходили — синий */ a:link { color: blue; } /* Светло-синий — цвет ссылок, по которым перешли */ a:link { color: lightblue; } /* Окрасим темно-синим цветом ссылки в момент клика на них */ a:active { color: darkblue; } /* При наведении курсора текст ссылки будет белого цвета на синем фоне */ a:hover { color: white; background-color: blue; } /* Если фокус переведен на любое поле "input" формы с классом "contact-form", границы этого поле изменят цвет */ .contact-form input:focus { border-color: #d3d3d3; } /* Белый цвет фона для активных полей форм */ input:enabled { background: white; } /* Затемним фон для полей формы, если они деактивированы */ input:disabled { background: lightgray; } /* Цвет фона чекбокса при выборе будет зеленым */ input[type="checkbox"]:checked { accent-color: green; } /* У формы с классом "contact-form" радиокнопки по умолчанию будут иметь тень */ .contact-form input[type="radio"]:default { box-shadow: 0 0 3px 3px gray; } /* Если значение поля формы валидно его типу (например, в поле типа email введен верный email), то граница поля будет серого цвета */ .contact-form input:valid { border-color: gray; } /* В случае невалидности значения поля формы определенного типа граница поля будет красной */ .contact-form input:invalid { border-color: red; } /* Обязательные поля имеют красную границу */ input:required { border-color: red; } /* Граница необязательных полей — светло-серая */ input:optional { border-color: lightgray; } /* Если в поле типа number вводится число, входящее в допустимый диапазон, граница поля будет серой */ input[type="number"]:in-range { border-color: gray; } /* Граница поля типа number будет красной, если в него вводится значение вне допустимого диапазона*/ input[type="number"]:out-of-range { border-color: red; }
Псевдоклассы структуры
К элементам этой группы стили применяются, в зависимости от положения этих элементов на странице. Если необходимо сделать так, чтобы у таблицы цвета строк чередовались, очень удобно использовать псевдоклассы этот типа. С их помощью мы можем задать для таблицы правило «каждая нечетная строка окрашивается в один цвет, а каждая четная — в другой», используя псевдоклассы :nth-child(odd)
и :nth-child(even)
.
Приведем описание таких псевдоклассов в таблице ниже.
Псевдокласс | К каким элементам применяются стили |
---|---|
:first-child | Первый дочерний элемент своего родителя |
:last-child | Последний дочерний элемент своего родителя |
:nth-child(n) | Каждый дочерний элемент, имеющий n порядковый номер у родителя. В качестве n используются числа, формулы или специальные слова odd и even. Например:
|
:nth-last-child(n) | Аналогичен :nth-child(n), но отсчет элементов идет с конца |
:only-child | Если такой элемент единственный у родителя |
:not(селектор) | Все элементы, кроме содержащих селектор, указанный в скобках |
:empty | Элементы, у которых нет дочерних элементов, включая текст |
:target | Элементы, имеющие id и к которым был осуществлен переход по «якорю». Например, пользователь нажал на ссылку вида <a href='#anchor'>Link</a> , которая направила его на элемент страницы <div id='anchor'>Section</div> |
/* Изменим цвет фона только первого элемента в списке */ li:first-child { background: #eee; } /* Сделаем фон последнего элемента отличным от остальных в списке */ li:last-child { background: #ccc; } /* Создадим чередование фона строк в таблице, закрашивая только четные строки */ tr:nth-child(even) { background: #eee; } /* Закрасим фон каждой третьей строки, начиная со второй строки с конца */ tr:nth-last-child(3n+2) { background: #eee; } /* Если элемент с классом "unique" является единственным дочерним элементом у своего родителя, то текст в "unique" получит жирное начертание */ .unique:only-child { font-weight: 700; } /* Изменен цвет всех элементов списка, кроме последнего */ li:not(:last-child) { background: #ccc; } /* Элемент списка будет спрятан, если он пустой */ li:empty { display: none; } /* Применим стили к элементу, которому пользователь был направлен при клике на "якорь" */ :target { background: blue; color: white; }
У некоторых из вышеперечисленных структурных псевдоклассов есть уточняющий по типу аналог, который выполняет те же функции, но применяет стили только к указанному типу селектора. К ним относятся: :first-of-type
, :last-of-type
, :nth-of-type(n)
, :nth-last-of-type(n)
, :only-of-child
.
Простой пример:
/* Начертание станет жирным у первого дочернего элемента "p" родителя, независимо от того, есть ли элементы другого типа перед этим параграфом */ p:first-of-type { font-weight: 700; }
Псевдоэлементы
Как можно догадаться из названия, псевдоэлементы — это такие элементы, которые фактически не существуют на HTML-странице. Они создаются средствами CSS. Их синтаксис идентичен синтаксису псевдоклассов: «селектор:псевдоэлемент».
Также присоединять псевдоэлементы к селектору можно и через двойное двоеточие
::
. Эта возможность была введена в CSS3. Но для совместимости со старыми браузерами рекомендуется устанавливать одно двоеточие, за исключением использования тех псевдоэлементов, которые были введены в CSS3.
Одним из наиболее популярных вариантов применения псевдоэлементов на практике является создание дополнительного слоя (наложения) над некоторым элементом документа, например, для покрытия изображения полупрозрачным фоном в качестве особого дизайнерского эффекта.
Также псевдоэлементы используются для придания некоторых декоративных свойств элементов: изменение стилей первой строки или буквы текста, выделения текста или стилизации подсказки placeholder элементов формы.
Дальше разберем несколько полезных псевдоэлементов.
Наиболее часто используемые псевдоэлементы — :before
и :after
. Их задачи очень похожи — добавить некоторый текст элементу, к которому они применены. Небольшое отличие состоит в том, что :before
добавляет этот текст в начале контента элемента, а :after
— после, о чем намекают названия псевдоэлементов. Текст добавляется с помощью CSS-свойства content
, которое является обязательным при использовании :before
и :after
, хотя это свойство особо не используется на практике.
Псевдоэлементы
:before
и:after
будут работать только с парными тегами. Их нельзя добавить, например, тегуimg
илиinput
. Также добавление CSS-свойстваcontent
является обязательным, чтобы псевдоэлемент работал. Необходимо добавлять это свойство, даже если его значение не нужно — в таком случае значением будет пустая строка (content: ""
).
В качестве примера применения этих псевдоэлементов приведем код создания наложения над блоком с изображением:
/* В блоке с классом "picture" есть изображение "img". Чтобы наложить полупрозрачный фон над этим изображением, используем этот код */ .picture { position: relative; width: 200px; height: 200px; } .picture:after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: blue; opacity: 0.2; }
Псевдоэлементы :first-letter
и :first-line
добавляют стили первой букве и первой строке текста в элементе соответственно. Причем :first-line
работает только с блочными элементами.
/* Первая буква элемента с классом "text" окрасится в красный цвет */ .text:first-letter { color: red; } /* Весь текст первой строки параграфа — красный */ p:first-line{ color: red; }
Чтобы применить стили к выделяемому с помощью курсора тексту, нужно использовать ::selection
(используем два двоеточия).
/* Фон выделяемого курсором текста будет зеленым */ .text::selection{ background: green; }
Стилизация текста подсказки placeholder у элементов формы реализуется с помощью псевдоэлемента ::placeholder
.
/* Подсказка поля формы будет серой */ input::placeholder { color: gray; }
Мы рассмотрели самые простые одиночные селекторы CSS. Далее в статье речь пойдет о том, как применять одни и те же CSS-правила для нескольких селекторов и как можно комбинировать селекторы. А также ознакомимся, как можно применять стили к элементам, в зависимости от отношений между ними.
Группировка селекторов
Часто бывает ситуация, когда один и тот же перечень CSS-правил нужно применить к нескольким селекторам. Чтобы не писать лишний код, целесообразно воспользоваться возможностью CSS, которая позволяет группировать селекторы, прописывая их через запятую.
Выглядит это следующим образом:
/* Подчеркнутый текст заголовков H3 и H4 */ h3, h4 { text-decoration: underline; }
Комбинирование селекторов
Для определенных целей стилизации иногда необходимо иметь возможность применять стили к одним элементам относительно расположения в DOM-дереве других. Это достигается, благодаря комбинированию селекторов.
В CSS существуют следующие комбинации селекторов:
- мультиселекторы одного элемента (
AB
); - селектор потомков (
A B
); - непосредственный дочерний селектор (
A > B
); - соседний селектор (
A + B
); - общий селектор соседей (
A ~ B
).
Мультиселекторы позволяют применить стили к элементу, который имеет все селекторы (AB
), содержащийся в мультиселекторе. Запись всех селекторов в CSS производится в ряд без пробелов.
Пример:
a.link[href^="https://www.domain.ru"]:first-child { color: red; }
Этот пример можно прочитать следующим образом: «Задать стили элементу, являющемуся первой дочерней ссылкой с классом .link
, которая ведет на https://www.domain.ru».
Селектор потомков (A B
) нужен для стилизации всех потомков B
элемента A
. Потомки — все элементы, вложенные в текущий элемент, независимо от уровня иерархии. A
и B
в этом случае разделяются пробелом.
/* Любой текст в теге "span" параграфа перейдет в верхний регистр, независимо от уровня вложенности */ p span { text-transform: uppercase; }
Непосредственный дочерний селектор (A > B
) подразумевает, что целевым элементом для стилизации будет дочерний элемент B
родительского элемента A
. В этом случае целевой элемент B
будет выбран только на следующем уровне иерархии под родителем A
, но не ниже.
/* Стилизация заголовка статьи произойдет, если этот заголовок находится на первом уровне вложенности у родителя */ article > h2 { font-weight: bold; }
Комбинация «Соседний селектор (А+B
)» используется, чтобы применить стили к соседнему по отношению к A
элементу B
, который расположен сразу после A
. Этой комбинацией удобно стилизовать, например, поле формы input
, которое идет сразу после label
.
/* Отступ слева для "label", который расположен сразу после "input" */ input + label { margin-left: 7px; }
Общий селектор соседей (A ~ B
) выбирает все соседние элементы B
, расположенные после соседнего элемента A
. У элементов A
и B
общий родитель.
/* Окрасим текст всех "span", идущих после "div" на одном уровне вложенности */ div ~ span { color: red; }
Вес селекторов
В CSS ситуация, когда одинаковые CSS-свойства прописываются разным селекторам (или комбинациям селекторов), указывающим на один и тот же элемент страницы, — довольно обычное явление. В этом случае к элементу применяются стили тех селекторов, которые имеют больший приоритет. Приоритетность селекторов определяется, благодаря наличию у них такого показателя, как вес (или специфичность).
Каждый селектор имеет вес, который рассчитывается с учетом содержимого, которое можно классифицировать следующим образом:
- внутренние (инлайн) стили — стили в значении атрибута
style
; - идентификаторы — атрибут
id
; - классы, псевдоклассы, атрибуты;
- теги, псевдоэлементы.
Вес высчитывают с помощью ряда из четырех чисел (X X X X
), суть которых можно выразить как «баллы за специфичность». Каждой позиции этого ряда добавляется единица, в зависимости от количества показателей, определяющих вес. Число на первой позиции имеет наибольшую важность. По направлению к четвертой позиции важность уменьшается.
Сравнивая эти баллы для конкурирующих селекторов, CSS понимает, какой из селекторов наиболее важен и применяет стили именно этого селектора. Сравнение происходит слева направо. Если число в первой позиции первого селектора больше, чем у его конкурента, то будут применены стили первого селектора. В случае равенства числе будут сравниваться последующие позиции, пока не будет найден приоритет.
При возникновении ситуации, когда специфичности обоих селекторов окажутся равными после сравнения баллов, CSS отдаст предпочтение тому селектору, который прописан в коде последним.
Если элемент, к которому применяются стили, содержит атрибут style
, то в первую позицию ряда добавляется единица. Единица во вторую позицию приплюсовывается, если есть селектор по идентификатору. Для классов, псевдоклассов и атрибутов зарезервирована третья позиция. Увеличиваем на единицу четвертую позицию, если имеем дело с селекторами по тегу и псевдоэлементами.
Универсальный селектор | Атрибут style | Идентификатор | Классы, псевдоклассы, атрибуты | Теги, псевдоэлементы |
---|---|---|---|---|
0 0 0 0 | 1 0 0 0 | 0 1 0 0 | 0 0 1 0 | 0 0 0 1 |
Что касается универсального селектора, то он не добавляет никакого веса (0 0 0 0).
Приведем примеры некоторых селекторов и расчет специфичности для них.
Селектор | Вес |
---|---|
* | 0 0 0 0 |
p | 0 0 0 1 |
.content | 0 0 1 0 |
#card-1 | 0 1 0 0 |
style="display: none;" | 1 0 0 0 |
ul > li | 0 0 0 2 |
.notification.show | 0 0 2 0 |
a:hover | 0 0 1 1 |
Задать наибольший приоритет селектору можно, благодаря ключевому слову !important
, которое добавляется в конец селектора. !important
перебивает любой вес. Если сравниваются селекторы, имеющими это ключевое слово, то специфичность определяется по вышеупомянутой методике с баллами.
.error { color: red!important; }
Использовать !important
нужно разумно и не злоупотреблять им, так как может возникнуть ситуация, что вариантов для маневрирования с весами будет очень мало — нужно будет постараться, чтобы создать селектор, имеющий больший приоритет, чем селектор с !important
, если появится такая необходимость. А если добавить !important
к CSS-свойству в атрибуте style
, будет получен самый большой вес, который невозможно будет перебить.
Подводя итог, отметим в качестве рекомендации, что при верстке желательно отдавать предпочтение классам:
- у них нет лимита по количеству на странице (как у идентификаторов);
- их можно делать уникальными (в то время как селектор тега ограничен в уникальности количеством существующих тегов);
- они оставляют достаточно пространства для маневра со специфичностью;
- они удобны для создания независимых блоков верстки, которые можно использовать много раз на странице, экономя время и делая код чистым, красивым и масштабируемым.
Насколько вам понятны возможности использования селекторов? Поделитесь своими мыслями в комментариях!