Что такое селектор в CSS
Селекторы в CSS позволяют установить связь одного правила с определенным элементом HTML. А также, чтобы задавать стили для отдельных элементов, игнорируя другие:

В этой статье мы рассмотрим способы определения стилей веб-страницы с помощью селекторов классов, селекторов потомков, псевдоклассов и селекторов идентификаторов.
- Настройка
- Селекторы классов
- Конвенция имен классов
- Более полезные div
- Дивы контейнеров
- Повторное использование стилей классов
- Изменение стилей классов
- Порядок имеет значение
- Селектор потомков
- Не переусердствуйте
- Псевдоклассы для ссылок
- Основные стили ссылок
- Состояние visited hover
- Состояние visited active
- Псевдоклассы для кнопок
- Элемент ссылки, а не элемент div
- Стили кнопок
- Другая кнопка
- Псевдоклассы для структуры
- Предостережения
- Селекторы идентификаторов
- Фрагменты URL-адресов
- Специфичность CSS
- Заключение
Настройка
Для примера нам нужен только один HTML-файл и таблица стилей CSS. Создайте папку css-selectors и веб-страницу под названием selectors.html со следующей разметкой:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Селекторы CSS</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<h1> Селекторы CSS</h1>
<p>Селекторы CSS позволяют <em>выбрать</em> отдельный HTML-элемент в документе HTML.
Это <strong>супер</strong> полезно.</p>
<p>Классы чрезвычайно важны, так как они позволяют выбрать
произвольные блоки на странице.</p>
<p>Мы так же рассмотрим в этом примере ссылки, поэтому вот ссылка
<a href='https://internetingishard.com'>Interneting Is Hard</a>, для которой нам нужно задать стили.</p>
<div>Кнопка Один</div>
</body>
</html>
Теперь создадим в той же папке файл styles.css. Это все, что понадобится для изучения CSS селекторов.
Селекторы классов
Селекторы классов позволяют применять стили CSS к определенному элементу HTML. Они дают возможность различать элементы HTML одного и того же типа. Например, когда есть два элемента <div>, но необходимо задать стили только для одного из них. Для селекторов классов нужны:
- Указанный атрибут класса в элементе HTML;
- Соответствующий селектор классов CSS.

Можно использовать селектор классов, чтобы назначить стили для первого абзаца нашей страницы-примера. Сначала добавим к нужному абзацу атрибут класса:
<p class='synopsis'> Селекторы CSS позволяют <em>выбрать</em> отдельный HTML-элемент в документе HTML. Это <strong>супер</strong> полезно.</p>
Теперь стилизуем абзац <p class='synopsis'> в файле CSS с помощью следующего кода:
.synopsis {
color: #7E8184; /* Светло серый */
font-style: italic;
}
Это правило применяется только к элементам с соответствующим атрибутом класса. Обратите внимание на точку (.) - префикс перед именем класса. Это отличает соседние селекторы CSS классов от селекторов типов:

Конвенция имен классов
Значение атрибута класса HTML может представлять собой почти все, что угодно, если оно соответствует селектору в коде CSS. Стандартная конвенция имен классов - это использование прописных букв и дефисов вместо пробелов, как в именах файлов и папок.
Добавление атрибута class не изменяет смысловое значение HTML-документа и служит для подключения CSS. Рекомендуется избегать имен классов, основанных на том, как они отображаются. Использование чего-то более семантического, например, .synopsis, дает больше свободы в действиях. Что позволяет настроить отображение этого абзаца.
Более полезные div
Атрибут class применяется не только к элементам <p> - он может быть использован для любого элемента HTML. Взяв на вооружение селекторы классов CSS, можно сделать блоки <div> и <span> намного более полезными. Мы можем использовать их для создания, как отдельных элементов, так и произвольных разделов веб-страницы:

Начнем с отдельных элементов. На этот раз мы будем использовать класс вместо CSS селектора div. Добавьте следующий код в файл styles.css:
.button {
color: #FFF;
background-color: #5995DA; /* Синий */
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063; /* Темно-серый */
border-radius: 5px;
width: 200px;
margin: 20px auto;
}
Конечно, для этого нам нужен соответствующий атрибут класса. Измените <div> в файле selectors.html на следующий код:
<div class='button'>Кнопка Один</div>
Данный код позволяет использовать стили и для других элементов, а не только для кнопок.
Дивы контейнеров
Помните, что <div> не изменяет семантическую структуру страницы. Это делает его отличным инструментом для определения представляемой структуры веб-страницы. Обертывая HTML-элементы в теги <div>, можно создать сайт с помощью более крупных фрагментов, не влияя на то, как поисковые системы просматривают наш контент:

Попробуем создать макет фиксированной ширины с использованием метода автополей. Сначала оберните весь документ в <div> и присвойте ему уникальный класс:
<body>
<div class='page'> <!-- Добавьте это -->
<h1> Селекторы CSS</h1>
<p class='synopsis'>Селекторы CSS позволяют <em>выбрать</em> отдельный HTML-элемент в документе HTML.
Это <strong>супер</strong> полезно.</p>
<p>Классы чрезвычайно важны,, так как они позволяют выбрать
произвольные блоки на странице.</p>
<p>Мы так же рассмотрим в этом примере ссылки, поэтому вот ссылка
<a href='https://internetingishard.com'>Interneting Is Hard</a>, для которой нам нужно задать стили.</p>
<div>Кнопка Один</div>
</div> <!-- Добавьте это -->
</body>
Затем добавьте следующий код в файл styles.css:
.page {
width: 600px;
margin: 0 auto;
}
Независимо от того, как будет изменяться размер окна браузера, веб-страница всегда будет иметь ширину 600 пикселей и выравниваться горизонтально по центру доступного пространства. Обратите внимание, что то же самое мы раньше делали для кнопки, но теперь мы делаем это с несколькими элементами одновременно, вложив их в общий контейнер:

Именно таким образом определяются более сложные макеты веб-страниц. Например, если на нашей странице была бы боковая панель, мы бы вложили все ее элементы в другой <div> с классом .sidebar.
Без CSS селекторов атрибутов классов, которые позволяют дифференцировать элементы <div>, ничего из этого не было бы возможно.
Повторное использование стилей классов
Один и тот же класс может применяться к нескольким элементам в рамках одного HTML-документа. Это означает, что можно использовать произвольные объявления CSS везде. Чтобы создать еще одну кнопку, нужно добавить еще один HTML-элемент с тем же классом:
<div class='button'>Кнопка Один</div>
<div class='button'>Кнопка Два</div>
В результате этого мы получим вторую кнопку, которая выглядит так же, как и первая. Это значительно упрощает работу веб-разработчиков. Если мы когда-нибудь захотим изменить цвет кнопки, нужно будет сделать это только в одном месте, и все наши кнопки автоматически обновятся:

Изменение стилей классов
Что, если мы захотим немного изменить вторую кнопку? К счастью, можно применить несколько классов к одному и тому же HTML-элементу. Стили из каждого класса будут применены к элементу, что даст возможность повторно использовать стили .button и одновременно переопределить некоторые из них новым классом:

Мы добавляем еще один класс к нашей второй кнопке с помощью следующей разметки. Обратите внимание, что несколько классов помещаются в один атрибут класса через пробелы:
<div class='button call-to-action'>Кнопка Два</div>
Этому элементу теперь присвоено два разных класса, и можно использовать любой из них для определения стилей. Это дает некоторые дополнительные возможности. Можно задать для второй кнопки стили класса .button и стили, относящиеся только к этой кнопке класса .call-to-action (обязательно добавьте этот код после правила .button):
.call-to-action {
font-style: italic;
background-color: #EEB75A; /* Желтый */
}
Порядок имеет значение
Хочу обратить ваше внимание на две важные вещи, касающиеся нашей второй кнопки:
- Это добавление нового объявления по сравнению с исходным правилом .button - font-style;
- Переопределение существующего в классе .button стиля - background-color.
Переопределение дочерних селекторов в CSS происходит из-за порядка размещения правил .call-to-action и .button в таблице стилей. Когда в файле CSS есть два противоречащих друг другу свойства, всегда применяется то, которое указано последним. Если бы вы разместили .call-to-action перед .button, применялось бы это правило, и кнопка осталась бы синей.
Это означает, что порядок атрибутов класса в HTML-элементе не влияет на поведение переопределения. Несколько классов в одном элементе применяются «одинаково», а приоритет определяется исключительно порядком размещения правил в файле styles.css.
Другими словами, следующие элементы эквивалентны:
<!-- В результате элементы будут отображаться на странице одинаково -->
<div class='button call-to-action'>Кнопка Два</div>
<div class='call-to-action button'>Кнопка Два</div>
Селектор потомков
Возможно, вы заметили, что <em> в нашем первом абзаце больше нельзя отличить от остального текста абзаца, так как правило .synopsis задает отображение курсивом всего текста абзаца.
Чтобы изменить этот элемент <em>, можно было бы добавить к нему еще один класс. Но это приведет к тому, что код будет не очень удобен. Мы хотим иметь правило .synopsis в качестве отдельного независимого компонента, для которого можно полностью задать стили через CSS. То есть без необходимости внесения изменений в HTML только для того, чтобы изменить какие-то стили:

Это то, для чего предназначены CSS селекторы потомков. Они позволяют настраивать только те элементы, которые находятся внутри другого элемента. Например, можно вывести этот элемент <em> в абзаце .synopsis со следующими стилями:
.synopsis em {
font-style: normal;
}
Добавление этого правила в файл styles.css задаст отображение <em> вертикальными (римскими) символами, тем самым определяя разницу с курсивным шрифтом, которым отображается весь абзац <p>. При этом остальных элементов <em>, размещенных на странице это изменение не коснется:

Селекторы потомков не ограничиваются селекторами классов. Таким образом, можно комбинировать любую другую группу селекторов. Например, если нужно выбрать только элементы <em> внутри заголовков:
h1 em {
/* определенные стили */
}
Не переусердствуйте
Можно вложить CSS селектор потомков настолько глубоко, насколько нужно, но не увлекайтесь. Все становится запутанно, когда вы начинаете писать правила, которые выглядят так:
/* Старайтесь избегать такого */
.article h2 .subheading em {
/* Конкретные стили */
}
Эти стили нельзя будет повторно использовать, поскольку они соответствуют только следующей структуре HTML:
<div class='article'>
<h2>
<span class='.subheading'>Это <em>на самом деле</em> особенный текст.</span>
</h2>
</div>
Если захотите применить эти стили к заголовку <h2>, который не был обернут в тег <div class = 'article'>, придется здорово поломать голову. Та же ситуация, если вы захотите применить их к заголовку <h3>.
Псевдоклассы для ссылок
До сих пор все селекторы CSS, которые мы рассматривали, были связаны непосредственно с фрагментами HTML-разметки. Тем не менее, на отображаемой веб-странице происходит больше, чем задает HTML-контент. Существует «стандартный» перечень действий, которые может предпринять пользователь.
Классический пример - это ссылка. Веб-разработчик создает элемент <a href>. После того как браузер отобразил его, пользователи могут взаимодействовать с этой ссылкой: навести на нее курсор мыши, кликнуть ссылку и перейти по ней:

Псевдоклассы CSS предоставляют механизм для подключения к таким действиям пользователя. В любой момент времени элемент <a href> может находиться в нескольких состояниях, и можно использовать псевдоклассы для определения отдельных стилей для каждого из этих состояний. Можно представить их как селекторы классов, которые не нужно писать самостоятельно, потому что они встроены в браузер.
Основные стили ссылок
В отличие от CSS селекторов псевдоклассы начинаются с двоеточия, за которым следует имя класса. Наиболее распространенными псевдоклассами ссылок являются:
- :link - ссылка, по которой пользователь еще не переходил;
- :visited - ссылка, по которой пользователь переходил раньше;
- :hover - ссылка, на которую пользователь навел курсор мыши;
- :active - ссылка, нажатая мышью (или пальцем).
Рассмотрим эти псевдоклассы, добавив следующие правила в CSS (также обратите внимание на то, что мы используем для обозначения цветов ключевые слова, а не шестнадцатеричные коды):
a:link {
color: blue;
text-decoration: none;
}
a:visited {
color: purple;
}
a:hover {
color: aqua;
text-decoration: underline;
}
a:active {
color: red;
}
Состояние visited hover
Приведенный выше фрагмент кода отлично подходит для большинства сайтов, но давайте более внимательно рассмотрим поведение a:visited, когда мы изменим атрибут href на URL-адрес, который раньше посещали. Стиль a:hover применяется как к ранее посещенным ссылкам, так и к тем, по которым мы еще не переходили. Можно еще больше модифицировать ссылки, объединив псевдоклассы.
Добавьте это правило ниже предыдущего фрагмента кода:
a:visited:hover {
color: orange;
}
Данный код создает специальный стиль для состояния при наведении курсора мыши на посещенные ранее ссылки. Наведя курсор на не посещенную ранее ссылку, мы увидим, что она «перекрашивается» в аквамариновый цвет. А при наведении курсора на посещенную ссылку она становится оранжевой. Фантастика! Но это ломает наш стиль a:active из-за некоторых внутренних аспектов CSS, о которых вы никогда не захотите читать. Когда вы нажмете на ссылку, она больше не будет становиться красной.
Состояние visited active
Можно исправить это с помощью CSS псевдоселектора a:visited:active. Добавьте следующий код в конец таблицы стилей. Обратите внимание, что, как и в случае с классом .call-to-action, порядок, в котором правила определяются в файле styles.css, имеет значение:
a:visited:active {
color: red;
}
Эти два последних раздела позволят задавать стили посещенных ссылок полностью отдельно от не посещенных.
Псевдоклассы для кнопок
Псевдоклассы предназначены не только для определения стилей ссылок. Вместо указания стилей для класса a:link и потомков изменим с помощью псевдоклассов класс .button. Это позволит создавать кнопки, которые ведут куда-то.
Элемент ссылки, а не элемент div
Сначала нужно изменить кнопки, чтобы они стали элементами <a href>, а не просто элементами <div>, как показано ниже:
<a class='button' href='nowhere.html'>Кнопка Один</a>
<a class='button call-to-action' href='nowhere.html'>Кнопка Два</a>
Если вы перезагрузите документ в браузере, то увидите, что некоторые стили больше не действуют. Хотя мы используем одни и те же классы. Это связано с тем, что <a> является встроенным элементом, а также имеет значение цвета по умолчанию:

Нам нужно снова сделать этот элемент блочным и удалить часть стилей ссылок по умолчанию.
Стили кнопок
Начнем с :link и :visited. Мы используем аналогичный подход, что и в предыдущем разделе о CSS селекторах родителя. Но поскольку это кнопки, то мы сохраним одинаковые цвета для состояний посещенная и не посещенная. Измените существующие правила .button следующим образом:
.button:link, /* Измените это */
.button:visited { /* Измените это */
display: block; /* Добавьте это */
text-decoration: none; /* Добавьте это */
color: #FFF; /* Все остальное остается без изменений */
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;
width: 200px;
margin: 20px auto;
}
Обратите внимание на новые псевдоклассы :link и :visited в селекторе. Без них стиль браузера по умолчанию для a:link не изменился бы. Теперь оформим состояние при наведении курсора.
.button:hover,
.button:visited:hover {
color: #FFF;
background-color: #76AEED; /* Light blue */
}
Обе наши кнопки при наведении курсора будут окрашиваться в более светлый голубой цвет. Сделаем так, чтобы кнопки становились темнее, когда пользователь нажимает на них с помощью псевдокласса :active:
.button:active,
.button:visited:active {
color: #FFF;
background-color: #5995DA; /* Blue */
}
Стили, которые мы только что определили, готовы к повторному использованию. Назначьте класс .button любому HTML-элементу, и вы превратите его в интерактивную кнопку.
Другая кнопка
Займемся второй кнопкой. Предполагается, что она имеет желтый фон, но мы изменили это кодом из предыдущего раздела. Наш селектор .button:link более «специфичен», чем текущее правило .call-to-action, поэтому он имеет приоритет.
Исправим такое положение вещей, применив к нашему правилу .call-to-action несколько псевдоклассов. Замените существующее правило следующим (убедитесь, что это определено после новых стилей .button из предыдущего раздела о дочерних селекторах в CSS):
.call-to-action:link,
.call-to-action:visited {
font-style: italic;
background-color: #EEB75A; /* Желтый */
}
.call-to-action:hover,
.call-to-action:visited:hover {
background-color: #F5CF8E; /* Светло-желтый */
}
.call-to-action:active,
.call-to-action:visited:active {
background-color: #EEB75A; /* Желтый */
}
Мы назначили класс .call-to-action только для второй кнопки, поэтому только она станет желтой. Конечно, нам по-прежнему нужно, чтобы класс .button был назначен для обоих элементов <a>, поскольку он определяет общие стили, такие как отступы, радиус границы и размер шрифта.
Псевдоклассы для структуры
Состояния ссылок – это лишь один аспект псевдоклассов. Существует также множество других псевдоклассов, которые предоставляют дополнительную информацию о контексте элемента. Например, псевдокласс last-of-type выбирает последний элемент определенного типа в родительском элементе. Это является альтернативой селекторам классов.
Например, мы могли бы использовать :last-of-type, чтобы добавить в наш пример определенное пространство после последнего абзаца страницы:
p:last-of-type {
margin-bottom: 50px;
}
Это позволяет не затрагивать первые два элемента <p> на странице, не добавляя для последнего абзаца новый атрибут класса:

Можно даже использовать псевдокласс :first-of-type вместо класса .synopsis. Заменив существующее правило .synopsis следующим фрагментом кода, мы получим тот же результат:
p:first-of-type {
color: #7E8184;
font-style: italic;
}
Использование этого метода вместо устаревших классов имеет свои преимущества и недостатки. Например, это работает только в том случае, если наш синопсис является элементом <p>. Если бы мы захотели создать синтаксис с несколькими параграфами, объединив много элементов <p> в <div class='synopsis'>, нам пришлось бы переписать наш CSS-код. С другой стороны, псевдоклассы позволяют задавать стили для определенных элементов, не изменяя HTML. Это дает нам четкое разделение контента от представления.
Предостережения
Но псевдоклассы немного сложнее. Контекстные селекторы CSS first-of-type и last-of-type действуют только внутри своего родительского элемента. Другими словами, p:first-of-type выбирает первый элемент <p> в каждом элементе контейнера.
У нас есть один общий <div>, который обертывает контент (.page), поэтому для нас это не проблема. Но что произойдет, если мы добавим следующий код в нижнюю часть элемента .page:
<div class='sidebar'>
<p>If this page had a sidebar...</p>
<p>We’d have some problems with pseudo-classes.</p>
</div>
Это иллюстрирует сложность применения псевдоклассов для структуры. Первый элемент <p> здесь также будет соответствовать p:first-of-type, потому что область применения псевдокласса ограничена родительским элементом.
Если вы не хотите затрагивать абзацы в боковой панели, и выбрать только первый <p> в контейнере <div class='page'>, то нужно ограничить область его применения с помощью селектора дочерних элементов. Например:
.page > p:first-of-type {
color: #7E8184;
font-style: italic;
}
Различные разработчики придерживаются разных «школ». Некоторым нравится семантическая природа псевдоклассов, в то время как другие доводят до крайности применение различных подробных атрибутов класса для каждого HTML-элемента.
Селекторы идентификаторов
CSS селекторы идентификаторов – альтернатива селекторам классов. Они работают почти так же, но на странице может размещаться только один элемент с определенным идентификатором. Это означает, что вы не сможете повторно использовать стили.
Вместо атрибута class для любого элемента HTML, используется атрибут id. Попробуйте добавить идентификатор ко второй кнопке:
<a id='button-2' class='button' href='nowhere.html'>Кнопка Два</a>
Соответствующий селектор CSS должен начинаться с символа хэша (#). Добавление следующего кода в файл styles.css изменит цвет текста желтой кнопки:
#button-2 {
color: #5D6063; /* Dark gray */
}
Проблема в том, что если мы захотим задать этот стиль и для другой кнопки, то нужно присвоить ей еще один уникальный атрибут id. Довольно скоро наш CSS начнет выглядеть довольно «грязно»:
/* (Это тяжело поддерживать) */
#button-2,
#button-3,
#checkout-button,
#menu-bar-call-to-action {
color: #5D6063;
}
По этой причине использовать CSS селекторы идентификаторов обычно не рекомендуется. Вместо этого используйте селекторы классов.
Фрагменты URL-адресов
Атрибуты id должны быть уникальными, поскольку на них указывают «фрагменты URL-адресов». Фрагменты - это элементы, с помощью которых можно указать пользователям на определенную часть веб-страницы. Они выглядят как селекторы идентификаторов, расположенные в конце URL-адреса:

Например, если мы хотим указать пользователю на вторую кнопку, можно использовать следующий код. Обратите внимание, что можно полностью опустить URL-адрес, если он указывает на другой раздел той же веб-страницы:
<!-- С той же страницы -->
<a href='#button-2'>Go to Button Two</a>
<!-- С другой страницы -->
<a href='selectors.html#button-2'>Go to Button Two</a>
Если вы добавите первый вариант ссылки в разметку страницы selectors.html и кликните по ней, то увидите, что данный URL-адрес значится в адресной строке браузера. Чтобы увидеть, как осуществляется переход ко второй кнопке, нужно добавить на страницу немного произвольного контента или сделать высоту окна маленькой:

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

Но не все селекторы CSS равнозначны. «Специфичность CSS» - это значимость, установленная для различных категорий селекторов. Это означает, что некоторые селекторы всегда будут переопределять другие независимо от того, какую позицию они занимают в таблице стилей.
Если вы добавите следующий код после существующих правил .call-to-action, он переопределит заданный ранее цвет фона. Если вы разместите его в верхней части файла, он сам будет переопределен, и наша кнопка не станет красной. Это ожидаемое поведение:
.call-to-action:link,
.call-to-action:visited {
background-color: #D55C5F; /* Красный */
}
Теперь посмотрите, что происходит, когда мы пытаемся сделать то же самое с помощью селектора идентификатора. Во-первых, обязательно удалите предыдущий фрагмент кода, а затем попробуйте добавить приведенный ниже код до существующих правил .call-to-action:
#button-2 {
background-color: #D55C5F; /* Красный */
}
CSS селекторы идентификаторов имеют более высокую специфичность, чем селекторы классов, поэтому вторая кнопка будет красной, даже если мы зададим фоновый цвет с помощью .call-to-action:link ниже. Концепция «порядок имеет значение» работает только тогда, когда все правила имеют одинаковую специфичность:

Специфичность селекторов, которые мы рассматривали в этой статье, показана ниже: от максимальной до минимальной:
• #button-2
• .button:link и .synopsis em (они равнозначны)
• .button
• a:link
• a
Иногда это приводит к путанице. Это настолько серьезная проблема, что была разработана целая методология под названием «BEM». Суть BEM заключается в попытке обеспечить то, чтобы правила CSS были многоразовыми, сделав все селекторами классов. Это исключает возможность возникновения проблем.
Заключение
В этой статье вы получили практический опыт работы с CSS селекторами классов, селекторами потомков, псевдоклассами, стилями ссылок и селекторами идентификаторов. Цель всех, описанных в этой статье приемов – обеспечить возможность указать определенный HTML-элемент из CSS-кода. Селекторы классов являются самыми универсальными и имеют наименьшее количество недостатков.