Record a use of pointer-events

pointer-events

Article first published on personal blog

Scenes

I encountered such a scene in a company project: there is a product (with icon, price and other information), when hovering to the icon, there should be a floating tooltips to display its detailed information, when the product is disabled, there will be a black The mask is covered on top, and it can't be selected at this time. Then the problem comes. I want to hover over the icon to display the tooltips, but there is a black mask on it. What should I do?

The code is as follows (some tags have been removed to prevent the code from being too long):

<style>
  .container {
    width: 500px;
    height: 300px;
    background: red;
    position: relative;
  }
  .mask {
    width: 100%;
    height: 100%;
    background: green;
    position: absolute;
    z-index: 2;
  }
  .content {
    width: 500px;
    height: 300px;
    background: blue;
  }
</style>
<body>
  <div class="container">
    <div class="mask"></div>
    <p class="content">我是内容</p>
  </div>

  <script>
    const mask = document.querySelector('.mask');
    const container = document.querySelector('.container');
    const content = document.querySelector('.content');

    content.addEventListener('mouseenter', () => {
      console.log('content mouseenter');
    });
    mask.addEventListener('mouseenter', () => {
      console.log('mask mouseenter');
    });
    container.addEventListener('mouseenter', () => {
      console.log('container mouseenter');
    });
  </script>
</body>
复制代码

However, its effect now is that when I hover up, the print order is as follows:

// container mouseenter
// mask mouseenter
复制代码

At that time, after thinking about it, I kept thinking about how to solve this problem. There was a mask on it, but it was triggered mouseenteron the top. , and then came the sentence: wonderful.contentpointer-events

What are pointer-events?

Let's take a look at its definition on Mdn

The pointer-events CSS property specifies under what circumstances (if any) a particular graphic element can be the trigger for mouse events.

It has many values:

/* Global values */
pointer-events: inherit;
pointer-events: initial;
pointer-events: unset;

/* Keyword values */
pointer-events: auto;
pointer-events: none;
/* 以下的属性仅适用于SVG */
pointer-events: visiblePainted;
pointer-events: visibleFill;
pointer-events: visibleStroke;
pointer-events: visible;
pointer-events: painted;
pointer-events: fill;
pointer-events: stroke;
pointer-events: all;
复制代码

To solve the above problem, you only need <div class='mask'>to add one pointer-events: noneto the above, let's take a look at the printing order:

// container mouseenter
// content mouseenter
复制代码

Why? Let's take a look at pointer-events:nonethe explanation on the Mdn documentation:

Elements never become triggers for mouse events. However, a mouse event can point to a descendant element when its descendant element's pointer-events property specifies a different value, in which case the mouse event will trigger the parent element's event listener during the capture or bubbling phase.

So we .maskadded this attribute on the above, it will not become the trigger of the mouse event, so the trigger of the mouse event will be successfully become .content, and this problem has been successfully solved.

But we see this definition, but when its descendant element also specifies this attribute, and it is not none, the mouse event can point to descendant element, and the rest is omitted... Let's try to write a demo again:

<style>
  .mask-child {
    width: 200px;
    height: 300px;
    background: yellow;
    pointer-events: auto;
  }
</style>
<body>
  <div class="container">
    <div class="mask">
      <div class="mask-child"></div>
    </div>
    <p class="content">我是内容</p>
  </div>

  <script>
    const maskChild = document.querySelector('.mask-child');

    maskChild.addEventListener('mouseenter', () => {
      console.log('maskChild mouseenter');
    });
  </script>
</body>
复制代码

Add this part to the code just now, let's take a look again, it should be noted that we .maskadded a child .mask-child, and then listened to its mouseenterevents, let's take a look at the effect:

// container mouseenter
// mask mouseenter
// maskChild mouseenter
复制代码

Unsurprisingly, it is still the same maskevent that will be triggered mouseenter, so we know that if you want to skip the specified event of an element, we can set one on it pointer-events:none, but it should be noted that its descendants should not specify pointer-eventsattributes again , otherwise it will still fail.

Example

  1. Does not trigger mouse events (drag, hover, click, etc.).
<style>
  button {
    pointer-events: none;
  }
</style>
<button onclick="handleClick()">测试</button>
<script>
  function handleClick() {
    console.log('handleClick');
  }
</script>
复制代码

does not print handleClick.

  1. Also, if it is set :hover, the :activepseudo-class will not be triggered.

Like before, if we wanted to cancel the hovereffect of a disabled element, we might write it like this:

<p class="content disable"></p>

<style>
  .content:not(disable):hover {
  }
</style>
复制代码

And now we can write it like this, is it simpler?

<p class="content disable"></p>

<style>
  .content.disable {
    pointer-events: none;
  }
  .content:hover {
  }
</style>
复制代码

In fact, there is a simpler method, which is to .disableput it below, because of the priority of css.

<p class="content disable"></p>

<style>
  .content:hover {
    background: black;
  }
  .content.disable {
    background: yellow;
  }
</style>
复制代码

Summarize

The above is the whole content of this article, it is a small record for myself, I hope it can help you.

Guess you like

Origin juejin.im/post/7079688237035290654