1

I have an element that has pointer events set to none, this is so hover styles for child elements don't show.

However when this element is clicked on I want to do something with JavaScript. Using an onclick event in JavaScript does not seem to work because pointer-events is set to none.

Is there a way around this so that I can have an element with no pointer events that can still trigger a JavaScript event?

[data-drawer="open"] {
  .site-drawer {
    transform: translateX(0);
    transition: all .2s ease;
  }

  .site-container {
    transform: translateX(-27.5rem);
    // Disabling pointer events disables styles hover styles on below elements
    // But also disables clicking on container to remove it.
    pointer-events: none;
    transition: all .2s ease;
    &:after {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background: rgba(0,0,0,.75);
      content: "";
    }
  }
}

JavaScript:

  this.siteContainer.addEventListener('click', (e) => {
    console.log('site container clicked');
    if(document.body.hasAttribute('data-drawer')) {
      document.body.removeAttribute('data-drawer');
    }
  });

Cheers

tomhughes
  • 4,597
  • 2
  • 24
  • 33
  • Can you please clarrify to me how do you set pointer events to none? – ngeksyo Jul 05 '17 at 11:30
  • Sorry for not being clear, pointer-events is a CSS property that controls when an element can be the target of mouse events. – tomhughes Jul 05 '17 at 11:31
  • So, `pointer-events` is doing just what it should, not allowing these kind of events. So what is the purpose of setting it to `none`? – Eddi Jul 05 '17 at 11:32
  • I'm using it to apply a wrapper over the page when an element I want the user to focus on appears (i.e. a modal or slide-in navigation menu). Whilst one of these components is on the page I don't want the user to be able to click within the container, therefore I've set pointer-events to none, however I still want the user to be able to click anywhere on the page except the modal to close it. The problem is without pointer events set to none hover styles still appear on page elements, I want to disable the hover effects. – tomhughes Jul 05 '17 at 11:34
  • Please add your code. – I haz kode Jul 05 '17 at 11:40
  • I think that will be not the correct solution. There is another way i think to use preventDefault or stopPropagration all events aside from click will do it. – ngeksyo Jul 05 '17 at 11:43
  • 1
    I suggest adding a non-clickable overlay on top of your content using pseudo-elements and z-index instead of using js – I haz kode Jul 05 '17 at 11:44
  • Forgive me if I'm wrong, isn't that effectively what I'm doing with the site-container or do you mean an element that overlays the entire site container. Effectively only taking up 100% of the viewport? – tomhughes Jul 05 '17 at 11:46
  • I don't know what .site-container is in your case. Essentially you would have four layers. I will start from the bottom. 1- the content of the website 2- the overlay that covers the content of the website while the modal is open 3- the modal 4- the layer that covers the modal contents. Result: user can't click inside the modal but can click outside anywhere on layer #2 – I haz kode Jul 05 '17 at 11:49
  • add you html if possible or a link if the website is live. – I haz kode Jul 05 '17 at 11:50
  • Sorry, site-container is the wrapper for the entire site, and also where I'm currently using a pseudo element for the site overlay. I can't link to the site unfortunately because it's behind a paywall, I'll try upload some HTML now. – tomhughes Jul 05 '17 at 11:51

2 Answers2

1

You can use this work around. Set pointer-events: none to the element that has the hover effects, And add a wrapper div to the elements that still needs to be triggered on click.

$(".cant-click-this").on("click", function(ev) {
  console.log("You cant trigger the element, and it has no hover effects.");
});
$(".click-me-instead").on("click", function(ev) {
  console.log("You can trigger click through the wrapper.");
});
.cant-click-this {
  pointer-events: none;
}

.cant-click-this:hover {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="click-me-instead">
  <button class="cant-click-this"> Try to click me</button> <br>Hovering is futile.
</div>
Rithwik
  • 1,128
  • 1
  • 9
  • 28
0

As I mentioned in the comments, you can achieve this by adding a non-clickable overlay on top of your content using pseudo-elements and z-index

Essentially you have four layers.

  1. the content of the website (white)
  2. the overlay that covers the content of the website while the modal is open (grey)
  3. the modal (red)
  4. the layer that covers the modal contents. (transparent)

Result: user can't click inside the modal but can click outside anywhere on layer #2

Rough example:

.modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  opacity: 0;
  pointer-events: none;
  background: rgba(0, 0, 0, .5)
}

.close {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  opacity: 0;
  display: none;
  z-index: 1;
  position: fixed;
  cursor: default;
}

.modal-content:after {
  content: "";
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
}

.modal:target {
  opacity: 1;
  pointer-events: auto;
}

.modal:target>.close {
  display: block;
}

.modal>div {
  width: 300px;
  text-align: center;
  padding: 40px;
  z-index: 2;
  position: relative;
  background: red;
}

.wrap,
.modal {
  display: flex;
  align-items: center;
  justify-content: center
}
<div class="wrap">
  <a href="#M"><button>You can click me!</button></a>
  <div id="M" class="modal">
    <div class="modal-content">
      <a href="#"><button>But not me!</button></a>
    </div>
    <a href="#" class="close"></a>
  </div>
</div>
I haz kode
  • 1,587
  • 3
  • 19
  • 39