获取重叠兄弟元素的CSS :hover效果

5

在运行以下代码时,最容易理解。当悬停在红色条上时,我希望同时触发列和中间行的悬停状态。

我想保持基于flex的列,并使条绝对定位在它们上面。

这可能吗?

编辑:

我只想让鼠标悬停的那一列变成蓝色。抱歉表述不清楚。更新了代码片段以显示所需的结果。

列之间由白线分隔。将鼠标悬停在灰色区域上可查看高亮显示的列。

谢谢。

.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: 1px solid white;
}

.column:hover {
  background: blue;
}

.bar {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: red;
}

.bar:hover {
  background: green;
}

.green {
  background: green;
}

.blue {
  background: blue;
}
Hover over the middle of the square. I want the middle column to turn blue and the bar to turn green.
Right now, only the bar turns green.

<div class='root'>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
  <div class='bar'>
  </div>
</div>

Desired result: 

<div class='root'>
  <div class='column'>
  </div>
  <div class='column blue'>
  </div>
  <div class='column'>
  </div>
  <div class='bar green'>
  </div>
</div>

最终编辑:

我提供了一个完整的版本来说明我的用例。我认为CSS无法解决这个问题,但是我已经接受了一个对我的原始问题有效的答案。

function enterColumn() {
  document.getElementById('column-status').innerHTML = 'In column'
}

function leaveColumn() {
  document.getElementById('column-status').innerHTML = 'Out of column'
}

function enterBar() {
  document.getElementById('bar-status').innerHTML = 'In bar'
}

function leaveBar() {
  document.getElementById('bar-status').innerHTML = 'Out of bar'
}
.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: 1px solid white;
}

.column:hover {
  background: blue;
}

.bar-container {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
}

.bar {
  position: absolute;
  top: 0;
  bottom: 0;
  background: red;
}

.bar:hover {
  background: green;
}

.green {
  background: green;
}

.blue {
  background: blue;
}
Hovering over a column or bar should be independent. Right now you can never have the 'In column' and 'In bar' status at the same time :(
<br />
It should scale to support any number of columns and any number of bars (where bars can be absolutely positioned anywhere along the x-axis)
<br />
Javascript events should be called on mouse events for both columns and bars.

<div class='root'>
  <div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
  </div>
  <div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
  </div>
  <div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
  </div>
  <div class='bar-container'>
    <div class='bar' style='left: 5px; right: 40px' onmouseenter='enterBar();' onmouseleave='leaveBar()'>
    </div>
    <div class='bar' style='left: 65px; right: 5px' onmouseenter='enterBar();' onmouseleave='leaveBar()'>
    </div>
  </div>
</div>

<div id='column-status'>
  Out of column
</div>
<div id='bar-status'>
  Out of bar
</div>


CSS 没有办法知道元素被悬停的位置,因此很可能无法仅通过 CSS 解决这个问题。 - chazsolo
@chazsolo 我希望有一种指针事件,它的行为类似于pointer-events: none,但仍会触发:hover选择器和onmouseover JavaScript事件。看起来我必须使用JavaScript来实现这个功能了。 - Noah Potter
3个回答

2

经过两个小时的尝试和错误,我终于想出了这个小技巧。

.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: solid #fff 1px;
}

.column:hover {
  background: blue;
}

.column .toggle{
  margin-top:33px;
  height: 33px;
  width: 100%;
}

.column .toggle:before{
  content: "";
  position: absolute;
  width: 34px;
  height: 33px;
}

.column .toggle:hover:after{
  content: "";
  position: absolute;
  z-index: 10;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: green;
  pointer-events:none;
}

.bar {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: red;
  pointer-events:none;
}
<div class='root'>
  <div class='column'><div class='toggle'></div></div>
  <div class='column'><div class='toggle'></div></div>
  <div class='column'><div class='toggle'></div></div>
  <div class='bar'></div>
</div>

现在,如果您需要将一些JavaScript事件绑定到.bar元素上,请将它们附加到.toggle上。

它将更改所有列的背景,而不仅仅是一个。 - Omri Luzon
修好了,如果这是你想要的,请告诉我。 - Etienne Martin
1
聪明的技巧。尽管它对我的用例无效,但我仍然接受它。我应该说明横跨的栏可能包含多个栏,并且它们应该触发JavaScript事件。我将使用我的实际用例更新我的问题,但我认为我试图过度使用CSS。我放弃拥有这种精确能力。 - Noah Potter

1
如果允许重新排列 divs,您可以将 .bar 定位在中间的 .column 之前,并使用相邻兄弟选择器。
.bar:hover + .column {
     background: blue;
}

.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: 1px solid white;
}

.column:hover {
  background: blue;
}

.bar {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: red;
}

.bar:hover {
  background: green;
}

.bar:hover + .column {
  background: blue;
}

.green {
  background: green;
}

.blue {
  background: blue;
}
<div class='root'>
  <div class='column'>
  </div>
  <div class='bar'>
  </div>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
</div>


我认为你没有完全理解这个问题。它有点模糊不清。OP希望悬停效果不仅影响中央列,而且影响所有三列。 - Etienne Martin

0
如果我理解你的意思,你的意思是当你悬停在任何元素上时,.column 应该变成 蓝色,而 .bar 应该变成 绿色。如果是这样的话,那么实际上很简单。只需将你的 hover 事件放在 .root 元素上,像这样:

.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: 1px solid white;
}

.bar {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: red;
}

.root:hover .bar {
  background: green;
}

.root:hover .column {
  background: blue;
}
<div class='root'>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
  <div class='bar'>
  </div>
</div>

如果不是这种情况,而你想要在鼠标悬停在 .bar 上时改变 .column 的颜色,请查看下面的代码片段。请注意,我已经稍微更改了 HTML 标记。由于 .bar 具有 position: absolute,所以它不会影响您将其放置在 .root 元素内的任何位置。

.root {
  width: 100px;
  height: 100px;
  background: grey;
  position: relative;
  display: flex;
}

.column {
  display: flex;
  flex: 1 1 auto;
  border-right: 1px solid white;
}

.bar {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  bottom: 33px;
  background: red;
}

.bar:hover {
  background: green;
}

.bar:hover ~ .column {
  background: blue;
}
<div class='root'>
  <div class='bar'>
  </div>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
  <div class='column'>
  </div>
</div>

如果这对你有帮助,请告诉我 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接