Как повлиять на другие элементы, когда один элемент наведен

459

То, что я хочу сделать, - это когда один определенный объект divнаходится под влиянием, это повлияет на свойства другого div.

Например, в этой демонстрации JSFiddle , когда вы наводите курсор мыши, #cubeэто меняет, background-colorно то, что я хочу, это то, что, когда я наводю курсор мыши #container, #cubeэто влияет.

div {
  outline: 1px solid red;
}
#container {
  width: 200px;
  height: 30px;
}
#cube {
  width: 30px;
  height: 100%;
  background-color: red;
}
#cube:hover {
  width: 30px;
  height: 100%;
  background-color: blue;
}
<div id="container">

  <div id="cube">
  </div>

</div>

Trufa
источник

Ответы:

987

Если куб находится прямо внутри контейнера:

#container:hover > #cube { background-color: yellow; }

Если куб находится рядом с (после закрывающего тега контейнера) контейнера:

#container:hover + #cube { background-color: yellow; }

Если куб находится где-то внутри контейнера:

#container:hover #cube { background-color: yellow; }

Если куб является родственником контейнера:

#container:hover ~ #cube { background-color: yellow; }
Майк
источник
107
Не забывайте, что общий комбинатор сестер ~для «куб находится где-то после контейнера в DOM и разделяет родителя»
robertc
3
Это круто. Есть ли какой-нибудь источник, где я могу найти больше информации об этом? Это поддерживается всеми браузерами, это CSS3? Было бы здорово иметь больше информации об этом. Спасибо!
Анонимный
2
+1 Отличный ответ @ Майк. Что если #containerрядом #cube, то есть #containerследует #cube?
PeterKA,
4
Что делать, если наведенный элемент находится внутри контейнера (на что мы хотим воздействовать) ??? Например: #cube: hover #container {Некоторые CSS-эффекты}
Ханзалла Афган
2
Хороший ответ !! А что если я захочу сменить родителя, когда наведу на него ребенка? Я думаю, что нет выбора для этого.
Микель
41

В этом конкретном примере вы можете использовать:

#container:hover #cube {
    background-color: yellow;   
}

Этот пример работает только потому, что cubeявляется потомком container. Для более сложных сценариев вам нужно использовать другой CSS или JavaScript.

Эмметт
источник
35

Использование одноуровневого селектора является общим решением для стилизации других элементов при наведении курсора на заданный элемент, но он работает только в том случае, если другие элементы следуют заданному элементу в DOM . Что мы можем сделать, когда другие элементы должны быть на самом деле раньше наведенного? Скажем, мы хотим реализовать виджет рейтинга сигнальной полосы, как показано ниже:

Виджет рейтинга сигнальной полосы

На самом деле это можно легко сделать с помощью модели flexbox CSS, установив flex-directionдля нее reverseтак, чтобы элементы отображались в порядке, противоположном тому, в котором они находятся в DOM. Снимок экрана выше - от такого виджета, реализованного с использованием чистого CSS.

Flexbox очень хорошо поддерживается 95% современных браузеров.

Дан Дакалеску
источник
Можно ли это отредактировать, чтобы подсветка не исчезала при перемещении мыши от 1 полосы к другой? Мигание немного отвлекает.
Цербр
@Cerbrus: Добавлено решение, которое не скрывает зависание, когда мышь находится между барами. Недостатком является то, что ширина стержней больше не равна.
Дан Даскалеску
1
Попробуйте это в своем первом фрагменте: .rating divborder-right: 4px solid white;
включите
1
Направление изгиба (не очень хорошо поддерживается для IE) ИЛИ 1) черный по умолчанию 2) весь синий при наведении мыши на контейнер 3) черный для следующего брата при наведении штанги :)
Stephane Mathis
Я сделал эту скрипку, которая (по крайней мере, для меня) сделала ее немного более очевидной в том, что здесь происходит. jsfiddle.net/maxshuty/cj55y33p/3
maxshuty
8

Большое спасибо Майку и Роберту за их полезные посты!

Если у вас есть два элемента в вашем HTML, и вы хотите :hoverболее одного и нацелены на изменение стиля в другом, эти два элемента должны быть напрямую связаны - родители, дети или братья и сестры. Это означает, что оба элемента должны быть либо внутри другого, либо оба должны содержаться в одном и том же элементе большего размера.

Я хотел, чтобы определения отображались в рамке справа от браузера, когда мои пользователи читали мой сайт и пересекались с :hoverвыделенными терминами; поэтому я не хотел, чтобы элемент 'definition' отображался внутри элемента 'text'.

Я почти сдался и просто добавил javascript на свою страницу, но это будущее, черт возьми! Нам не нужно мириться с тем, что back sass из CSS и HTML говорит нам, где мы должны разместить наши элементы для достижения желаемого эффекта! В конце концов мы пошли на компромисс.

В то время как фактические элементы HTML в файле должны быть либо вложенными, либо содержаться в одном элементе, чтобы быть допустимыми :hoverцелями друг для друга, positionатрибут css может использоваться для отображения любого элемента там, где вам нужно Я использовал position: fixed, чтобы разместить цель моего :hoverдействия там, где я хотел, на экране пользователя независимо от его расположения в HTML-документе.

HTML:

<div id="explainBox" class="explainBox"> /*Common parent*/

  <a class="defP" id="light" href="http://en.wikipedia.or/wiki/Light">Light                            /*highlighted term in text*/
  </a> is as ubiquitous as it is mysterious. /*plain text*/

  <div id="definitions"> /*Container for :hover-displayed definitions*/
    <p class="def" id="light"> /*example definition entry*/ Light:
      <br/>Short Answer: The type of energy you see
    </p>
  </div>

</div>

CSS:

/*read: "when user hovers over #light somewhere inside #explainBox
    set display to inline-block for #light directly inside of #definitions.*/

#explainBox #light:hover~#definitions>#light {
  display: inline-block;
}

.def {
  display: none;
}

#definitions {
  background-color: black;
  position: fixed;
  /*position attribute*/
  top: 5em;
  /*position attribute*/
  right: 2em;
  /*position attribute*/
  width: 20em;
  height: 30em;
  border: 1px solid orange;
  border-radius: 12px;
  padding: 10px;
}

В этом примере цель :hoverкоманды из элемента в пределах #explainBoxдолжна быть #explainBoxили внутри #explainBox. Атрибуты позиции, назначенные #definitions, заставляют его появляться в нужном месте (снаружи #explainBox), даже если он технически расположен в нежелательной позиции в документе HTML.

Я понимаю, это считается плохой формой использования того же #id для более чем одного HTML-элемента; однако в этом случае случаи #lightмогут быть описаны независимо из-за их соответствующих позиций в уникально #idd элементах. Есть ли причина не повторять id #lightв этом случае?

стог
источник
Довольно длинный ответ для такого короткого момента, но вот его jsfiddle: jsfiddle.net/ubershmekel/bWgq6/1
ubershmekel
1
некоторые браузеры выходят из себя, когда вы используете один и тот же IDнесколько раз. Просто используйте class.
Серж Саган
6

Только это сработало для меня:

#container:hover .cube { background-color: yellow; }

Где .cubeнаходится CssClass #cube.

Протестировано в Firefox , Chrome и Edge .

Cyberhawk
источник
4

Вот еще одна идея, которая позволяет вам влиять на другие элементы без учета какого-либо конкретного селектора и только с использованием :hoverсостояния основного элемента.

Для этого я буду полагаться на использование пользовательских свойств (переменных CSS). Как мы можем прочитать в спецификации :

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

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

Вот пример:

#container {
  width: 200px;
  height: 30px;
  border: 1px solid var(--c);
  --c:red;
}
#container:hover {
  --c:blue;
}
#container > div {
  width: 30px;
  height: 100%;
  background-color: var(--c);
}
<div id="container">
  <div>
  </div>
</div>

Почему это может быть лучше, чем использование специального селектора в сочетании с парением?

Я могу привести по крайней мере две причины, которые делают этот метод хорошим для рассмотрения:

  1. Если у нас есть много вложенных элементов, которые используют одни и те же стили, мы не сможем использовать сложный селектор для нацеливания их всех при наведении курсора. Используя пользовательские свойства, мы просто меняем значение при наведении на родительский элемент.
  2. Пользовательское свойство может использоваться для замены значения любого свойства, а также его частичного значения. Например , мы можем определить пользовательское свойство для цвета , и мы используем его в пределах border, linear-gradient, background-color, и box-shadowт.д. Это позволит избежать нас переустановки всех эти свойств при наведении курсора мыши.

Вот более сложный пример:

.container {
  --c:red;
  width:400px;
  display:flex;
  border:1px solid var(--c);
  justify-content:space-between;
  padding:5px;
  background:linear-gradient(var(--c),var(--c)) 0 50%/100% 3px no-repeat;
}
.box {
  width:30%;
  background:var(--c);
  box-shadow:0px 0px 5px var(--c);
  position:relative;
}
.box:before {
  content:"A";
  display:block;
  width:15px;
  margin:0 auto;
  height:100%;
  color:var(--c);
  background:#fff;
}

/*Hover*/
.container:hover {
  --c:blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>

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

Темани Афиф
источник