Есть ли селектор CSS «предыдущий брат»? - PullRequest
1191 голосов
/ 30 ноября 2009

Знак плюс (+) предназначен для следующего брата. Есть ли эквивалент для предыдущего брата?

Ответы [ 15 ]

746 голосов
/ 30 ноября 2009

Нет, селектор «предыдущий брат» отсутствует.

В связанной заметке, ~ для родного брата-наследника (то есть элемент идет после этого, но не обязательно сразу после) и является селектором CSS3. + для следующего брата и является CSS2.1.

См. Комбинированный элемент смежного брата из Селекторный уровень 3 и 5.7 Селекторы соседнего брата из Каскадные таблицы стилей Уровень 2 Редакция 1 (CSS 2.1) Спецификация .

203 голосов
/ 17 января 2015

Я нашел способ стилизовать всех предыдущих братьев и сестер (в отличие от ~), который может работать в зависимости от того, что вам нужно.

Допустим, у вас есть список ссылок, и при наведении на одну из них все предыдущие должны стать красными. Вы можете сделать это так:

/* default link color is blue */
.parent a {
  color: blue;
}

/* prev siblings should be red */
.parent:hover a {
  color: red;
}
.parent a:hover,
.parent a:hover ~ a {
  color: blue;
}
<div class="parent">
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
</div>
142 голосов
/ 19 марта 2013

Селектор уровня 4 вводит :has() (ранее указатель субъекта !), что позволит вам выбрать предыдущего брата с помощью:

previous:has(+ next) {}

… но на момент написания этой статьи это далеко за гранью поддержки браузера.

126 голосов
/ 20 марта 2016

Рассмотрим свойство order макетов flex и grid.

Я сконцентрируюсь на flexbox в примерах ниже, но те же понятия применимы к Grid.


С помощью flexbox можно смоделировать предыдущий селектор брата.

В частности, свойство flex order может перемещать элементы по экрану.

Вот пример:

Вы хотите, чтобы элемент A становился красным при наведении на элемент B.

<ul>
    <li>A</li>
    <li>B</li>
</ul>

ШАГОВ

  1. Сделать ul гибкий контейнер.

    ul { display: flex; }
    

  1. Обратный порядок братьев и сестер в разметке.

    <ul>
       <li>B</li>
       <li>A</li>
    </ul>
    

  1. Используйте селектор брата для выбора элемента А (подойдет ~ или +).

    li:hover + li { background-color: red; }
    

  1. Используйте свойство flex order для восстановления порядка братьев и сестер на визуальном дисплее.

    li:last-child { order: -1; }
    

... и вуаля! Родился предыдущий селектор брата (или, по крайней мере, имитированный).

Вот полный код:

ul {
    display: flex;
}

li:hover + li {
    background-color: red;
}

li:last-child {
    order: -1;
}

/* non-essential decorative styles */
li {
    height: 200px;
    width: 200px;
    background-color: aqua;
    margin: 5px;
    list-style-type: none;
    cursor: pointer;
}
<ul>
    <li>B</li>
    <li>A</li>
</ul>

Из спецификации flexbox:

5,4. Порядок отображения: свойство order

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

Свойство order управляет порядком, в котором элементы flex отображаются в контейнере flex, назначая их порядковым группам. Он принимает одно значение <integer>, которое указывает, какая порядковая группа гибкого элемента принадлежит.

Начальное значение order для всех изгибаемых элементов равно 0.

Также см. order в спецификации CSS Grid Layout .


Примеры «предыдущих селекторов братьев и сестер», созданных с помощью свойства flex order.

.container { display: flex; }

.box5 { order: 1; }    
.box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }

.box6 { order: -4; }
.box7 { order: -3; }
.box8 { order: -2; }
.box9 { order: -1; }
.box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;
                                              font-size: 1.5em; }
.box12 { order: 2; }
.box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;
                                        font-size: 1.5em; }
.box21 { order: 1; }
.box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }

/* non-essential decorative styles */
.container {
    padding: 5px;
    background-color: #888;
}
.box {
    height: 50px;
    width: 75px;
    margin: 5px;
    background-color: lightgreen;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    cursor: pointer;
}
<p>
Using the flex <code>order</code> property to construct a previous sibling selector
</p>

<div class="container">
    <div class="box box1"><span>1</span></div>
    <div class="box box2"><span>2</span></div>
    <div class="box box3"><span>3</span></div>
    <div class="box box5"><span>HOVER ME</span></div>
    <div class="box box4"><span>4</span></div>
</div>

<br>

<div class="container">
    <div class="box box9"><span>HOVER ME</span></div>
    <div class="box box12"><span>HOVER ME</span></div>
    <div class="box box6"><span>6</span></div>
    <div class="box box7"><span>7</span></div>
    <div class="box box8"><span>8</span></div>
    <div class="box box10"><span>10</span></div>
    <div class="box box11"><span>11</span></div>
</div>

<br>

<div class="container">
    <div class="box box21"><span>HOVER ME</span></div>
    <div class="box box13"><span>13</span></div>
    <div class="box box14"><span>14</span></div>
    <div class="box box15"><span>15</span></div>
    <div class="box box16"><span>16</span></div>
    <div class="box box17"><span>17</span></div>
    <div class="box box18"><span>18</span></div>
    <div class="box box19"><span>19</span></div>
    <div class="box box20"><span>20</span></div>
</div>

jsFiddle


Примечание к сведению & ndash; Два устаревших представления о CSS

Flexbox разрушает давние представления о CSS.

Одно из таких убеждений состоит в том, что предыдущий селектор брата не возможен в CSS .

Сказать, что это убеждение широко распространено, было бы преуменьшением. Вот несколько вопросов, связанных с переполнением стека:

Как описано выше, это убеждение не совсем верно. Предыдущий селектор родного брата может быть смоделирован в CSS с помощью свойства flex order.

z-index Миф

Другое давнее убеждение заключается в том, что z-index работает только на позиционированных элементах.

На самом деле, самая последняя версия спецификации & ndash; W3C Editor's Draft & ndash; по-прежнему утверждает, что это правда:

9.9.1 Задание уровня стека: z-index свойство

z-index

  • Значение: авто | | наследовать
  • По умолчанию: авто
  • Относится к: позиционированным элементам
  • Наследуется: нет
  • Проценты: N / A
  • Носитель: визуальный
  • Расчетное значение: как указано

(выделение добавлено)

Однако в действительности эта информация устарела и неточна.

Элементы, которые гибкие элементы или элементы сетки могут создавать стеки контексты, даже когда position равен static.

4,3. Гибкий элемент Z-Ordering

Элементы Flex отображаются точно так же, как и встроенные блоки, за исключением того, что вместо необработанных документов используется порядок документов с измененным порядком. порядок документа и значения z-index, отличные от auto, создают контекст стека, даже если position равно static.

5,4. Ось Z Порядок: свойство z-index

Порядок рисования элементов сетки точно такой же, как у встроенных блоков, за исключением того, что порядок документов с измененным порядком равен используется вместо исходного порядка документов, и значения z-index, отличные от auto, создают контекст стека, даже если position это static.

Вот демонстрация z-index работы с не позиционированными гибкими элементами: https://jsfiddle.net/m0wddwxs/

65 голосов
/ 30 ноября 2011

У меня был тот же вопрос, но потом у меня был "дух" момент. Вместо написания

x ~ y

написать

y ~ x

Очевидно, что это соответствует «х» вместо «у», но отвечает «есть совпадение?» вопрос, и простой обход DOM может привести вас к нужному элементу более эффективно, чем зацикливание в JavaScript.

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

24 голосов
/ 19 августа 2015

Два трюка . В основном инвертирование порядка HTML ваших желаемых элементов в HTML и использование
~ Следующие братья и сестры оператор:

float-right + в обратном порядке элементов HTML

div{ /* Do with the parent whatever you know just to make the
  inner float-right elements appear where desired */
  display:inline-block;
}
span{
  float:right;  /* float-right the elements! */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
  background:red;
} 
<div>
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>

Родитель с direction: rtl; + в обратном порядке внутренних элементов

.inverse{
  direction: rtl;
  display: inline-block; /* inline-block to keep parent at the left of window */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
  background:gold;
}
Hover one span and see the previous elements being targeted!<br>

<div class="inverse">
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>
17 голосов
/ 25 апреля 2017

+ для следующего брата. Есть ли эквивалент для предыдущего двойники?

Вы можете использовать два селектора ax : ! и ?

В обычном CSS есть 2 последующие селекторы одноуровневых :

  • + - это немедленный последующий селектор брата
  • ~ - это любой последующий селектор брата

В обычном CSS нет предыдущего селектора родного брата .

Однако в библиотеке постпроцессора CSS ax есть 2 предыдущих селекторов родного брата :

  • ? - предыдущий предыдущий селектор брата (противоположный +)
  • ! - это любой предыдущий селектор брата (напротив ~)

Рабочий пример:

В приведенном ниже примере:

  • .any-subsequent:hover ~ div выбирает любой последующий div
  • .immediate-subsequent:hover + div выбирает непосредственное последующее div
  • .any-previous:hover ! div выбирает любой предыдущий div
  • .immediate-previous:hover ? div выбирает непосредственно предыдущий div

div {
  display: inline-block;
  width: 60px;
  height: 100px;
  color: rgb(255, 255, 255);
  background-color: rgb(255, 0, 0);
  text-align: center;
  vertical-align: top;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.6s ease-out;
}

code {
  display: block;
  margin: 4px;
  font-size: 24px;
  line-height: 24px;
  background-color: rgba(0, 0, 0, 0.5);
}

div:nth-of-type(-n+4) {
  background-color: rgb(0, 0, 255);
}

div:nth-of-type(n+3):nth-of-type(-n+6) {
  opacity: 1;
}

.any-subsequent:hover ~ div,
.immediate-subsequent:hover + div,
.any-previous:hover ! div,
.immediate-previous:hover ? div {
  opacity: 1;
}
<h2>Hover over any of the blocks below</h2>

<div></div>
<div></div>

<div class="immediate-previous">Hover for <code>?</code> selector</div>
<div class="any-previous">Hover for <code>!</code> selector</div>
<div class="any-subsequent">Hover for <code>~</code> selector</div>
<div class="immediate-subsequent">Hover for <code>+</code> selector</div>

<div></div>
<div></div>

<script src="https://rouninmedia.github.io/axe/axe.js"></script>
15 голосов
/ 14 января 2017

Еще одно решение flexbox

Вы можете использовать обратный порядок элементов в HTML. Затем, кроме использования order, как в Michael_B в ответе , вы можете использовать flex-direction: row-reverse; или flex-direction: column-reverse; в зависимости от вашего макета.

Рабочий образец:

.flex {
  display: flex;
  flex-direction: row-reverse;
   /* Align content at the "reversed" end i.e. beginning */
  justify-content: flex-end;
}

/* On hover target its "previous" elements */
.flex-item:hover ~ .flex-item {
  background-color: lime;
}

/* styles just for demo */
.flex-item {
  background-color: orange;
  color: white;
  padding: 20px;
  font-size: 3rem;
  border-radius: 50%;
}
<div class="flex">
  <div class="flex-item">5</div>
  <div class="flex-item">4</div>
  <div class="flex-item">3</div>
  <div class="flex-item">2</div>
  <div class="flex-item">1</div>
</div>
14 голосов
/ 03 сентября 2014

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

Что вы можете сделать, это использовать селектор CSS3: псевдокласс, называемый nth-child()

#list>* {
  display: inline-block;
  padding: 20px 28px;
  margin-right: 5px;
  border: 1px solid #bbb;
  background: #ddd;
  color: #444;
  margin: 0.4em 0;
}

#list :nth-child(-n+4) {
  color: #600b90;
  border: 1px dashed red;
  background: orange;
}
<p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>

<div id="list">
  <span>1</span><!-- this will be selected -->
  <p>2</p><!-- this will be selected -->
  <p>3</p><!-- this will be selected -->
  <div>4</div><!-- this will be selected -->
  <div>5</div>
  <p>6</p>
  <p>7</p>
  <p>8</p>
  <p>9</p>
</div>

Ограничения

  • Невозможно выбрать предыдущие элементы на основе классов следующих элементов
  • Это то же самое для псевдоклассов
4 голосов
/ 29 августа 2014

Если вы знаете точную позицию, сработает :nth-child() исключение всех следующих братьев и сестер.

ul li:not(:nth-child(n+3))

Что бы выбрать все li с до 3-го (например, 1-го и 2-го). Но, на мой взгляд, это выглядит некрасиво и имеет очень узкий сценарий использования.

Вы также можете выбрать nth-child справа налево:

ul li:nth-child(-n+2)

Что делает то же самое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...