Когда мы делали Шар судьбы на CSS, то встретили там родственные селекторы. Тогда мы про это поговорили вскользь, теперь разберём поглубже. Заодно посмотрим на соседние селекторы в CSS.
Что такое селектор и зачем он нужен
Селектор в CSS — это когда мы за один раз выбираем все элементы, которые подходят под нужные нам критерии.
Например, на странице везде у нас установлен размер шрифта в 14 пикселей, а мы хотим сделать так, чтобы первый абзац после каждого подзаголовка был красным. Для этого можно сделать отдельный стиль и привязать его ко всем первым абзацам в разделах, но у такого решения есть минус. Если мы будем добавлять текст в какие-то разделы, то нам нужно будет следить за тем, чтобы указанный стиль был прописан только у первого абзаца. Это легко сделать, когда на сайте одна страница, а если их сто и все постоянно обновляются?
Чтобы не искать все первые абзацы вручную, используют селекторы — в них указывают нужные критерии, а браузер сам смотрит, какие элементы под них подходят. Как только что-то подходит — к нему применяется стиль, прописанный в этом селекторе.
Соседние селекторы
Для создания соседнего селектора в CSS используется плюс:
элемент_1 + элемент_2 {
// описание стиля
}
Он сработает только в том случае, когда второй элемент на странице идёт сразу после первого. В примере из начала статьи стоит такая задача: выделить красным цветом все первые абзацы разделов — те, которые идут сразу после заголовков второго уровня. Чтобы автоматически найти все такие абзацы, используем соседний селектор:
h2 + p {
// стиль первого абзаца
}
Если после подзаголовка идёт, например, картинка, а только потом абзац — стиль не сработает, потому что элементы должны быть соседями, отсюда и название. Сделаем страницу с соседними селекторами и покрасим первые абзацы в красный. За основу возьмём статью про спринты в программировании:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Соседние селекторы</title>
<style type="text/css">
body {
font-family: Arial;
font-size: 16px;
}
/* используем соседний селектор */
h2 + p {
color: red;
}
</style>
</head>
<body>
<h1>Что такое спринты в программировании</h1>
<h2>Ситуация</h2>
<!-- это будет красным -->
<p>У команды разработчиков есть большой проект, где нужно сделать много разных вещей:</p>
<!-- а это — нет -->
<p>— придумать архитектуру всего сервиса,<br>
— написать серверную часть,<br>
— сделать вёрстку и дизайн для мобильных приложений,<br>
— выпустить сайт, который может делать то же самое, что и приложения,<br>
— предусмотреть интеграцию с другими сервисами,<br>
— сделать авторизацию через популярные соцсети.</p>
<p>Времени на всё — 6 месяцев, и кажется, что этого достаточно. Но это может быть обманчиво, потому что команда расслабляется, каждый начинает делать что-то своё, а за месяц до финала выясняется, что вместе эти отдельные части работать не будут. Например, сервер не отдаёт данные в нужном формате для веб-страницы, приложения хранят данные только у себя и не умеют отправлять их на сервер, а авторизация в соцсетях работает только на Андроиде.</p>
<h2>Что такое спринт</h2>
<p>Спринт — это небольшой фиксированный отрезок времени, в который команда делает какую-то ограниченную часть проекта. Например, команда может двигаться двухнедельными спринтами, с каждым спринтом добавляя в проект новые возможности. </p>
<p>Задача спринта — чтобы по его итогу что-то работало. Например, если мы взяли в спринт единую авторизацию в сервисе, то к концу спринта она должна работать и быть протестированной. Нельзя к концу спринта сказать «Ой, ну ничего, в следующий раз доделаем». К концу спринта должно быть готово.</p>
</body>
</html>
Родственные селекторы
Если соседние селекторы выбирают тех, кто стоит рядом по соседству, то родственные выбирают те элементы, у которых есть общий родитель и которые стоят на одном уровне вложенности. Для обозначения родственного селектора используется тильда:
элемент_1 ~ элемент_2 {
// описание стиля
}
Работает это так:
- Браузер находит первый элемент.
- Смотрит, есть ли на одном уровне с ним вторые элементы.
- Если есть — проверяет, у них один родитель или нет.
- Если один — применяется указанный стиль.
Звучит сложновато, покажем на примере. Допустим, мы хотим, чтобы в основной статье все заголовки второго уровня, которые идут после первого, были написаны тонким шрифтом. Для этого мы создаём родственный селектор:
h1 ~ h2 {
font-weight: 100;
}
Общий родитель у них — это тег <body>, оба тега вложены внутрь на одном уровне. Если мы добавим этот селектор в стили из предыдущего примера, то получим тонкие заголовки второго уровня:
А теперь добавим внутрь страницы врезку, где тоже будет заголовок второго уровня. К нему этот стиль с тонким начертанием уже не применится — у него нет общего родителя с заголовком h1. Следите за руками:
- у заголовков h1 и h2 без врезки общий родитель — <body>;
- у заголовка h1 и заголовка h2 внутри врезки нет общего родителя, потому что родитель для h1 — это <body>, а для h2 внутри врезки родитель — <div>, внутри которого он находится.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Соседние селекторы</title>
<style type="text/css">
body {
font-family: Arial;
font-size: 16px;
}
/* используем соседний селектор */
h2 + p {
color: red;
}
/* используем родительский селектор */
h1 ~ h2 {
font-weight: 100;
}
</style>
</head>
<body>
<h1>Что такое спринты в программировании</h1>
<h2>Ситуация</h2>
<!-- это будет красным -->
<p>У команды разработчиков есть большой проект, где нужно сделать много разных вещей:</p>
<!-- а это — нет -->
<p>— придумать архитектуру всего сервиса,<br>
— написать серверную часть,<br>
— сделать вёрстку и дизайн для мобильных приложений,<br>
— выпустить сайт, который может делать то же самое, что и приложения,<br>
— предусмотреть интеграцию с другими сервисами,<br>
— сделать авторизацию через популярные соцсети.</p>
<p>Времени на всё — 6 месяцев, и кажется, что этого достаточно. Но это может быть обманчиво, потому что команда расслабляется, каждый начинает делать что-то своё, а за месяц до финала выясняется, что вместе эти отдельные части работать не будут. Например, сервер не отдаёт данные в нужном формате для веб-страницы, приложения хранят данные только у себя и не умеют отправлять их на сервер, а авторизация в соцсетях работает только на Андроиде.</p>
<div style="background-color: yellow; padding-bottom: 10px;">
<h2>Что делают в спринте</h2>
<p>Цели у спринта могут быть общими для всей команды. Например:</p>
<p>— сделать единую авторизацию и протестировать её на всех платформах,<br>
— настроить синхронизацию между устройствами,<br>
— выработать единую систему сообщений об ошибках.</p>
</div>
<h2>Что такое спринт</h2>
<p>Спринт — это небольшой фиксированный отрезок времени, в который команда делает какую-то ограниченную часть проекта. Например, команда может двигаться двухнедельными спринтами, с каждым спринтом добавляя в проект новые возможности. </p>
<p>Задача спринта — чтобы по его итогу что-то работало. Например, если мы взяли в спринт единую авторизацию в сервисе, то к концу спринта она должна работать и быть протестированной. Нельзя к концу спринта сказать «Ой, ну ничего, в следующий раз доделаем». К концу спринта должно быть готово.</p>
</body>
</html>
Что дальше
Кроме этих ещё есть дочерний селектор и селектор атрибутов. Про них — в другой раз.