今天做项目中偶然误把元素加上了pointer-events属性,结果导致后来在js中给该元素加点击事件不能用,检查了半天才发现是这个属性的问题。之前没有好好研究,于是决定仔细研究一下。
一、定义及语法
根据MDN上的解释如下:
CSS属性pointer-events
允许作者控制特定的图形元素在何时成为属性事件的target。当未指定该属性时,SVG内容表现如同visiblePainted
。
除了指定元素不成为鼠标事件的目标,none
值还指示鼠标事件穿过该元素,并指向位于元素下面的元素。
初始值 | auto |
---|---|
适用元素 | all elements |
是否是继承属性 | yes |
适用媒体 | visual |
计算值 | as specified |
是否适用于 CSS 动画 | 否 |
正规顺序 | the unique non-ambiguous order defined by the formal grammar |
语法
pointer-events: auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit
值
auto
- 与
pointer-events
属性未指定时的表现效果相同,对于SVG内容,该值与visiblePainted
效果相同 none
- 元素永远不会成为鼠标事件的target。但是,当其后代元素的
pointer-events
属性指定其他值时,鼠标事件可以指向后代元素,在这种情况下,鼠标事件将在捕获或冒泡阶触发父元素的事件侦听器。 visiblePainted
-
只适用于SVG。元素只有在以下情况才会成为鼠标事件的目标:visibility
属性值为visible
,且鼠标指针在元素内部,且fill
属性指定了none
之外的值visibility
属性值为visible
,鼠标指针在元素边界上,且stroke
属性指定了none
之外的值
visibleFill
- 只适用于SVG。只有在元素
visibility
属性值为visible
,且鼠标指针在元素内部时,元素才会成为鼠标事件的目标,fill
属性的值不影响事件处理。 visibleStroke
- 只适用于SVG。只有在元素
visibility
属性值为visible
,且鼠标指针在元素边界时,元素才会成为鼠标事件的目标,stroke
属性的值不影响事件处理。 visible
- 只适用于SVG。只有在元素
visibility
属性值为visible
,且鼠标指针在元素内部或边界时,元素才会成为鼠标事件的目标,fill
和stroke
属性的值不影响事件处理。 painted
-
只适用于SVG。元素只有在以下情况才会成为鼠标事件的目标:- 鼠标指针在元素内部,且
fill
属性指定了none
之外的值 - 鼠标指针在元素边界上,且
stroke
属性指定了none
之外的值
visibility
属性的值不影响事件处理。 - 鼠标指针在元素内部,且
fill
- 只适用于SVG。只有鼠标指针在元素内部时,元素才会成为鼠标事件的目标,
fill
和visibility
属性的值不影响事件处理。 stroke
- 只适用于SVG。只有鼠标指针在元素边界上时,元素才会成为鼠标事件的目标,
stroke
和visibility
属性的值不影响事件处理。 all
- 只适用于SVG。只有鼠标指针在元素内部或边界时,元素才会成为鼠标事件的目标,
fill
、stroke
和visibility
属性的值不影响事件处理。
二、到底什么是pointer-events
pointer-events如上述所言
支持的值很多,但大多都与SVG相关,我们可以不用理会。而对于我们来讲,需要注意的就是[none|auto]两个属性值了。“auto”没什么好说的,就是在正常状态下的元素。本文将着重研究一下“none”。
pointer-events:none
顾名思意,就是让任何鼠标元素对鼠标事件不起作用,这里的鼠标事件包括css中的hover,同时也会关闭js中的onclick。
三、效果
pointer-events:none
的作用不只是禁用链接hover,打开链接等效果,是真实意义上的将onlick
事件去掉了。但是,他不会关闭键盘时间,比如点击"tab"键会切换<a>标签,设置了pointer-events:none的元素同样有反应。
我们看一下例子:
代码如下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> .none{ pointer-events: none; } </style> </head> <body> <a href="#1" class="auto">auto1</a> <a href="#2" class="none">none</a> <a href="#3" class="auto">auto2</a> </body> </html>
注:要想真的将元素鼠标和键盘事件都去掉,可以使用:无href + pointer-events:none
下面内容转载自:http://www.zhangxinxu.com/wordpress/2011/12/css3-pointer-events-none-javascript/
四、实际应用
在IE浏览器下,filter滤镜实现的半透明渐变背景元素本身就是镂空的穿透的,即我们可以使用鼠标选择或点击半透明背景后面的元素,如下截图:
但是对于FireFox或是Chrome等现代浏览器,则半透明覆盖下面的元素会被遮住,无法选择或点击:
此时,我们可以利用pointer-events:none
的“幻影”特性,对半透明覆盖元素应用pointer-events:none
声明使其可以鼠标穿透,于是,半透明覆盖后面的文字可以选择了,链接也可以点击了:
五、兼容性
目前FireFox浏览器,Chrome都支持。Opera以及IE不支持。
六、pointer-events扩展之浏览器支持的JS判断
考虑到某些浏览器不支持CSS3 pointer-events属性,因此,在实际应用的时候,可能要对不同浏览器做不同处理,这个时候就需要判别当前用户浏览器是否支持pointer-events. 下面就是JS实现验证的代码:
var supportsPointerEvents = (function(){ var dummy = document.createElement(‘_‘); if(!(‘pointerEvents‘ in dummy.style)) return false; dummy.style.pointerEvents = ‘auto‘; dummy.style.pointerEvents = ‘x‘; document.body.appendChild(dummy); var r = getComputedStyle(dummy).pointerEvents === ‘auto‘; document.body.removeChild(dummy); return r; })();
上面的代码其实对于浏览器是否支持其他CSS3属性也是比较受用的。
该验证idea来自 Martin Auswöger (https://github.com/ausi/Feature-detection-technique-for-pointer-events)
七、pointer-events扩展之幻影特性的JS替代实现
直接代码(基于jQuery):
function noPointerEvents (element) { $(element).bind(‘click mouseover‘, function (evt) { this.style.display = ‘none‘; var x = evt.pageX, y = evt.pageY, under = document.elementFromPoint(x, y); this.style.display = ‘‘; evt.stopPropagation(); evt.preventDefault(); $(under).trigger(evt.type); }); }
上面展示代码中有个比较有意思的方法就是elementFromPoint
,这东西兼容性还是很不错的。具体可参见我之前这篇“CSSOM视图模式(CSSOM View Module)相关整理”(较长)中的Part 三
部分,有demo示意。
八、小卖弄:a标签按钮完全禁用实例
最后,小小卖弄下,综合本文杂七杂八的内容,做个可能没多大实际意义的实例,就是上面唠叨了很多的a标签按钮完全禁用效果。
按钮UI借鉴新浪微博。
您可以狠狠地点击这里:a标签按钮完全禁用demo卖弄版
注
:本demo是为了应用CSS3 pointer-events
属性而使用了pointer-events
,实际应用无需如此折腾。
本demo应用了上面浏览器是否支持pointer-events
属性的JS扩展。完整JavaScript代码如下:
var supportsPointerEvents = (function(){ //上面验证浏览器支持pointer-events属性代码 })(); var oArea = document.getElementById("testArea"), oButton = document.getElementById("testButton"); oArea.onkeyup = function() { var length = this.innerHTML.length; if (length == 0 || length > 140) { oButton.className = "test_button test_button_disabled"; oButton.removeAttribute("href"); } else { oButton.className = "test_button"; oButton.href = "javascript:"; } }; oButton.onclick = function() { //如果支持CSS3 pointer-events,CSS自动判定是否执行点击事件,脚本这边可以无顾忌执行弹出 //如果不支持CSS3 pointer-events //通过按钮状态判定是否弹出 if (supportsPointerEvents || (!supportsPointerEvents && this.href)) { alert("发送成功"); } return false; };
通过控制href
属性实现完全意义上的禁用。