猴赛雷的pointer-events,一个你可以用不到但是不能不知道的 CSS属性

之前有一次美团的面试,面试官问我:如果有两个元素,一个元素覆盖到另一个元素上,如何做到点击上面的元素触发下面的元素? 当时的我在工作生涯中其实并没遇到过这种问题,也没有想到为什么会有这种情况的出现,也只是凭着自己的工作经验想出一个可以通过父子元素冒泡的做法实现这个做法,面试官虽说这个方法确实可以实现这个需求,我向他询问应该如何实现这个功能的时候,才首次认识了我们在这篇文章中要了解的pointer-events属性。

pointer-event是什么?有什么作用?

pointer-events 属性用于设置元素是否对鼠标事件做出反应。 默认值为auto,就是元素对鼠标事件做出反应,可设置为pointer-events: none; 表示元素忽略鼠标事件。

用最简单的话来说,只要设置了pointer-events: none; 任何鼠标事件都将被无效化(例如:点击事件、鼠标移入移除、css的hover等)。

让我们上代码来看下没有设置pointer-events: none; 的效果是什么

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<style>
	#demo {
		width: 200px;
		height: 200px;
		background-color: aqua;
		text-align: center;
		line-height: 200px;
	}
	#demo:hover {
		background-color: bisque;
	}
</style>
<body>
	<div id="demo">我是测试的div</div>
	<script>
		const demo = document.getElementById('demo');
		demo.onclick = e => {
			console.log('点击了');
		};
		demo.onmouseenter = e => {
			console.log('移入了');
		};
		demo.onmouseleave = e => {
			console.log('移出了');
		}
	</script>
</body>
</html>

上面的代码写了一个div元素,我们在这个元素上绑定了点击、鼠标移入、鼠标移出这三个js鼠标事件,并在css上绑定了hover样式,鼠标进入会改变元素的背景色,现在这个demo是这个样子的

这个就是正常我们元素对鼠标事件响应的样子,接下来我们在demo元素上加上pointer-events: none; 属性 看一下是什么样子

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<style>
	#demo {
		width: 200px;
		height: 200px;
		background-color: aqua;
		text-align: center;
		line-height: 200px;
		pointer-events: none;
	}
	#demo:hover {
		background-color: bisque;
	}
</style>
<body>
	<div id="demo">我是测试的div</div>
	<script>
		const demo = document.getElementById('demo');
		demo.onclick = e => {
			console.log('点击了');
		};
		demo.onmouseenter = e => {
			console.log('移入了');
		};
		demo.onmouseleave = e => {
			console.log('移出了');
		}
	</script>
</body>
</html>

上面代码仅增加了一行pointer-events: none; 接下来我们看看元素对于鼠标事件是什么反应

我们可以看到代码中的js鼠标事以及hover全部都无效化了,元素没有对以上操作做出反应(鼠标点击选中文字是可以的)

现在我们知道了pointer-events的作用了,那我们来做一下文章开头说的面试题吧 一个元素覆盖在另一个元素,点击上面的元素触发下面元素的点击事件。

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<style>
	#demo {
		width: 350px;
		height: 400px;
		background-color: #f3f3f3;
		position: fixed;
		left: 50%;
		transform: translateX(-50%);
		color: red;
	}
	#bottom {
		width: 200px;
		height: 200px;
		background-color: red;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		z-index: 1;
		color: azure;
	}
	#top {
		width: 300px;
		height: 300px;
		background-color: yellow;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		opacity: 0.4;
		z-index: 2;
		color: black;
	}
</style>
<body>
	<div id="demo">
		我是父元素盒子
		<div id="bottom">我是下面的元素</div>
		<div id="top">我是上面的元素</div>
	</div>
	<script>
		const bottom = document.getElementById('bottom');
		bottom.onclick = e => {
			console.log('点击了');
		};
		bottom.onmouseenter = e => {
			console.log('移入了');
		};
		bottom.onmouseleave = e => {
			console.log('移出了');
		}
	</script>
</body>
</html>

在最上层盒子上加上 pointer-events: none; 之后

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<style>
	#demo {
		width: 350px;
		height: 400px;
		background-color: #f3f3f3;
		position: fixed;
		left: 50%;
		transform: translateX(-50%);
		color: red;
	}
	#bottom {
		width: 200px;
		height: 200px;
		background-color: red;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		z-index: 1;
		color: azure;
	}
	#top {
		width: 300px;
		height: 300px;
		background-color: yellow;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		opacity: 0.4;
		z-index: 2;
		color: black;
		pointer-events: none;
	}
</style>
<body>
	<div id="demo">
		我是父元素盒子
		<div id="bottom">我是下面的元素</div>
		<div id="top">我是上面的元素</div>
	</div>
	<script>
		const bottom = document.getElementById('bottom');
		bottom.onclick = e => {
			console.log('点击了');
		};
		bottom.onmouseenter = e => {
			console.log('移入了');
		};
		bottom.onmouseleave = e => {
			console.log('移出了');
		}
	</script>
</body>
</html>

pointer-events 的基础知识我们就说完了,附上一个最近在实际工作中使用pointer-events完成的一个功能模块的图片吧(工作代码就不展示了,就当做是一个使用场景,以后有这种需求的话可以用pointer-events进行实现)。

需求:有一个球场的图片,里面分割了很多模块,点击某一模块展示一个模块被选中的样式。

当时的第一想法就是背景图上覆盖元素,图片上有24个模块,只需要循环24个元素覆盖到上面,点击的时候某个模块展示被选中的样式就好,做出来的效果就是这样的

这么做的问题就是,整个背景图都会被覆盖掉,球场线根本就看不到,尤其是我全都选中之后,根本就看不出这是个球场了,所以就稍加改动,让背景图覆盖我要展示选中的元素上面,通过给背景图所在元素上添加pointer-events: none; 即可完美的实现我们要实现的功能了

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax