今天做項目中偶然誤把元素加上了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
屬性實現完全意義上的禁用。