Dex Dex - 1 month ago 9
CSS Question

How can I make a child follow the same behaviour as its parent when using opacity and visibility properties on both of them?

Sorry for the probably unclear title, but I don't know how to accurately describe the problem I am facing. I've create a jsFiddle to hopefully clarify the problem.

I have the following layout in which all 4 divs have

opacity: 1
and
visibility: visible
and div a and b both have
position:absolute
with
top: 0
and
left: 0
.

<div class="a">
<div class="child-a"></div>
</div>
<div class="b">
<div class="child-b"></div>
</div>


If you look at the example you can change div b to:
opacity: 0
and
visibility: hidden
(this happens with a transition). Now you only see div a and its child child-a. You CAN click on div a but you cannot click on child-a. If you try to do so, you will actually have clicked on child-b.

It appears eventhough child-b's parent does not get triggered by mouseevents anymore and seems to be hidden, the child still listens for/ gets triggered by them. I would expect the child to also be "truly" hidden like its parent.

How can I make sure the click on the area where you see child-a actually is applied onchild-a as well? I do want to be able to use a transitions in opacity between showing and hiding the div, so using
display:none
is something you cannot transition (as far as I understand it).

I did add the
display:none
toggle in the example because that toggle does behave the way I whould expect (only then you cannot transition anymore).

Answer

You can play a bit with pointer-events:

.fade-in {
    pointer-events: none;
}
.fade-in.show-me {
    pointer-events: auto;
}
.fade-in .fade-in {
    pointer-events: none;
}
.show-me .show-me {
    pointer-events: auto;
}

Here is a demo:

var a = document.getElementsByClassName("a")[0];
var b = document.getElementsByClassName("b")[0];
var c = document.getElementsByClassName("c")[0];
var d = document.getElementsByClassName("d")[0];
var e = document.getElementsByClassName("e")[0];
var childA = document.getElementsByClassName("child-a")[0];
var childB = document.getElementsByClassName("child-b")[0];

c.onclick = function () {
  if (b.classList.contains("show-me")) {
    b.classList.remove("show-me");
  } else {
    b.classList.add("show-me");
  }
};
d.onclick = function () {
  if (b.classList.contains("hide")) {
    b.classList.remove("hide");
  } else {
    b.classList.add("hide");
  }
};

a.onclick = function () { console.log("a");e.innerHTML = "a<br>"+e.innerHTML; };
b.onclick = function () { console.log("b");e.innerHTML = "b<br>"+e.innerHTML; };
childA.onclick = function (ev) {ev.stopPropagation(); console.log("child-a");e.innerHTML = "child-a<br>"+e.innerHTML; };
childB.onclick = function (ev) {ev.stopPropagation(); console.log("child-b");e.innerHTML = "child-b<br>"+e.innerHTML; };
.a,
.b {
  position: absolute;
  top: 10px;
  left: 10px;
  cursor: pointer;
}
.a:hover,.b:hover {
  box-shadow: 0 0 2px #000;
}
.a {
  background-color: #fee;
}
.b {
  background-color: #eef;
}
.child-a,.child-b {
  float: left;
  width: 80px;
  height: 80px;
  margin: 25px;
  box-shadow: 0 0 2px #000;
  cursor: pointer;
  line-height: 100px;
  text-align: center;
}
.child-a:hover,.child-b:hover {
  box-shadow: 0 0 4px #000;
}
.fade-in {
  opacity: 0;
  visibility: hidden;
  transition-delay: 0s;
  transition-duration: 200ms;
  transition-property: opacity, visibility;
  transition-timing-function: ease;
  pointer-events: none;
}
.fade-in.show-me {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.fade-in .fade-in {
  pointer-events: none;
}
.show-me .show-me {
  pointer-events: auto;
}
.c, .d {
  width: 240px;
  height: 40px;
  margin-top: 30px;
  cursor: pointer;
  background-color: #fff;
  margin-left: 160px;
  box-shadow: 0 0 2px #000;
  line-height: 40px;
  text-align: center;
  border-radius: 3px;
}
.c:hover, .d:hover {
  box-shadow: 0 0 4px #000; 
}
.hide {
  display: none;
}
.e {
  clear: both;
}
<div class="a fade-in show-me">
  <div class="child-a fade-in show-me">a-child</div>
</div>
<div class="b fade-in show-me">
  <div class="child-b fade-in show-me">b-child</div>
</div>

<div class="c">Toggle b opacity and visibility</div>
<div class="d">Toggle b display</div>
<div class="e"></div>