小技巧 | 漸變消失遮罩的多種實現方式

2023-10-17 12:01:47

我的小冊 《CSS 技術揭祕與實戰通關》上線了,想了解更多有趣、進階、系統化的 CSS 內容,可以猛擊 - LINK

知乎看到一題比較有意思的題目。

題目大致是如何實現下述圖片的效果,如果使用 div 前置遮擋的話,會影響 div 後面的按鈕,使其無法被點選。

本文將簡單介紹幾種這個效果的實現方案。

漸變配合 pointer-event

第一種方式,比較容易想到。使用漸變配合 pointer-event 實現。

簡單模擬一下場景,假設我們有如下一個 ul 列表,超出可以捲動:

<div class="g-container">
    <ul>
        <li>Button</li>
        <li>Button</li>
        <li>Button</li>
        <li>Button</li>
        <li>Button</li>
        <li>Button</li>
    </ul>
</div>
ul {
    width: 300px;
    display: flex;
    flex-wrap: nowrap;
    border: 1px solid #999;
    padding: 5px;
    overflow-x: scroll;
}

像是這樣:

首先,我們需要實現右側的漸變消失的遮罩效果,這個最常見的,就是通過疊加一個從透明到白色的漸變層實現。

這個簡單,我們藉助元素的偽元素,絕對定位到右側即可:

.g-container {
    ...
    
    &::before {
        content: "";
        position: absolute;
        right: 0;
        bottom: 0;
        top: 0;
        width: 100px;
        background: linear-gradient(90deg, transparent, #fff);
    }
}

效果如下:

這樣遮罩就解決了,唯一的問題在於,疊加的這一層,確實遮擋住了其下方的按鈕點選:

這個其實也好解決,只需要給疊加的這一層,新增一個 pointer-event: none 即可。

pointer-event:CSS 屬性指定在什麼情況下 (如果有) 某個特定的圖形元素可以成為滑鼠事件的 target。當值為 none 時,元素永遠不會成為滑鼠事件的 target,也就是我們常說的,實現了滑鼠點選穿透

程式碼如下:

.g-container {
    ...
    
    &::before {
        content: "";
        position: absolute;
        right: 0;
        bottom: 0;
        top: 0;
        width: 100px;
        background: linear-gradient(90deg, transparent, #fff);
        pointer-event: none;
    }
}

如此一來,就能完美實現此效果,有遮罩,且遮罩不會遮擋住下方內容:

完整的程式碼你可以戳這裡:CodePen Demo -- Linear Gradient Mask & Pointer-event

使用 mask 實現更完美的遮罩

但是,上述方法不是最完美的。

假設我們的背景,不是純色,而是漸變色的話,效果會是這樣:

我們希望,內容是真的逐漸消失,而不是通過遮罩遮擋住。所以,我們期待的結果,應該是這樣:

即便是漸變背景,內容仍然可以逐漸消失。

為了解決解決這個問題,CSS 有一個專門的屬性來處理這個問題,也就是 -- mask。

mask:屬性允許使用者通過遮罩或者裁切特定區域的圖片的方式來隱藏一個元素的部分或者全部可見區域。

使用 mask 後,程式碼非常簡單,也不需要 pointer-event

<ul>
    <li>Button</li>
    <li>Button</li>
    <li>Button</li>
    <li>Button</li>
    <li>Button</li>
    <li>Button</li>
</ul>
ul {
    width: 300px;
    display: flex;
    flex-wrap: nowrap;
    overflow-x: scroll;
    mask: linear-gradient(90deg, #000 70%, transparent);
}

由於不存在遮擋物,也就不再需要 pointer-event 了,所有內容都是可以直接點選的:

完整的程式碼你可以戳這裡:CodePen Demo -- Linear Gradient Mask

如果你是第一次接觸 mask,這裡有關於 mask 的一些基礎知識及進階用法,也許你會有興趣:

最後

本文到此結束,希望對你有幫助