猴赛雷的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; 即可完美的实现我们要实现的功能了

相关推荐
NetX行者3 分钟前
基于Vue 3的AI前端框架汇总及工具对比表
前端·vue.js·人工智能·前端框架·开源
独立开阀者_FwtCoder3 分钟前
手握两大前端框架,Vercel 再出手拿下 Nuxt.js,对前端有什么影响?
前端·javascript·vue.js
独立开阀者_FwtCoder4 分钟前
弃用 html2canvas!快 93 倍的截图神器!
前端·javascript·vue.js
weixin_3993806918 分钟前
TongWeb8.0.9.0.3部署后端应用,前端访问后端报405(by sy+lqw)
前端
伍哥的传说39 分钟前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript
洛小豆1 小时前
深入理解Pinia:Options API vs Composition API两种Store定义方式完全指南
前端·javascript·vue.js
洛小豆1 小时前
JavaScript 对象属性访问的那些坑:她问我为什么用 result.id 而不是 result['id']?我说我不知道...
前端·javascript·vue.js
叹一曲当时只道是寻常1 小时前
Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
前端·golang
超级土豆粉1 小时前
npm 包 scheduler 介绍
前端·npm·node.js
bug爱好者1 小时前
原生小程序如何实现跨页面传值
前端·javascript