CSS特效:pointer-events: none;的一种特殊应用

一、需求描述

今天看到一个设计需求:需要在弹框中显示如下界面,其中有两个效果:
1.顶部点击项目,下面的内容能相应滚动定位,同时滚动的时候顶部项目也能相应激活显示
2.顶部右侧有一个模糊渐变效果,并且要保证不影响项目的点击
在这里插入图片描述

二、功能实现

第一点,实现很简单,核心代码如下:

<div class="drug-detail-content">
      <van-tabs v-model:active="active" @click-tab="handleTabClick">
        <van-tab v-for="i in ['适用症', '包装规格', '用法用量', '不良反应', '禁忌事项']" :title="`${i}`"></van-tab>
      </van-tabs>
      <div ref="tabContentRef" class="tabs-content">
        <div class="tab-title">适用症</div>
        <div class="tab-content">
        </div>
        <div class="tab-title">包装规格</div>
        <div class="tab-content">
        </div>
        <div class="tab-title">用法用量</div>
        <div class="tab-content">
        </div>
        <div class="tab-title">不良反应</div>
        <div class="tab-content">
        </div>
        <div class="tab-title">禁忌事项</div>
        <div class="tab-content">
        </div>
      </div>
    </div>
const visiable = ref(false)
const active = ref(0)
import { useEventListener, useDebounceFn } from '@vueuse/core'
const tabContentRef = ref()

let isClick = false // 防止点击引起的内容区滚动影响tab激活
const handleTabClick = ({name}) => {
  const ele = tabContentRef.value.getElementsByClassName('tab-title')[name]
  isClick = true
  ele?.scrollIntoView()
}
 
const show = () => {
  visiable.value = true
  nextTick(() => {
    useEventListener(tabContentRef.value, 'scroll', useDebounceFn(() => {
      if(isClick) {
        isClick = false
        return ;
      }
      const scrollTop = tabContentRef.value?.scrollTop
      const eles = tabContentRef.value?.getElementsByClassName('tab-title')
      if(eles) {
        const tops = []
        Array.from(eles)?.map(o => {
          tops.push(o.offsetTop - 20)
        })
        active.value = tops.findIndex((v, i) => {
          return v <= scrollTop && scrollTop < tops[i+1]
        })
      }
    }, 300))
  })
}

第二点,它的实现,就得提到我们今天要说的pointer-events: none;

先看一下实现的效果:
在这里插入图片描述
可以看到我们利用伪元素::after,在wrap的右侧覆盖了带渐变背景的层:

background-image: linear-gradient(90deg,hsla(0,0%,100%,.5),#fff);

为了不让这个层影响我们点击后面的tab,这里重点需要对这个伪元素的层设置pointer-events: none;,它在这里起到一种点击“击穿”的效果:

By setting pointer-events to none, the element becomes “transparent” to pointer events, meaning it won’t capture any clicks or other pointer interactions, and they’ll pass through to the element behind it.
参考:How to Prevent Elements Receiving Click Events With CSS

### pointer-events: none 和 cursor: pointer 同时生效的原因 当 `pointer-events: none` 和 `cursor: pointer` 同时应用于一个元素时,会出现看似矛盾的行为。这是因为 `pointer-events: none` 的作用是使该元素不再成为鼠标事件的目标[^3],而 `cursor` 属性仅在元素能够响应鼠标事件时才生效[^4]。因此,当 `pointer-events: none` 被设置时,元素本身无法响应鼠标事件,包括改变光标的样式。 然而,如果父级元素设置了 `pointer-events: none`,但其子元素设置了 `pointer-events: auto`,那么子元素仍然可以响应鼠标事件,并且其 `cursor` 属性也会正常生效。这种情况下,子元素的 `cursor` 样式会覆盖父级的禁用效果。 --- ### 解决冲突的方案 #### 方案一:使用伪类或 JavaScript 动态调整 可以通过伪类或 JavaScript 来动态调整光标样式。例如,当用户将鼠标悬停在禁用的元素上时,可以通过检测鼠标位置来显示自定义光标。 ```javascript document.querySelector('.disabled-element').addEventListener('mouseover', () => { document.body.style.cursor = 'not-allowed'; }); document.querySelector('.disabled-element').addEventListener('mouseout', () => { document.body.style.cursor = 'default'; }); ``` 这种方式可以绕过 CSS 中的限制,直接通过 JavaScript 控制光标行为。 --- #### 方案二:利用后代元素实现视觉效果 如果需要在禁用元素上显示特定的光标样式,可以为其添加一个透明的后代元素,并设置 `pointer-events: auto` 和 `cursor: pointer`。这样,用户看到的是禁用元素的外观,但实际上是与后代元素交互。 ```html <div class="parent" style="pointer-events: none;"> <div class="child" style="pointer-events: auto; cursor: pointer;"></div> </div> ``` 在这种情况下,尽管父级元素禁用了鼠标事件,但子元素仍然可以响应并显示指定的光标样式。 --- #### 方案三:移除 pointer-events: none 如果 `pointer-events: none` 并非必须,可以直接移除该属性,并通过其他方式(如 `event.preventDefault()`)阻止默认行为。这样可以确保 `cursor` 属性正常生效。 ```javascript document.querySelector('.element').addEventListener('click', (event) => { event.preventDefault(); }); ``` --- ### 总结 `pointer-events: none` 和 `cursor: pointer` 同时生效的根本原因是 `pointer-events: none` 禁用了元素的鼠标事件响应能力,导致 `cursor` 属性无法生效[^4]。解决这一问题的方法包括通过 JavaScript 动态调整光标样式、利用后代元素实现视觉效果,或者移除 `pointer-events: none` 并通过其他方式阻止默认行为。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓风伴月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值