渐变消失遮罩?不在话下

今天,在知乎[1]看到一题比较有意思的题目。

题目大致是如何实现下述图片的效果,如果使用 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;
}

像是这样:

渐变消失遮罩?不在话下插图1

首先,我们需要实现右侧的渐变消失遮罩效果,这个最常见的,就是通过叠加一个从透明到白色的渐变层实现。

这个简单,我们借助元素的伪元素,绝对定位到右侧即可:

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

效果如下:

渐变消失遮罩?不在话下插图2

这样遮罩就解决了,唯一的问题在于,叠加的这一层,确实遮挡住了其下方的按钮点击:

渐变消失遮罩?不在话下插图3

这个其实也好解决,只需要给叠加的这一层,添加一个 pointer-event: none 即可。

pointer-event:CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target[2]。当值为 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;
    }
}

如此一来,就能完美实现此效果,有遮罩,且遮罩不会遮挡住下方内容:

渐变消失遮罩?不在话下插图4

完整的代码你可以戳这里:CodePen Demo — Linear Gradient Mask & Pointer-event[3]

使用 mask 实现更完美的遮罩

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

假设我们的背景,不是纯色,而是渐变色的话,效果会是这样:

渐变消失遮罩?不在话下插图5

我们希望,内容是真的逐渐消失,而不是通过遮罩遮挡住。所以,我们期待的结果,应该是这样:

渐变消失遮罩?不在话下插图6

即便是渐变背景,内容仍然可以逐渐消失。

为了解决解决这个问题,CSS 有一个专门的属性来处理这个问题,也就是 — mask。

mask[4]:属性允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。

使用 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 了,所有内容都是可以直接点击的:

渐变消失遮罩?不在话下插图7

最后

本文到此结束,希望对你有帮助 :)

发表评论

后才能评论

评论(1)