Чи є селектор "попереднього брата"?


1354

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

Чи є еквівалент для попереднього брата?


17
OMG, всі відповіді тут пропонують змінити порядок html-елементів, а потім використовувати CSS, щоб вони з'явилися назад - справжня розтяжка. Звичайно, це не вказується у запитанні, але більшість питань "чи можна зробити X із CSS" повинні припускати, що ви не можете структурно змінити HTML.
squarecandy

3
@squarecandy, я здебільшого згоден з вашим коментарем. Але рішення, які ви називаєте неадекватними, все ж корисні в деяких випадках (зауважте підсумки). Тож їх варто опублікувати. Те, що ви бачите як "справжній розтяг", може бути "творчим рішенням" для інших.
Майкл Бенджамін

Відповіді:


839

Ні, не існує селектора "попереднього брата".

Згадана примітка ~- призначена для загального спадкоємця (тобто елемент приходить після цього, але не обов'язково одразу після) і є селектором CSS3. +призначений для наступного брата та є CSS2.1.

Див. Розділ " Суміжні комбінатори братів" з селекторів рівня 3 та 5.7 Суміжні селектори вибору з каскадних таблиць стилів рівень 2, версія 1 (CSS 2.1) .


14
Зі стандарту CSS3: Елементи, представлені двома послідовностями, поділяють один і той же батьків у дереві документів, а елемент, представлений першою послідовністю, передує (не обов'язково одразу) елементу, представленому другою.
Лежати Райан

26
@Lie Ryan: Так, але суть клітсу у його відповіді полягає в тому, що ви не вибираєте попереднього елемента.
BoltClock

42
Ось приклад, який я зробив, щоб побачити, що це можна, а що не можна робити. jsfiddle.net/NuuHy/1
Abacus

7
Корисна для цього функція jquery є prev (). Наприклад $ ("# the_element"). Prev (). Css ("фон-колір", "червоний")
Satbir Kira

1
В залежності від вашої розмітки, це може допомогти: stackoverflow.com/questions/42680881 / ...
samnau

234

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

Скажімо, у вас є список посилань, і коли ви наведіть курсор на одне, всі попередні повинні стати червоними. Ви можете зробити це так:

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


17
Ви можете додати пояснення, як це працює. (здається, що ви застосовуєте стиль до всіх предметів і до наступних предметів, але це можна чітко описати)
AL

1
Дивовижне рішення. Не потрібно впорядковувати елементи в розмітці, ні в візуалізації (через float:right) Це вимагало краплі пробілу між одиницями / словами та підкладкою замість поля, але це працює зовсім інакше!
Стівен Вахон

7
Так, але більшість часу потрібен один попередній НЕ ВСІ попередні!
azerafati

41
Усі посилання червоніють, якщо я наведіть на простір між ними.
Лінн

3
@Lynn відповідь включає лише код, щоб зробити попередні посилання червоними після наведення курсору. Додаткові стилі залежать від вашого випадку використання. Для компонента з оцінкою зірок (який, мабуть, є звичайним випадком), вам потрібно буде позбутися цього простору, а також зробити червоним кольором посилання.
богомол

164

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

previous:has(+ next) {}

... але під час написання, для підтримки браузера є деяка відстань за межею кровотоку.


51
"Край кровотоку для підтримки браузера" може бути завищенням. На момент написання цього запису не може використовуватись навіть найновіша версія Chrome :has().
Рід Мартін

33
@ReedMartin - Ось чому я сказав деяку відстань за межею кровотоку
Квентін,

12
": 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.


За допомогою флексокса можна моделювати попередній селектор.

Зокрема, 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. Використовуйте селектор сестер, щоб націлити елемент А ( ~або +буде).

    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значення для всіх гнучких елементів - 0.

Також дивіться orderу специфікації макета сітки CSS .


Приклади "попередніх селекторів", створених із 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

  • Значення: авто | | успадковувати
  • Початковий: авто
  • Застосовується для: розташованих елементів
  • Спадково: ні
  • Відсотки: Не застосовується
  • ЗМІ: візуальні
  • Обчислене значення: як зазначено

(наголос додано)

Однак насправді ця інформація є застарілою та неточною.

Елементи, які є гнучкими елементами або елементами сітки, можуть створювати контексти укладання, навіть коли 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роботи над непозиціонованими гнучкими елементами: https://jsfiddle.net/m0wddwxs/


15
orderВластивість не є рішенням , оскільки воно призначене виключно для зміни візуального порядку, так що це НЕ відновити первісний семантичний порядок , який ви змушені зміни в HTML для цього обхідного шляху на роботу.
Марат Таналін

2
@Marat Tanalin: Для 90% випадків використання, якщо припустити, що підтримка браузера не є проблемою, це буде добре. Решта 10% випадків використання - це 1) випадки, коли зміна візуального порядку не є рішенням, або 2) випадки, які взагалі не включають CSS. На щастя, для №2, селектори-4 надають: має (), і розробники бібліотек-селекторів просто реалізують це.
BoltClock

5
Майте на увазі, що CSS2.2 ED, який ви цитуєте, є, по суті, ще CSS2. І макет флексбоксу та сітки в CSS2 не існує, тому що стосується CSS2, то ця інформація, безумовно, є правдивою. Принаймні, текст може бути оновлений, щоб згадати, що z-індекс може застосовуватись до інших типів елементів у майбутніх рівнях CSS, так само, як він каже, що інші властивості можуть встановлювати контекст складання, наприклад, непрозорість.
BoltClock

3
Якщо у когось виникають проблеми з розумінням того, коли z-indexбуде працювати, навіть коли "omg, не positionвказано!", Специфікація згадує про концепцію складання контексту , що добре пояснюється цією статтею про MDN
Rogier Spieker,

3
@Michael_B ласкаво просимо! Я мав справу з багатьма передовиками, не знаючи цього. Ще одна річ, яку я хотів би зазначити, попередній фальшивий селектор також чудово працює з float: right(або будь-яким іншим способом змінити замовлення, з яких flex/orderмало (найменше?) Побічних ефектів). Зітхнув дві примхи: демонстрація float: rightпідходу та демонстраціяdirection: rtl
Rogier Spieker

69

У мене було те саме питання, але тоді у мене був «духа» момент. Замість того, щоб писати

x ~ y

писати

y ~ x

Очевидно, це відповідає "x" замість "y", але це відповідає "чи є відповідність?" Питання, і просте обхід DOM може ефективніше дістати вас до потрібного елемента, ніж зациклюватися на JavaScript.

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


18
Я вважаю, що це працює, коли y можна легко знайти. Проблема полягає в тому, що якщо y можна знайти лише відносно x, і при його перетворенні ви не можете знайти y, тому що ви повинні знайти x спочатку. Це, звичайно, посилається на питання про те, що y передує рідним братам, а не наступному, але може також застосовуватися і для наступного брата.
Девід

19
Ти такий собі суворий, Різкий. (Вибачте, не втримався.) Справа в тому, що іноді просто потрібно знати, "чи існує?". В інших випадках ви можете використовувати ": раніше", щоб помістити щось між двома елементами. Нарешті, якщо вам все-таки доведеться потрапити в jQuery, використовувати find ("y ~ x"). Prev () простіше, ніж багато альтернатив.
Брайан Ларсен

156
Ідея попереднього селектора сестер полягає в тому, що він вибере попередній елемент. На жаль, реверсування його, як описано тут, не забезпечує цю функціональність.
Zenexer

14
Дякую @Zenexer за уточнення, що ця відповідь не дає фактичного вирішення оригінального питання, я починав почувати себе дурним, думаючи про те, як y ~ xможна вирішити свою проблему
Хайме Хаблутцель,

4
Я розумію ідею, що стоїть за цією відповіддю, однак міркування, наведені у відповіді, не мають сенсу. Селектор y ~ xне відповідає "чи є збіг?" питання, адже два наведених тут селектора означають абсолютно різні речі. Ні в якому разі y ~ xне вдасться створити відповідність, наприклад, з піддеревом <root><x/><y/></root>. Якщо питання "чи існує?" то селектор просто y. Якщо питання: "чи існує даний рідний брат x у будь-якому довільному положенні?" тоді вам знадобляться обидва селектори. (Хоча, мабуть, я просто заїжджаю в цей момент ...)
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 є два наступні селектори :

  • +є негайним наступним селектором
  • ~є будь-яким наступним селектором

У звичайних CSS немає попереднього селектора .

Однак, в сокиру CSS бібліотеки постпроцесор, є 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>


3
Це дає мені синтаксичну помилку, коли я намагаюся реалізувати її на sass всередині рейки проекту.
alex

25
ax - це пост-процесор CSS. Він не використовує той самий синтаксис, що і попередні процесори CSS, такі як Sass, Less або Stylus.
Rounin

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>

Обмеження

  • Ви не можете вибрати попередні елементи на основі класів наступних елементів
  • Це те саме для псевдокласів

1
@Ian, тому що :nth-child(-n+4)це псевдоклас, який потрібно застосувати до селектора, щоб правильно працювати. Якщо вас не переконують, спробуйте експериментувати, використовуючи виделку моєї загадки, і ви побачите, що вона не
прокидається

1
Насправді, ви можете перейти до типу вузла незалежно за допомогою *селектора, але це прикро погана практика.
Джош Берджесс

1
Це відповідь, яка працювала на мене, не впевнений, чому її не проголосували вище чи прийнято.
Джейк Каттралл

1
Насправді він працює для різних вузлів: jsfiddle.net/aLhv9r1w/316 . Будь ласка, оновіть свою відповідь :)
Джеймі Баркер

1
У мене був складний селектор, але скажімо, що це так, li#someListItemі я хотів, щоб вузол (и) прямо перед ним (саме так я інтерпретую "попередній") - я не бачу, як надана вами інформація може допомогти мені виразити це через CSS. Ви просто вибираєте перших n братів і сестер, і припускаєте, що я знаю п. Виходячи з цієї логіки, будь-який селектор може зробити трюк і вибрати потрібний мені елемент (наприклад: not ()).
Бітолеан

4

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

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

Який обрав би всі lis до 3-го (наприклад, 1-го та 2-го). Але, на мою думку, це виглядає некрасиво і має дуже тугий шаф.

Ви також можете вибрати п’ятого дитини справа наліво:

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

Що робить те саме.


3

Ні. Це неможливо через CSS. Це сприймає «Каскад» до серця ;-).


Однак якщо ви зможете додати JavaScript на свою сторінку, трохи jQuery може привести вас до вашої кінцевої мети.
Ви можете використовувати jQuery's findдля того , щоб виконати "погляд вперед" на своєму цільовому елементі / класі / id, а потім назад для вибору цілі.
Потім ви використовуєте jQuery, щоб переписати DOM (CSS) для свого елемента.

На основі цієї відповіді Майка Бранта може допомогти наступний фрагмент jQuery.

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

Спершу вибираються всі <ul>s, які відразу слідують за a <p>.
Тоді це "назад", щоб вибрати всі попередні <p>s з цього набору <ul>s.

Ефективно "попередній брат" був вибраний через jQuery.
Тепер за допомогою .cssфункції передайте у свій CSS нові значення для цього елемента.


У моєму випадку я шукав спосіб вибрати DIV з ідентифікатором #full-width, але ТОЛЬКО, якщо він мав (непрямий) нащадок DIV з класом .companies.

Я мав контроль над усім HTML внизу .companies, але не міг змінити жоден HTML над ним.
А каскад йде лише в 1 напрямку: вниз.

Таким чином я міг вибрати ВСЕ #full-widths.
Або я міг вибрати, .companiesщо слідував лише за a #full-width.
Але я не міг вибрати лише ті #full-width, що тривали .companies .

І, знову ж таки, мені не вдалося додати .companiesбільше HTML в HTML. Ця частина HTML була написана зовні і обернула наш код.

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

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

Це знаходить все #full-width .companiesі вибирає лише ті .companies, подібно до того, як селектори використовуються для націлювання на конкретні елементи у стандарті CSS.
Потім він використовує .parentsдля "зворотного відстеження" та вибору ВСІХ батьків батьків .companies,
але фільтрує ці результати, щоб зберегти лише #fill-widthелементи, так що, врешті-решт,
він вибирає #full-widthелемент, лише якщо він має .companiesнащадка класу.
Нарешті, він присвоює новому widthзначенню CSS ( ) отриманий елемент.

$(".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.
. Знайдіть : Отримайте нащадків кожного елемента в поточному наборі відповідних елементів, відфільтрованому селектором, об'єктом jQuery або елементом.
. батьки : Отримайте безпосередньо передували брати кожного елемента в наборі відповідних елементів. Якщо надається селектор, він отримує попередній брат, лише якщо він відповідає цьому селектору (фільтрує результати, щоб включити лише перелічені елементи / селектори).
. css : встановлення одного або декількох властивостей CSS для набору відповідних елементів.


Це не має нічого спільного з питанням. Звичайно, це можливо за допомогою JS, і вам навіть не потрібен jQuery для цього ( previousElementSibling).
Fabian von Ellerts

1
@FabianvonEllerts Я відповів на питання ОП безпосередньо в першому рядку своєї відповіді. Як свідчить моя відповідь, через CSS це буквально неможливо . Тоді я надав 1 можливий шлях вперед до досягнення мети, використовуючи технологію (JS ​​| JQuery), з якою користувачі CSS можуть бути знайомі та мати доступ до них. Наприклад, на багатьох сайтах WordPress також є JQuery, тому це проста точка входу: проста у використанні, запам'ятовуванні та розширенні. Було б безвідповідально просто відповісти " НІ" , не надаючи альтернативного способу досягнення мети. Я поділився тим, що дізнався і використовував, коли у мене було те саме питання.
SherylHohman

previousElementSibling()для тих, хто більше знайомий з нативними функціями JS DOM, можна було б отримати ще один не-CSS шлях вперед.
SherylHohman

Інші CSS HACKS мені здаються дуже цікавими, але для мого конкретного випадку вони або не спрацювали (потрапили в категорію застережень), або були занадто складними. Для інших, хто потрапляє в ту ж саму обставину, справедливо поділитися цим простим у використанні методом, який може працювати, коли вищезазначені рішення не спрацьовують, або було б надто складно реалізувати / підтримувати. Багато CSS HACKS поділилися. Ця робота навколо не висвітлювалася. НІКОЙ з відповідей не використовує +(неіснуючий) селектор, про який спеціально запитувала ОП. Вважайте цю відповідь JS "хаком". Тут потрібно заощадити інший час, який я витратив на пошук рішення.
SherylHohman

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
пливуть праворуч і, +або ~селектори вражають мене як найчистішу роботу.
Вілліям Джадд

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>

Що ми можемо зробити, щоб блок шкарпеток (включаючи кольори шкарпеток) візуально виділявся за допомогою відстані?

Що було б добре, але не існує:

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.


2

Мені потрібно було рішення, щоб вибрати попередній трійковий брат. Я придумав це рішення, використовуючи 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;
    }
`;

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

Сподіваюся, це комусь допоможе.


1
це в основному те ж трюк , як і в старшому відповіді від однієї і тієї ж теми: stackoverflow.com/a/27993987/717732
Кетцалькоатль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.