Есть ли селектор «предыдущий брат»?

1356

Знак плюс ( +) предназначен для следующего брата.

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

Jourkey
источник
18
OMG, все ответы здесь, предлагающие вам изменить порядок элементов html, а затем использовать CSS, чтобы они выглядели задом наперед, являются настоящим натяжением. Конечно, это не указывает на вопрос, но большинство вопросов «Можете ли вы сделать X с помощью CSS» должны предполагать, что вы не можете изменить HTML структурно.
Squarecandy
3
@squarecandy, я в основном согласен с вашим комментарием. Но решения, которые вы называете неадекватными, тем не менее, в некоторых случаях полезны (обратите внимание на отрицательные отзывы). Так что их стоит опубликовать. То, что вы видите как «настоящий натяжение», может быть «творческим решением» для других.
Майкл Бенджамин

Ответы:

839

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

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

См. Смежный братский комбинатор от селекторов уровня 3 и 5.7 Смежные соседние братские селекторы от каскадных таблиц стилей, редакция 1 уровня 2 (CSS 2.1) .

Клетус
источник
14
Из стандарта CSS3: элементы, представленные двумя последовательностями, имеют одного и того же родителя в дереве документа, и элемент, представленный первой последовательностью, предшествует (не обязательно сразу) элементу, представленному второй.
Ли Райан
26
@Lie Райан: Да, но в своем ответе Клеетс говорит, что вы не выбираете предыдущий элемент.
BoltClock
42
Вот пример, который я сделал, чтобы увидеть, что это может и не может сделать. jsfiddle.net/NuuHy/1
Абак
7
Полезная для этого функция jquery: prev (). Например, $ ("# the_element"). Prev (). Css ("background-color", "red")
Сатбир Кира
1
В зависимости от вашей разметки это может помочь: stackoverflow.com/questions/42680881/…
samnau
235

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

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

/* 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>

mantish
источник
17
Вы можете добавить объяснение того, как это работает. (кажется, что вы применяете стиль ко всем элементам и к следующим элементам, но он может быть подробно описан)
AL
1
Отличное решение. Нет необходимости переупорядочивать элементы в разметке или в рендере (через float:right). Для этого потребовался пробел между единицами / словами и отступами вместо полей, но он работает совершенно иначе!
Стивен Вачон
7
да, но в большинстве случаев нужен один предыдущий, а НЕ ВСЕ предыдущие!
Азерафати
42
Все ссылки станут красными, если я наведусь на пространство между ними, для меня.
Линн
3
@ Линн ответ включает только код, чтобы сделать предыдущие ссылки красным при наведении курсора. Дополнительные стили зависят от вашего варианта использования. Для компонента звездного рейтинга (который, я полагаю, является распространенным случаем) вам необходимо избавиться от этого места, а также сделать красным ссылку.
mantish
164

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

previous:has(+ next) {}

... но на момент написания этой статьи, это некое преимущество за пределами поддержки браузеров.

Quentin
источник
52
«Чувствительность для поддержки браузера» может быть преувеличением. На момент написания этой статьи даже самая последняя версия Chrome не могла использовать :has()псевдокласс.
Рид Мартин
33
@ReedMartin - Вот почему я сказал, что некоторое расстояние за пределами кровотечения
Квентин
12
msgstr ": has не помечен как часть профиля динамического селектора, что означает, что его нельзя использовать в таблицах стилей; только с такими функциями, как document.querySelector ()." - developer.mozilla.org/en-US/docs/Web/CSS/:has
Arch Linux Tux
1
@ArchLinuxTux: «Это ограничение теперь снято», поэтому однажды мы могли использовать эту функцию: D.
Джейкоб ван Линген
@JacobvanLingen - caniuse.com/#feat=css-has - в настоящее время ни один браузер не поддерживает его.
Квентин
153

Рассмотрим orderсвойство гибких и сеточных макетов.

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


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

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

Вот пример:

Вы хотите, чтобы элемент 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. Используйте селектор брата, чтобы предназначаться для Элемента A ( ~или +сделаю).

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

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

    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управляет свойство порядок , в котором гибкие элементы появляются в гибком контейнере, назначая их порядковые группы. Он принимает одно <integer>значение, которое указывает, к какой порядковой группе относится элемент flex.

Начальное orderзначение для всех элементов flex - 0.

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


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

.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


Примечание: два устаревших представления о CSS

Flexbox разрушает давние убеждения о CSS.

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

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

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

z-indexМиф

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

На самом деле, самая последняя версия спецификации - проект редактора W3C - все еще утверждает, что это правда:

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

z-index

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

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

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

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

4,3. Flex Item Z-Ordering

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

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

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

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

Майкл Бенджамин
источник
16
orderСвойство не является решением , поскольку оно предназначено исключительно для изменения визуального порядка, так что это не восстановить первоначальный семантический порядок , который вы вынуждены изменения в HTML для этого обходного пути на работу.
Марат Таналин
5
Имейте в виду, что CSS2.2 ED, который вы цитируете, по сути, все еще CSS2. А в CSS2 нет flexbox и макета сетки, поэтому, что касается CSS2, эта информация, безусловно, верна. По крайней мере, текст может быть обновлен, чтобы упомянуть, что z-index может применяться к другим типам элементов на будущих уровнях CSS, так же как он говорит, что другие свойства могут устанавливать контекст стека, такой как непрозрачность.
BoltClock
3
@BoltClock Мой комментарий не имеет ничего общего с поддержкой браузера. Техника нарушает семантику в пользу изложения. Я считаю, что обычный регулярный класс, добавленный к элементу «предыдущий брат» на стороне сервера, гораздо более разумен.
Марат Таналин
3
В случае, если у кого-то возникают проблемы с пониманием того, когда z-indexбудет работать, даже если «omg, там не positionуказано!», В спецификации упоминается концепция стекового контекста , что хорошо объясняется в этой статье о MDN
Rogier Spieker,
3
@Michael_B, пожалуйста! Я имел дело с множеством фронтменов, не подозревающих об этом. Еще одна вещь, о которой я хотел бы упомянуть, селектор поддельного предыдущего брата также прекрасно работает сfloat: right (или с любым другим способом отменить порядок, который flex/orderимеет небольшие (наименьшие?) Побочные эффекты). Взбил две скрипки: демонстрация float: rightподхода и демонстрацияdirection: rtl
Рогьер Шпикер
69

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

x ~ y

записывать

y ~ x

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

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

Брайан Ларсен
источник
18
Я считаю, что это работает, когда вы можете легко найти. Проблема в том, что если y можно найти только относительно x, и, перевернув его, вы не сможете найти y, потому что сначала нужно найти x. Это, конечно, относится к вопросу о том, что у вас предшествующий брат, а не о следующем, но может также относиться к тому, что у следующий брат.
Дэвид
19
Ты грубый, суровый. (извините, не смог устоять.) Дело в том, что иногда вам просто нужно знать «существует ли у вас?». В других случаях вы можете использовать «: before», чтобы поместить что-то между двумя элементами. Наконец, если вам нужно перейти в jQuery, использовать find ("y ~ x"). Prev () проще, чем многие альтернативы.
Брайан Ларсен
157
Идея предыдущего родственного селектора состоит в том, что он выберет предыдущий элемент. К сожалению, изменение его, как описано здесь, не обеспечивает эту функциональность.
Zenexer
14
Спасибо @Zenexer за разъяснение, что этот ответ не дает реального решения исходного вопроса, я начинал чувствовать себя глупо, размышляя о том, как y ~ xможно решить мою проблему
Хайме Хаблутцель,
4
Я понимаю идею, лежащую в основе этого ответа, однако аргументация, приведенная в ответе, не совсем имеет смысла. Селектор y ~ xне отвечает "есть совпадение?" вопрос, потому что два селектора, приведенные здесь, означают совершенно разные вещи. Там нет никакого способа, y ~ xчтобы когда-либо произвести сопоставление, данное поддерево, <root><x/><y/></root>например. Если вопрос "существует ли у?" тогда селектор просто y. Если вопрос «существует ли у данного брата х в любой произвольной позиции?» тогда вам понадобятся оба селектора. (Хотя, может быть, я просто придираюсь к этому моменту ...)
BoltClock
25

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

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>

Роко С. Бульян
источник
25

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

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

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

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

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

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

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

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

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

  • .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>

Rounin
источник
3
Это дает мне синтаксическую ошибку, когда я пытаюсь реализовать ее на sass внутри проекта rails.
Алекс
25
axe это постпроцессор CSS. Он не использует тот же синтаксис, что и препроцессоры CSS, такие как Sass, Less или Stylus.
Рунин
1
@Rounin, не могли бы вы добавить ссылки на документацию? Я не могу найти постпроцессор топора .
Дионис
@Dionys - Спасибо за ваш интерес. ax - это проект, который я начал в конце 2016 года, когда я не знал ES2015, и даже объекты в JS были для меня очень новыми. Репозиторий GitHub находится здесь: github.com/RouninMedia/axe . Я очень хочу вернуться к этому в какой-то момент (я также разработал нечто, называемое « топор-лезвие», которое является CSS-эквивалентом событий javascript), но мне нужно сначала завершить работу над другим проектом (под кодовым названием ashiva ).
Рунин
17

Еще одно решение 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>

Вадим Овчинников
источник
16

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

Что вы можете сделать, это использовать селектор 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>

Ограничения

  • Вы не можете выбрать предыдущие элементы на основе классов следующих элементов
  • Это то же самое для псевдо-классов
0x1gene
источник
1
@Ian, потому что :nth-child(-n+4)это псевдокласс, который нужно применить к селектору, чтобы он работал правильно. Если вы не уверены, попробуйте поэкспериментировать с вилкой моей скрипки, и вы увидите, что она не работает
0x1gene
1
На самом деле, вы можете использовать независимый тип узла, используя *селектор, но это ужасно плохая практика.
Джош Берджесс
1
Это ответ, который работал для меня, не уверен, почему он не проголосовал выше или принят.
Джейк Кэттролл
1
На самом деле, он работает для разных узлов: jsfiddle.net/aLhv9r1w/316 . Пожалуйста, обновите свой ответ :)
Джейми Баркер
1
У меня был сложный селектор, но, скажем так, li#someListItemи я хотел, чтобы узлы были перед ним (именно так я интерпретирую «предыдущий») - я не понимаю, как предоставленная вами информация может помочь мне выразить это через CSS. Вы просто выбираете первые n братьев и сестер и предполагаете, что я знаю n. Основываясь на этой логике, любой селектор может сделать свое дело и выбрать нужный мне элемент (ы) (например, not ()).
bitoolean
4

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

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

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

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

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

Который делает то же самое.

ядро
источник
3

Нет. Это невозможно через CSS. Он принимает "Каскад" близко к сердцу ;-).


Однако, если вы сможете добавить JavaScript на свою страницу, немного jQuery поможет вам достичь конечной цели.
Вы можете использовать jQuery findдля «предварительного просмотра» целевого элемента / класса / id, а затем вернуться назад, чтобы выбрать цель.
Затем вы используете jQuery, чтобы переписать DOM (CSS) для вашего элемента.

Основываясь на этом ответе Майка Бранта , может помочь следующий фрагмент jQuery.

$('p + ul').prev('p')

Сначала выбираются все <ul>s, которые сразу же следуют за <p>.
Затем он «возвращается», чтобы выбрать все предыдущие <p>s из этого набора <ul>s.

По сути, «предыдущий брат» был выбран с помощью jQuery.
Теперь используйте .cssфункцию, чтобы передать новые значения CSS для этого элемента.


В моем случае я искал способ выбрать DIV с идентификатором #full-width, но ТОЛЬКО если он имел (косвенный) потомок DIV с классом .companies.

Я контролировал весь HTML-код .companies, но не мог изменить ни один из HTML-кодов над ним.
И каскад идет только в 1 направлении: вниз.

Таким образом я мог выбрать ВСЕ #full-widths.
Или я мог выбрать, .companiesчто только следовал за #full-width.
Но я не мог выбрать только #full-widthто, что продолжалось .companies .

И, опять же, я не смог добавить .companies выше в HTML. Эта часть HTML была написана внешне и обернула наш код.

Но с помощью jQuery я могу выбрать нужные #full-widths, а затем назначить соответствующий стиль:

$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );

Он находит все #full-width .companiesи выбирает только те .companies, которые похожи на то, как селекторы используются для нацеливания на определенные элементы в стандарте в CSS.
Затем он использует .parents«backtrack» и выбирает ВСЕХ родителей .companies,
но фильтрует эти результаты, чтобы сохранить только #fill-widthэлементы, так что, в конце концов,
он выбирает #full-widthэлемент, только если у него есть .companiesпотомок класса.
Наконец, он присваивает новое значение CSS ( width) результирующему элементу.

$(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
div {
  background-color: lightblue;
  width: 120px;
  height: 40px;
  border: 1px solid gray;
  padding: 5px;
}
.wrapper {
  background-color: blue;
  width: 250px;
  height: 165px;
}
.parent {
  background-color: green;
  width: 200px;
  height: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div class="wrapper">

  <div class="parent">
    "parent" turns red
    <div class="change-parent">
    descendant: "change-parent"
    </div>
  </div>
  
  <div class="parent">
    "parent" stays green
    <div class="nope">
    descendant: "nope"
    </div>
  </div>
  
</div>
Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>
<b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>
<br>
(reverse cascade, look ahead, parent un-descendant)
</html>

Справочные документы jQuery : элемент
$ () или jQuery () : DOM.
, find : Получить потомков каждого элемента в текущем наборе соответствующих элементов, отфильтрованных селектором, объектом jQuery или элементом.
, родители : Получить непосредственно предшествующий брат каждого элемента в наборе соответствующих элементов. Если предоставляется селектор, он извлекает предыдущего родного брата, только если он соответствует этому селектору (фильтрует результаты, чтобы включить только перечисленные элементы / селекторы).
, css : установить одно или несколько свойств CSS для набора соответствующих элементов.

SherylHohman
источник
Это не имеет ничего общего с вопросом. Конечно, это возможно с помощью JS, и вам даже не нужен jQuery для этого ( previousElementSibling).
Фабиан фон Эллертс
1
@FabianvonEllerts Я ответил на вопрос ОП прямо в первой строке моего ответа. Как говорится в моем ответе, это буквально невозможно через CSS . Затем я предоставил 1 возможный путь для достижения цели, используя технологию (JS ​​| JQuery), с которой пользователи CSS могут быть знакомы и иметь доступ к ней. Например, многие сайты WordPress также имеют JQuery, так что это простая точка входа: проста в использовании, запоминании и расширении. Было бы безответственно просто ответить НЕТ , не предлагая альтернативного способа достижения цели. Я поделился тем, что узнал и использовал, когда у меня был тот же вопрос.
ШерилХоман
previousElementSibling()для тех, кто более знаком с нативными функциями JS DOM, может быть предложен другой путь, отличный от CSS.
ШерилХоман
Я нашел другие CSS-хаки очень интересными, но для моего конкретного случая они либо не работали (попали в категорию предостережений), либо были слишком запутанными. Для других, попадающих в те же обстоятельства, справедливо поделиться этим простым в использовании методом, который может работать там, где вышеперечисленные решения не работают или будут слишком сложны для реализации / обслуживания. Многие CSS-хаки были распространены. Эта работа не была покрыта. Ни один из ответов не использует +(несуществующий) селектор, который специально запрашивал OP. Считайте этот ответ JS "взломать". Это здесь, чтобы сэкономить время, которое я потратил, чтобы найти решение.
ШерилХоман
2

Там нет «предыдущий» селектор родственный , к сожалению, но вы можете , возможно , , до сих пор получить тот же эффект , с помощью определения местоположения (например , флоат право). Это зависит от того, что вы пытаетесь сделать.

В моем случае я хотел использовать 5-звездочную систему рейтинга CSS. Мне нужно покрасить (или поменять иконку) предыдущие звезды. Плавая каждый элемент вправо, я, по сути, получаю тот же эффект (таким образом, HTML для звезд должен быть написан «назад»).

Я использую FontAwesome в этом примере и меняю между юникодами fa-star-o и fa-star http://fortawesome.github.io/Font-Awesome/

CSS:

.fa {
    display: inline-block;
    font-family: FontAwesome;
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* set all stars to 'empty star' */
.stars-container {
    display: inline-block;      
}   

/* set all stars to 'empty star' */
.stars-container .star {
    float: right;
    display: inline-block;
    padding: 2px;
    color: orange;
    cursor: pointer;

}

.stars-container .star:before {
    content: "\f006"; /* fontAwesome empty star code */
}

/* set hovered star to 'filled star' */
.star:hover:before{
    content: "\f005"; /* fontAwesome filled star code */
}

/* set all stars after hovered to'filled star' 
** it will appear that it selects all after due to positioning */
.star:hover ~ .star:before {
    content: "\f005"; /* fontAwesome filled star code */
}

HTML: (40)

JSFiddle: http://jsfiddle.net/andrewleyva/88j0105g/

Андрей Лейва
источник
1
float right и / +или ~селекторы поражают меня как самая чистая работа вокруг.
Уильям Джадд
2

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

Скажем, у нас есть:

<div>
  <ul>
    <li><a>Pants</a></li>
    <li><a>Socks</a></li>
    <ul>
      <li><a>White socks</a></li>
      <li><a>Blue socks</a></li>
    </ul>
  </ul>
</div>

Что мы можем сделать, чтобы блок Socks (включая цвета носков) выделялся визуально, используя интервалы?

Что бы хорошо, но не существует:

ul li ul:parent {
  margin-top: 15px;
  margin-bottom: 15px;
}

Что существует:

li > a {
  margin-top: 15px;
  display: block;
}
li > a:only-child {
  margin-top: 0px;
}

Это устанавливает все якорные ссылки на 15px наверху и сбрасывает его обратно на 0 для тех, у которых нет элементов UL (или других тегов) внутри LI.

DynamicDan
источник
2

Мне нужно решение, чтобы выбрать предыдущий родной брат tr. Я придумал это решение, используя компоненты React и Styled. Это не мое точное решение (это по памяти, часы спустя). Я знаю, что есть ошибка в функции setHighlighterRow.

OnMouseOver для строки установит индекс строки в состояние и повторно отобразит предыдущую строку с новым цветом фона

class ReactClass extends Component {
  constructor() {
    this.state = {
       highlightRowIndex: null
    }
  }

  setHighlightedRow = (index) => {
    const highlightRowIndex = index === null ? null : index - 1;
    this.setState({highlightRowIndex});
  }

  render() {
    return (
       <Table>
        <Tbody>
           {arr.map((row, index) => {
                const isHighlighted = index === this.state.highlightRowIndex
                return {
                    <Trow 
                        isHighlighted={isHighlighted}
                        onMouseOver={() => this.setHighlightedRow(index)}
                        onMouseOut={() => this.setHighlightedRow(null)}
                        >
                        ...
                    </Trow>
                }
           })}  
        </Tbody>   
       </Table>
    )
  }
}

const Trow = styled.tr`
    & td {
        background-color: ${p => p.isHighlighted ? 'red' : 'white'};
    }

    &:hover {
        background-color: red;
    }
`;
рукав моря
источник
0

Нет и есть .

Если вы должны поместить метку перед входом, вместо этого поместите метку после ввода, сохраните и метку, и ввод внутри элемента div, и стилируйте элемент div следующим образом:

.input-box {
  display: flex;
  flex-direction: column-reverse;
}
<div class="input-box">
                <input
                  id="email"
                  class="form-item"
                 
                />
                <label for="email" class="form-item-header">                  
                      E-Mail*                  
                </label>
</div>

Теперь вы можете применить стандартные опции стилей для следующего брата, доступные в css, и вы увидите, что вы используете предыдущий стилевый стиль.

Ron16
источник
-1

У меня была похожая проблема, и я обнаружил, что все проблемы такого рода можно решить следующим образом:

  1. придать всем вашим элементам стиль.
  2. Придайте выбранному элементу стиль.
  3. назначьте стиль следующим элементам, используя + или ~.

и таким образом вы сможете стилизовать ваши текущие, предыдущие элементы (все элементы, переопределенные текущими и последующими элементами) и ваши следующие элементы.

пример:

/* all items (will be styled as previous) */
li {
  color: blue;
}

/* the item i want to distinguish */
li.milk {
  color: red;
}

/* next items */
li ~ li  {
  color: green;
}


<ul>
  <li>Tea</li>
  <li class="milk">Milk</li>
  <li>Juice</li>
  <li>others</li>
</ul>

Надеюсь, это кому-нибудь поможет.

Hejar
источник
1
это в основном то же трюк , как и в старшем ответе от одной и той же темы: stackoverflow.com/a/27993987/717732
Кетцалькоатль