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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

previous:has(+ next) {}

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

Ответ 4

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

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


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

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

Вот пример:

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

<Предварительно > <код > < уль >   < & Li GT, A </& Li GT;   < & Li GT, B </& Li GT; </мкл > Код >

ШАГОВ

  • Сделайте ul контейнер flex.

      ul {display: flex; }
    Код>

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

    <Предварительно > <код > < уль >  < & Li GT, B </& Li GT;  < & Li GT, A </& Li GT; </мкл > Код >
    1. Используйте селектор для выбора для целевого элемента A ( ~ или +).

        li: hover + li {background-color: red; }
      Код>

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

          li: last-child {order: -1; }
        Код>

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

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

  ul {
   дисплей: flex;
}

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

li: last-child {
   порядок: -1;
}

/* несущественные декоративные стили */
li {
   высота: 200 пикселей;
   ширина: 200 пикселей;
   background-color: aqua;
   margin: 5px;
   list-style-type: none;
   курсор: указатель;
}Код>
  <ul>
   < & Li GT, B </& Li GT;
   < & Li GT, A </& Li GT;
</мкл >код>

Ответ 5

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

x ~ y

написать

y ~ x

Очевидно, что это соответствует "x" вместо "y", но отвечает "есть ли совпадение?". вопрос и простой обход DOM могут привести вас к правильному элементу более эффективно, чем цикл в javascript.

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

Ответ 6

Два трюка. В основном, инвертирование порядка 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 "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>

Ответ 7

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

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

В традиционном CSS есть 2 последующих селектора:

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

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

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

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

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

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

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

Ответ 8

Другое решение flexbox

Вы можете использовать инверсию порядка элементов в HTML. Затем, используя order, как в Michael_B answer, вы можете использовать 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>

Ответ 9

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

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

Ответ 10

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

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

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

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

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

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

Ответ 11

К сожалению, нет "предыдущего" селектора, но вы можете получить тот же эффект, используя позиционирование (например, float right). Это зависит от того, что вы пытаетесь сделать.

В моем случае я хотел получить 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/

Ответ 12

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

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

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

Ответ 13

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

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

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

Пример:

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

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

Ответ 14

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


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

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

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

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

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


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

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

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

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

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

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

Это находит все #full-width.companies и выбирает только те .companies, подобно тому, как селекторы используются для нацеливания на определенные элементы в стандарте в CSS.
Затем он использует .parents для "возврата" и выбора ВСЕХ родителей .companies,
но фильтрует эти результаты, чтобы сохранить только элементы #fill-width, так что в итоге
он выбирает элемент #full-width если у него есть .companies класса .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>

Ответ 15

Простой простой ответ для оформления меню: переключитесь с a + ul на ul + a в вашем HTML/XML.

Я хотел, чтобы элемент меню первого уровня имел другой background-color даже если конкретным элементом меню второго уровня был элемент меню.

#menu ul > li:hover > a:not(:only-child)
{
 background-color: rgba(204,204,204,.2);/* IE11 ~ IE15 Fallback */
 background-color: var(--color_anchor_focus);
}

Единственным негативным эффектом был естественный порядок кода при отключении прослушивателя событий. В качестве альтернативы мне очень нравится творчество этого flex и order ответа по Michael_B выше, хотя он по- прежнему немного грязный.

Ответ 16

На самом деле вы можете через CSS !!!

с :not селектор.

CSS

//# + means the next, so this will theNextThatNotH1
.target+:not(h1){color:red}

HTML

<p class="target">Black</p><h1>NOT targeting previous</h1>
<p class="target">RED</p><h2> targeting previous</h2>

Ответ 17

Мне нужно решение, чтобы выбрать предыдущий родной брат 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;
    }
';

Ответ 18

Хорошо, я действительно опаздываю на вечеринку, но мне очень нравится мантишный ответ. Он умный и не требует перестановки элементов; он даже не требует изменения HTML.

Это важно, потому что вся цель CSS - извлечь стили из разметки.

Чтобы иметь возможность обойтись со следующим смежным, но не предыдущим смежным селектором, необходимо знать, что один из братьев и сестер будет совпадать как предшественник, а не ноль. В своем примере наведение говорит вам это. У вас также могут быть другие вещи, которые могут вам это сказать, например, атрибут aria-value-now у родителя.

Я полагаю, что таким образом можно сохранить детерминированный анализ и избежать циклов.

Ответ 19

Как уже говорилось много раз - с div ~ p выбираются все элементы <p>, которым предшествует элемент <div>.

Отметьте этот список всех селекторов CSS.