Селектор обобщенных родственных элементов

в 7:30, , рубрики: css, селекторы, метки: ,

В последующих нескольких абзацах я хочу подробнее рассмотреть селектор обобщенных родственных элементов (или ~) и область его возможного применения.
На написание данной статьи меня натолкнула малая распространённость информации о нём.

Что это такое?

Основная задача селектора обобщённых родственных элементов — выбор элемента (-ов), идущего после заданного элемента, и имеющего с ним общего родителя.
Обозначается всё это вот так:
A~B {style}, где A и B — строковые значения, определяющие селектор. style — применяемые свойства.
Пример
HTML:

<article>
    <h1>Заголовок</h1>
    <h2>Подзаголовок 1</h2>
    <p/>Это абзац с текстом
    <h2>Подзаголовок 2</h2>
    <span>Это текст, обрамлённый в span</span>
 </article>​ 

CSS:

h1~h2 {
    color:red;  
}​

В результате в красный цвет окрасятся заголовки h2, т.к. у них общий родительский элемент с заголовком h1, и в коде они стоят после него.

Демо.

Если же элемент будет стоять выше исходного, то он не будет выбран.

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

Пример

HTML:

<article>
    <h1>Заголовок</h1>
    <h2>Подзаголовок 1</h2>
    <p/>Это абзац с текстом
    <h2>Подзаголовок 2</h2>
    <p>Это второй абзац с текстом
      <span>Это текст, обрамлённый в span, который находится внутри абзаца</span>
    </p>
</article>​

CSS:

h1~span {
    color:red;  
}​

Демо.

В результате ничего не выделится красным, т.к. родитель элемента span — p, а элемента h1 — article.
Для того чтобы span стал красным, необходимо либо вынести его из абзаца на один уровень с h1, либо сделать так:

CSS:

h1~p span {
    color:red;  
}​

Демо.

Использование вместе с :hover

На мой взгляд, всю свою полезность селектор “A~B” проявляет в связке с событиями элементов, такими как :hover, :focus и др.
Если раньше можно было менять стиль элемента только при наведении указателя мыши на него самого, то использование селектора обобщенных родственных элементов позволяет поменять стиль элемента, отличного от того, на котором произошло событие.

Символически (в случае с :hover) это выглядит так:
A:hover ~ B{style}, где A — элемент, на который наведён указатель мыши, а на B распространяются новые стилевые правила.

Пример

HTML:

<body>
  <span>Наведи указатель на эту надпись и блоки станут зёлёными</span>
  <div>Блок №1</div>
  <div>Блок №2</div>
</body>​

CSS:

div{
 width:100px;
 height:50px;
 margin:5px;
 background:gray;   
}
​span:hover~div{
 background:green;
}​

Демо.

В результате, блоки станут зелёного цвета, при наведении на надпись.

Теперь пойдём дальше и присвоим элементам разные классы.
Пример

HTML:

<body>
  <span class="span1">Покрасить Блок №2 в зелёный цвет</span>
    <br/>
  <span class="span2">Покрасить Блок №1 в синий цвет</span>
  <div class="block1">Блок №1</div>
  <div class="block2">Блок №2</div>
</body>​
CSS:
span{
cursor:pointer;
}

div{
 width:100px;
 height:50px;
 margin:5px;
 background:gray;   
}

.span1:hover~.block2{
 background:green;   
}

.span2:hover~.block1{
 background:blue;   
}
​

Демо.

Можно применять вот так:
HTML:

<body>
  <span class="spanRed">Покрасить Блок в красный цвет</span>
    <br/>
  <span class="spanBlue">Покрасить Блок в синий цвет</span>
     <br/>
  <span class="spanGreen">Покрасить Блок в зелёный цвет</span>
    
  <div class="block">Блок</div>
</body>​

CSS:
span{
cursor:pointer;
}

div{
 width:100px;
 height:50px;
 margin:5px;
 background:gray;   
}

.spanRed:hover~.block{
 background:red;   
}
.spanBlue:hover~.block{
 background:blue;   
}
.spanGreen:hover~.block{
 background:green;   
}

Демо

Анимируем

Очень интересного эффекта можно достичь в совокупности с новыми возможностями CSS3. Например, в примере ниже используется свойство transition.

Пример

HTML:

<body>
  <span class="right">Вправо</span>
    
  <span class="left">Влево</span>
     
  <span class="top">Вверх</span>
    
  <span class="down">Вниз</span>
     <br/>
    
  <div class="block">Блок</div>
</body>​

CSS:
span{
position:absolute;
display:block;
width:100px;
height:50px;
margin:10px;
background:silver;
cursor:pointer;
}
.left{
    top:12%;
}
.right{
    top:12%;
    left:40%;
}
.top{
    left:20%;
}
.down{
     top:25%;
    left:20%;
}
.block{
 position:absolute;
 top:50%;
 right:50%;
 width:100px;
 height:50px;
 margin:5px;
 background:gray;
 -webkit-transition:all 2s ease;
 -o-transition:all 2s ease;    
 -moz-transition:all 2s ease;   
}
.right:hover~.block{
 right:10%;   
}
.left:hover~.block{
 right:90%;   
}
.top:hover~.block{
 top:10%;   
}
.down:hover~.block{
 top:90%;   
}

Демо

Как видите, у селектора обобщенных родственных элементов есть достаточное количество интересных способов применения. В последнее время CSS продвинулся далеко и позволяет реализовать то, что раньше возможно было только с использованием JavaScript.
Но всё-таки, на мой взгляд, если провести аналогии, CSS — это механическая составляющая (если угодно — “железо”) которая не предназначена для построения логики. JavaScript, например, может выступать в роли “программного обеспечения”.
Итак, в этой статье я попытался раскрыть тему селектора обобщенных родственных элементов. Получилось или нет, судить вам.

Ну и на последок (наведите на солнышко)

Автор: Niksg

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js