純CSS屬性pointer-events:none解決滾動穿透問題


·什么是滾動穿透:

在移動端的前端開發中,我們常常會用到Modal彈窗,又稱模態框,用來在已有頁面顯示新的選項、提示或新內容。遮罩層常出現在彈窗后,用來在視覺上,幫助用戶集中注意力,功能上,防止用戶繼續操作頁面上的其他內容。遮罩層通常是一個絕對定位,寬高充滿內容區域或可視區域,層級略低於彈窗的具有一定透明度的背景。

在Web端,我們只需要通過CSS設置上述屬性,就可以完成實現“遮罩實現”的功能,但當用戶使用鼠標滾輪,或者在移動端,通過手指滑動時,我們發現:

位於遮罩層背后的內容,穿透了我們設置的遮罩層,跟隨用戶的操作發生滾動。這種現象,就被稱為“滾動穿透”。

·你可能會想到的解決滾動穿透問題的方法:

看到這種由非直接目標對象響應事件的現象,很多人都會想到 Js的事件處理機制,進而想到,阻止事件冒泡,避免對Modal彈窗層的操作,冒泡到遮罩層下。

然而這種思路並不總是行得通,冒泡的前提,是兩個對象具有父子關系,事件從子對象傳遞到父對象,然而我們的彈出層經常被直接append到body或根節點中,與原有內容在一個層級,用阻止冒泡的方法並不能達成目的。

事實上,位於遮罩層下方的可滾動元素和上方的彈出層,由於重疊,直接響應了用戶的操作,而不是接受上層的事件傳遞。

那我們可不可以阻止默認事件呢?

通過preventDefault()阻止默認事件,任何通常被該實現觸發並作為結果的默認行為都不會發生,上層和下層元素的默認滾動行為都將被阻止,這顯然並不是我們想要的。

此外,還有很都方法,通過十幾行甚至幾十行代碼,在移動端,阻止滾動穿透,有點大材小用啦。

·化繁為簡,一行CSS3屬性解決滾動穿透問題

讓我們先認識這個CSS3屬性 pointer-events,它的默認屬性值是auto,而對於前端開發,另一個值 none,顯然更有用。通過設置:

 

pointer-events: none > 元素永遠不會成為鼠標事件的target。但是,當其后代元素的pointer-events屬性指定其他值時,鼠標事件可以指向后代元素,在這種情況下,鼠標事件將在捕獲或冒泡階段觸發父元素的事件偵聽器。

 

將MDN的解釋形象化,你可以把設置 pointer-events: none 看成一張透明紙,它本身不再響應鼠標事件(事實上,也包括移動的手指觸摸Touch事件),卻可以傳遞事件,讓事件穿過它自己,繼續傳到父級。

 

簡而言之,我們想讓哪層不滾動,只需要給這層設置 pointer-events: none 。

配合彈窗的狀態,當彈窗顯示的時候,給位於遮罩層底下的圖層設置  pointer-events: none ,當彈窗隱藏/關閉的時候,設置  pointer-events: auto ,或者干脆移除這個屬性。

 

pointer-events 是一個比較早公布的CSS3屬性,在Web端和移動端都有良好的支持度:

 

 
CSS3的屬性pointer-events的瀏覽器和移動端兼容性圖示
CSS3的屬性pointer-events的瀏覽器和移動端兼容性圖示


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM