'pointer-events:none but capture click

is it possible to allow only click and disable all other pointer-events

top-layer has a search bar

bottom-layer has a word cloud

I have set pointer-events:none on top-layer, so all words in the word cloud can be hovered over even if they are below the search bar.

but I want the click event on the input text to be enabled, so that when the user wants to type in something, he can.

enter image description here

Here is a related fiddle

The text is behind the input, but it should be hoverable, the input is above the text, but it should be focusable using mouse, to allow the user to type in.

Note: it looks like a placeholder thing, but it is not. please see the original image to see what i am trying to achieve.



Solution 1:[1]

Because pointer-events is blocking interactieve events(click, hover, mouseenter etc.) it would be only accessible with javascript (through focus for example).

It's maybe not the best solution but it will do I guess in your case?

(function($) {
  var focus = false;
  $(document).on('click', function(e) {
    console.log(focus);
    e.preventDefault();
    if (focus) {
      focus = false;
      $('.cl1').trigger('blur');
    } else {
      focus = true;
      $('.cl1').focus();
    }
  });
})(jQuery);

a fiddle with this working solution: https://jsfiddle.net/cob02bpv/1/

Edit: you could check on which element was clicked, only elements under the input will be tricky.

If its not the solution the only one would be to calculate the coordinates from the input box and check where the click event was triggered. But still you would have problems for your elements under the input box.

Solution 2:[2]

I think this should work. Listening to the click event on the parent container, getting the event.clientX and event.clientY values to check if they are within the bounds of the input element. If so, you can then set the focus to the input element. You can still determine if one of the random words underneath the input element has been clicked.

var d = document,
    c = d.getElementsByClassName('container').item(0),
    inp = d.createElement('input'),
    a = 50,
    i = 0;


/*
 | get the clientBoundingRect of the input element
 | and if the mouse x and mouse y positions are within
 | the bounds set the focus on to the input element.
------------------------------------------------------------- */
function inpClickHndl (evt) {
  var inpRect = inp.getBoundingClientRect(),
      x = evt.clientX,
      y = evt.clientY,
      l = inpRect.left,
      w = l + inpRect.width,
      t = inpRect.top,
      h = t + inpRect.height;

  if (x >= l && x <= w && y >= t && y <= h) {
    inp.focus();
  }
}

/* 
 | ignore this, it's just to create the random words.
------------------------------------------------------------- */
function wordClickHndl (evt) {
  this.style.color = "yellow";
}

for (i; i < a; i++) {
  var p = d.createElement('p'),
      t = d.createTextNode('Random Word');
  p.appendChild(t);
  p.addEventListener('click', wordClickHndl, false);
  p.style.position = 'absolute';
  p.style.top = Math.floor(Math.random() * (window.innerHeight - 80)) + -40 + 'px';
  p.style.left = Math.floor(Math.random() * (window.innerWidth - 80)) + -40 + 'px';
  p.style.fontSize = Math.floor(Math.random() * (38 - 8)) + 8 + 'px';
  p.style.fontWeight = 'bold';
  c.appendChild(p);
}

inp.setAttribute('type', 'text');
c.appendChild(inp);

/*------------------------------------------------------------- */

// add a click handler to your parent element.
c.addEventListener('click', inpClickHndl, false);
body {
  margin: 0;
  font-family: sans-serif;
}

.container {
  position: relative;
  height: 100vh; width: 100vw;
  background-color: #1a1a1a;
}

.container p {
  color: green;
}

.container p:hover {
  color: red;
  cursor: pointer;
}

.container input {
  position: absolute;
  top: 50%; left: calc(50% - 85px);
  pointer-events:none;
  opacity: .75;
}
<div class="container"></div>

Solution 3:[3]

Just add the pointer-events CSS3 property, setting as initial to the text box. Using !important is recommended also, so because another property can pass that added.

In CSS3:

pointer-events:initial !important

In JavaScript:

document.querySelector('input[type=text]').style.pointerEvents="initial"

Solution 4:[4]

If layout permits it you could use the adjacent sibling combinator, given that you re-order the elements:

Tested on FireFox and Chrome.

.backText:hover {
  color           : red;
}
.cl1 {
  opacity         : 0.7;
  position        : absolute;
}
/* adjacent sibling combinator */
.wrap-input:hover + div {
  color           : red;
}
.cl1:focus {
  opacity         : 1;
}
<div>
  <div class="wrap-input">
    <input type="text" class="cl1" value="aa" />
  </div>
  <div class="backText">
     Some text to be hovered even if input is above
  </div>
</div>

Other options

The following only works on FireFox. Tested on Chrome and it flickers when pointer is moved, - but could perhaps give some ideas.

Instead of setting pointer-events on the input-element directly, set it using the :hover pseudo-class.

Example, based on your fiddle:

.cl1 {
  position        : absolute;
  top             : 0px;
  opacity         : 0.7;
  height          : 30px;
}
/* Move pointer-events here */
.cl1:hover {
  pointer-events  : none;
}
.cl1:focus {
  opacity         : 1;
}

.backText:hover {
  color           : red;
}
<div>
  <div class="backText">
     Some text to be hovered even if input is above
  </div>
  <div>
    <input type="text" class="cl1" />
  </div>
</div>

Solution 5:[5]

I had the same problem in the past. I managed to solve it in a bit tricky way, just added parent division with button inside and applied click event on parent element and pointer-events: none to child button element.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yoram de Langen
Solution 2
Solution 3 Klaider
Solution 4 Community
Solution 5 la_petite_kozel