Home > Net >  Prevent overlay click for elements with a higher z index
Prevent overlay click for elements with a higher z index

Time:10-30

I have a simple overlay that I want to catch click events on. Problem is, I don't want any clicks that occur within the content of the overlay to trigger an event. For example, if you look at my code snippet below, clicking inside the .content div should not trigger the click event listener that I set on the overlay, but it does.

Basically I want to just know when someone clicks the black background of the overlay. Is there anyway to do this with how I currently have my code?

const overlay = document.querySelector('.overlay')

overlay.onclick = function() {
  console.log('click on overlay!')
}
body {
  margin: 0;
}

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  background-color: rgba(0,0,0,0.5);
  width: 100%;
  height: 100%;
  z-index: 10;
}

.content {
  width: 200px;
  height: 200px;
  position: absolute;
  z-index: 11;
  top: calc(50% - 100px);
  left: calc(50% - 100px);
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="overlay">
  <div class="content">Hello World</div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

you can disable the click event for the content div

const content = document.querySelector('.content');
content.off('click');

CodePudding user response:

Access the event target in the arguments of your function. From there use a conditional if statement to ensure that the target clicked is the overlay, and only do your action if the condition is true.

const overlay = document.querySelector('.overlay')

overlay.onclick = function(e) {
  if (e.target.classList.contains("overlay")) {
  console.log('click on overlay!')
}
}
body {
  margin: 0;
}

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  background-color: rgba(0,0,0,0.5);
  width: 100%;
  height: 100%;
  z-index: 10;
}

.content {
  width: 200px;
  height: 200px;
  position: absolute;
  z-index: 11;
  top: calc(50% - 100px);
  left: calc(50% - 100px);
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="overlay">
  <div class="content">Hello World</div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

@PsiKai solution is good. You can also handle it with enter image description here

I don't know what is best solution for your problem but it can be solved in several ways:

  1. Solution proposed by @PsiKai and @Joulss where you're checking target element by class name. Registered event listener

  2. Solution proposed by @eMentorship. By changing the markup, event at bubbling phase doesn't touch .overlay element.

const content = document.querySelector('.element');
content.addEventListener('click', event => event.stopPropagation());

By calling stopPropagation you stoping event from going to the parent element and as a result .overlay event handler ignored as event not bubbling to the root element.

Event phase: https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase

PS. According to MDN: The addEventListener() method is the recommended way to register an event listener. The benefits are as follows:

  • It allows adding more than one handler for an event. This is particularly useful for libraries, JavaScript modules, or any other
    kind of code that needs to work well with other libraries or
    extensions.
  • In contrast to using an onXYZ property, it gives you finer-grained control of the phase when the listener is activated (capturing vs. bubbling).
  • It works on any event target, not just HTML or SVG elements.
  • Related