惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
V
Vulnerabilities – Threatpost
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
Know Your Adversary
Know Your Adversary
K
Kaspersky official blog
T
Tor Project blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Cloudflare Blog
Simon Willison's Weblog
Simon Willison's Weblog
雷峰网
雷峰网
I
Intezer
C
Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Latest news
Latest news
C
CERT Recently Published Vulnerability Notes
P
Privacy International News Feed
P
Proofpoint News Feed
F
Fortinet All Blogs
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
宝玉的分享
宝玉的分享
量子位
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Announcements
Recent Announcements
D
Darknet – Hacking Tools, Hacker News & Cyber Security
aimingoo的专栏
aimingoo的专栏
A
Arctic Wolf
Martin Fowler
Martin Fowler
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
IT之家
IT之家
小众软件
小众软件
T
The Blog of Author Tim Ferriss
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
TaoSecurity Blog
TaoSecurity Blog
D
DataBreaches.Net
Webroot Blog
Webroot Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
美团技术团队
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog

戴兜的小屋

Hi! 2024 - 戴兜的小屋 [简中] Google Summer of Code & Chrome Extensions - 戴兜的小屋 Google Summer of Code & Chrome Extensions - 戴兜的小屋 SCSS+WindiCSS实现主题色切换 - 戴兜的小屋 Plaid CTF Writeup [Treasure Map/CSS] - 戴兜的小屋 写一个炫酷的个人名片页✨✨ - 戴兜的小屋 【戴兜的游戏安利】Hi-Fi RUSH,不可多得的动作爽游 - 戴兜的小屋 Manifest V3扩展Content Script绕过CSP限制点击页面内元素 - 戴兜的小屋 在 Nuxt.js 中配合 windicss 实现暗黑模式适配 - 戴兜的小屋 实现滚动时Header自动隐藏 - 戴兜的小屋 你好!2023 - 戴兜的小屋 !important导致TransitionGroup失效 - 戴兜的小屋 新年快乐! - 戴兜的小屋 CSS Layout API初探:瀑布流布局实现 - 戴兜的小屋 你好! 2022 - 戴兜的小屋 手撸一个前端天气卡片 - 戴兜的小屋 Hi!2021 - 戴兜的小屋 服务器又搬迁啦! - 戴兜的小屋 base64数据隐写实现原理分析 - 戴兜的小屋
优雅地实现滚动容器遮罩 - 戴兜的小屋
戴兜文章作者 · 2023-12-09 · via 戴兜的小屋

在设计前端页面时,常常会遇到这种情况:可滚动容器的边界并非父容器的边界,导致子元素溢出造成裁切,让页面产生比较怪异的视觉效果(左图)

添加遮罩之后,效果自然了许多(右图)

纯色遮罩

以上图的这种情况举例,我们需要做的,是在可滚动容器的顶部和底部分别放置一个线性渐变的纯色遮罩,遮挡生硬的裁切线。创建两个元素 .top-mask.bottom-mask 来作为遮罩,遮罩的颜色与父容器背景一致,使用 absolute 定位。

.top-mask {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 24px;
    background: linear-gradient(to top, transparent 0%, white 100%);
}

.bottom-mask {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 24px;
    background: linear-gradient(to bottom, transparent 0%, white 100%);
}

直接为可滚动容器设置 position: relative 是行不通的,这会导致遮罩跟随容器滚动。所以需要在可滚动容器外部再嵌套一层 relative 定位的元素,使两个遮罩根据其位置定位,最终的结构大概是下面这样的:

<!-- 无遮罩 -->
<div class="out-container">
    <div class="scrollable-container">
        <!-- 很多很多的子元素 -->
    </div>
</div>

<!-- 有遮罩 -->
<div class="out-container">
    <div class="relative-container">
        <div class="top-mask"></div>
        <div class="bottom-mask"></div>
        <div class="scrollable-container">
            <!-- 很多很多的子元素 -->
        </div>
    </div>
</div>

Codepen 查看演示

后续为了优化视觉效果,可以根据条件显示/隐藏对应的 mask 元素(滚动条在顶部时不显示 top-mask,反之亦然)

改进:Alpha 遮罩

上面的这种方法有许多缺陷:

  1. 引入了许多额外的元素,致使整体布局变得复杂。
  2. 蒙版覆盖在可滚动容器之上,需要使用 pointer-events: none; 避免影响滚动操作。
  3. 仅适用于父容器为纯色的场景,在父容器有透明度、有背景图案或渐变时,遮罩会露馅。

是否有一种方法,在不引入额外元素、不使用绝对定位的条件下,解决这些缺陷呢?这时候就可以用到 mask CSS属性。mask 属性允许提供一张图片作为蒙版,改变元素的可视区域。我们只需要生成一个线性渐变,将其作为可滚动容器的蒙版即可。

使用linear-gradient创建一个多段的线性渐变,得到图中的蒙版效果。

linear-gradient(to bottom, transparent 0%, white 25px, white calc(100% - 25px), transparent 100%)

接着,将得到的渐变图案作为 mask 应用到滚动容器上,为了便于自定义,将这里的遮罩高度 25px 提取出来,以 CSS 变量的形式提供。下面是完整的样式:

.scrollable-container {
  --show-top-mask: 0;
  --show-bottom-mask: 0;
  --mask-size: 25px;
  --gradient: linear-gradient(to bottom, transparent 0%, white calc(var(--show-top-mask) * var(--mask-size)),white calc(100% - calc(var(--mask-size)*var(--show-bottom-mask))), transparent 100%);
  -webkit-mask: var(--gradient);
  mask: var(--gradient);
}

.top-mask {
  --show-top-mask: 1;
}

.bottom-mask {
  --show-bottom-mask: 1;
}

因为我们将容器两侧的遮罩合并到了一个线性渐变中,想要控制其中一侧的遮罩就不太容易了,为了实现遮罩的独立控制,额外定义了 --show-top-mask--show-bottom-mask 变量。最终的效果如下图所示:

CodePen 查看