问题
This is a Q/A on how to handle the opacity of overlapping elements and make it consistent while hover, with a JS solution.
Requirement
The requirement is to develop two elements, which are transparent and overlapping, like the two red boxes below. These need to be transparent so that the background contents are visible.
Now, while hover on any of these elements, the particular element should turn opaque like below.
回答1:
There's a CSS only solution, which makes it a bit more efficient. Like this for example:
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>
回答2:
I tried with elements at absolute positions. In this case I'm able to move each of them on top the wrapper
on mouse enter, then back to their position on mouse leave, via pure JavaScript.
I have expanded the example to 3 elements, where your code shows the artifacts, and added borders to actually see the overlapping.
CODEPEN
The 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>
The 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; }
The 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);
}
回答3:
Solution
As described in the requirement, the solution starts with creating two elements and probably a wrapper to those.
<div class="wrapper">
<div class="first"></div>
<div class="second"></div>
</div>
Now, we style them to match the design.
.first,
.second {
width: 100px;
height: 100px;
background-color: red;
opacity: 0.6;
}
And the below lines of code for the overlap.
.second {
margin-left: 50px;
margin-top: -50px;
}
The problem with this approach is that the opacity will not be consistent on the overlapped region and it gets a darker shade.
Note that this is not a bug with the browsers and the reason for this behaviour is explained here.
The right approach
The better way to handle this situation is to avoid making the children elements transparent and instead set 'opacity' in the parent level. And while hover, toggle these opacity levels between the parent and children with JS.
$(".first, .second").hover(function() {
$(".wrapper, .first, .second").not(this).toggleClass("add-opacity");
});
Also, the hover on overlapped region would cause flickering due to change in stack order, which can be handled by setting z-index
to the hovered element.
.first:hover,
.second:hover {
z-index: 1;
}
CODEPEN
Hope this helps.
回答4:
Here's another approach using Pointer_events
whenever you hover on an element you disable the pointer-events
on the other :
$('.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>
check the compatibility for this as it will work in most browsers except Safari ( as of now ).
来源:https://stackoverflow.com/questions/49900770/overlapped-elements-with-opacity-and-handling-the-hover-on-those