重叠元素的不透明度和处理这些元素上的“悬停”状态

3

这是关于如何处理重叠元素的不透明度并在悬停时使其保持一致的Q/A,提供了JS解决方案。

需求

要求开发两个透明且重叠的元素,就像下面的两个红色框。这些需要透明以便背景内容可见。

enter image description here

现在,当鼠标悬停在这些元素之一上时,特定的元素应该变得不透明,如下所示。

enter image description here


@appleapple - 你为什么这样认为?至少,这是要求的一部分 :) - Gibin Ealias
1
好的,如果你能做到第一个,我想第二个就很简单了。 - apple apple
1
感谢您提出这个有趣的问题。 - apple apple
1
@appleapple - 确实没错 :) 只是为了节省大家推导逻辑的时间。 - Gibin Ealias
将这两个正方形分解成几个小正方形会行吗,或者你必须只能使用这两个正方形? - Scaramouche
显示剩余2条评论
4个回答

11

有一个纯CSS的解决方案,这使得它更加高效。比如这个:

body {
  background-image: linear-gradient(45deg, transparent 50%, #aaa 75%);
  background-size: 20px 20px;
}

#a {
  position: absolute;
  width: 150px;
  height: 150px;
  top: 50px;
  left: 50px;
  background: rgba(255, 0, 0, 1);
}

#b {
  position: absolute;
  width: 150px;
  height: 150px;
  top: 125px;
  left: 125px;
  background: rgba(255, 0, 0, 1);
}

#wrapper {
  opacity: 0.5;
}

/* instead of changing the classes,  
you can use selectors like this:*/

#wrapper:hover #a:hover,
#wrapper:hover #b:hover {
  opacity: 1;
  z-index: 10;
}

#wrapper:hover {
  opacity: 1;
}

#wrapper:hover #b,
#wrapper:hover #a {
  opacity: 0.5;
  z-index: -1;
}
<div id=wrapper>
  <div id="a">
  </div>
  <div id="b">
  </div>
</div>


仅使用CSS就可以实现,你有没有想法如何使它们透明? - Scaramouche
@Scaramouche 不确定你的意思,它们在示例中是透明的。我添加了背景以使其更加明显。 - Julien Grégoire
太棒了。我之前不知道还可以使用多个hover选择器。 - Gibin Ealias
使用这个解决方案,您仍然会在其他元素的交叉点上出现多余的不透明度,例如这里。而且这不是JS。 - edixon

2
我尝试使用绝对位置的元素。在这种情况下,我能够通过纯JavaScript在鼠标进入时将它们移动到wrapper的顶部,然后在鼠标离开时将它们移回原位。
我已经扩展了示例以包含3个元素,其中您的代码显示出伪影,并添加了边框以实际看到重叠。 CODEPEN HTML代码:
<div id=top>
  <div id=wrapper>
    <div class="first" onMouseEnter="hover3b(event)" onMouseLeave="hover3e(event)"></div>
    <div class="second" onMouseEnter="hover3b(event)" onMouseLeave="hover3e(event)"></div>
    <div class="third" onMouseEnter="hover3b(event)" onMouseLeave="hover3e(event)"></div>
  </div>
</div>

CSS:

body {
  background-image: linear-gradient(45deg, transparent 50%, #aaa 75%);
  background-size: 20px 20px;
}

.first, .second, .third {
  width: 100px;
  height: 100px;
  background-color: red;
  position: absolute;
  border: 3px solid black;
}

#wrapper {
  width: 200px;
  height: 200px;
  background-color: yellow;
  border: 3px solid green;
  opacity: 0.6;
}

.first { left: 0px; top: 0px; }
.second { left: 80px; top: 80px; }
.third { left: 160px; top: 160px; }

JavaScript代码:
var from = null; // remember where to put back the element
function hover3b(e) {
  var t = e.target;
  from = t.nextElementSibling;
  if (!from)
    from = null;
  document.getElementById("top").appendChild(t);
}
function hover3e(e) {
  document.getElementById("wrapper").insertBefore(e.target, from);
}

这也是一个有效的解决方案。感谢你的努力。 - Gibin Ealias

1

解决方案

根据需求描述,解决方案始于创建两个元素和可能的包装器。

<div class="wrapper">
  <div class="first"></div>
  <div class="second"></div>
</div>

现在,我们将其样式与设计匹配。
.first,
.second {
  width: 100px;
  height: 100px;
  background-color: red;
  opacity: 0.6;
}

以下是关于重叠的代码行。
.second {
  margin-left: 50px;
  margin-top: -50px;
}

这种方法存在问题,透明度 在重叠区域不会保持一致,而且颜色会变得更暗。

enter image description here

请注意,这不是浏览器的错误,这种行为的原因在此处解释。

正确的方法

处理这种情况的更好方式是避免使子元素透明,而是在父级别中设置“opacity”。当悬停时,使用JS在父级和子级之间切换这些不透明度水平。

$(".first, .second").hover(function() {
  $(".wrapper, .first, .second").not(this).toggleClass("add-opacity");
});

此外,由于堆叠顺序的更改,重叠区域上的悬停会导致闪烁,可以通过将z-index设置为悬停元素来处理。
.first:hover,
.second:hover {
  z-index: 1;
}

希望这有所帮助。

CODEPEN


3
你为什么要为自己的问题设定悬赏并自己回答它呢? - JPeG
了解是否有更好的答案。 - Gibin Ealias
2
希望这能有所帮助。成功了吗? - Jorge Zuverza
@JorgeZuverza,我不确定你的意思是什么。 - Gibin Ealias
@JPeG,FYI,我上周已经回答了它,但是悬赏是昨天创建的,以查看是否有更好的解决方案。其他用户发布了几个这样的解决方案。 - Gibin Ealias

-1

这里有另一种方法,使用Pointer_events

每当您悬停在一个元素上时,您会禁用其他元素上的pointer-events

$('.first').hover(
  () => { $('.second').css({'pointer-events': 'none'})},
  () => { $('.second').css({'pointer-events': 'auto'})
})

$('.second').hover(
  () => {$('.first').css({'pointer-events': 'none'})},
  () => {$('.first').css({'pointer-events': 'auto'})
})
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  border: 0;
}

body {
  background-image: linear-gradient(45deg, transparent 50%, #aaa 75%);
  background-size: 20px 20px;
}

.wrapper {
  margin-top: 10px;
  margin-left: 10px;
}

.first {
  width: 100px;
  height: 100px;
  background: rgba(255, 0, 0, 0.6);
}

.second {
  width: 99px;
  height: 98px;
  margin-top: -49px;
  margin-left: 50px;
  background: -webkit-linear-gradient(transparent 50%, rgb(255, 0, 0) 50%), -webkit-linear-gradient(0deg, transparent 50%, rgb(255, 0, 0) 50%);
  opacity: 0.6;
}

.first:hover,
.second:hover {
  background: rgba(255, 0, 0, 1);
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="first" id="first"></div>
  <div class="second" id="second"></div>
</div>

请检查兼容性,因为它可以在大多数浏览器中使用,但目前不支持Safari。


这仍然没有解决重叠区域不一致的不透明度问题。请查看我的答案,了解如何处理它。 - Gibin Ealias

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