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

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - 蓓蕾心晴

语雀思维导图如何导入到飞书文档 js 实现点击触发复制口令到剪贴板,并跳转 华为鸿蒙手机通过Chrome DevTools调试App内WebView页面 vscode左侧搜索栏搜索时排除不参与搜索的文件夹 css动画已经执行过一次如何再次执行? vscode设置单击选中带连字符的单词 移动端盒子元素实现左右可滑动且竖向页面可滑动 js 判断设备类型包括异形屏 element ui 日期组件实现仅显示日期选择但值包含固定的时间 master远端代码更新,本地拉取不到 css 实现刘海屏样式兼容并支持 js 获取刘海屏高度后动态修改 css 判断在支持某些属性的情况下再添加样式 vue3 provide的值 在回调函数中改变,inject 如何获取到最新的值? vue3如何将 app 全局变量对象变为响应式并监听到某个属性的改变 ResizeObserver loop completed with undelivered notifications. 报错 git 修改本地仓库的远程仓库地址 git突然无法推送到远程仓库 css实现图片等比例完全展示,背景加图片 200%放大虚化 element-ui 使用 el-date-picker 如何限制时间选择范围? element-ui 使用 el-date-picker 如何监听数据变更?
css 背景模糊在真机测试会出现黑色蒙层闪现问题解决
蓓蕾心晴 · 2026-03-17 · via 博客园 - 蓓蕾心晴

背景

使用 css  设置 blur 设置背景模糊的时候,使用了 transform: scale(10px); ,在移动端真机上测试时,无论安卓还是 iOS,都会出现页面首次加载,图片会首次请求的时候,先出现黑色蒙层遮罩,再渲染图片,黑色蒙层遮罩消失的情况,这在一些已实现的按钮下面还会出现按钮下方的周边区域却无黑色遮罩的情况。

解决方案

将 transfrom: scale 改成 transfrom: scale3d

代码实现:

以下为 less 实现的一个混合函数,可以直接使用

/* 完整的背景高斯模糊样式 - 包含模糊层和原图层 */
/* @scale: 模糊图片放大倍数, @blur: 模糊像素, @blurImgUrl: 模糊层图片地址, @bgImgUrl: 背景层图片地址(可选) */
/* 注意:调用者需要自行设置定位方式(relative/absolute/fixed) */
.bg-blur(@scale: 1.5, @blur: 10px, @blurImgUrl: '', @bgImgUrl: '') {
  overflow: hidden;
  position: relative;

  // 模糊层(底层)- 独立控制,只要传入了模糊图片就显示
  & when not (@blurImgUrl = '') {
    &::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-image: @blurImgUrl;
      background-size: contain;
      background-repeat: no-repeat;
      background-position: center;
      -webkit-filter: blur(@blur);
      filter: blur(@blur);
      -webkit-transform: scale3d(@scale, @scale, 1);
      transform: scale3d(@scale, @scale, 1); /* 触发 GPU 加速,关键步骤,使用 transform:scale 会导致真机页面初次展示有黑色遮罩出现的问题 */
      will-change: transform; /* 提示浏览器优化 */
      z-index: 1;
    }
  }

  // 原图层(顶层)- 独立控制,只要传入了背景图片就显示
  & when not (@bgImgUrl = '') {
    &::after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-image: @bgImgUrl;
      background-size: contain;
      background-repeat: no-repeat;
      background-position: center;
      z-index: 2;
    }
  }
}

核心原理

1. 核心原因:2D 变换与 filter: blur() 的渲染冲突

(1) 2D 变换 (scale()) 的渲染流程

  • 在移动端浏览器(尤其是 WebKit/Blink 内核)中,2D 变换(如 scale())和 CSS 滤镜(如 blur())通常由 CPU 处理,而非 GPU。
  • 当伪元素(::before)同时应用 filter: blur() 和 scale(1.5) 时,浏览器会分两步渲染:
    1. 先渲染模糊效果:对透明背景(或未加载完成的图片)应用 blur(),此时透明像素会被视为黑色,导致黑色蒙层。
    2. 再应用缩放:对已模糊的黑色背景进行缩放,导致视觉上“先黑后模糊”的闪动。

(2) 3D 变换 (scale3D()) 的渲染优化

  • 强制 GPU 加速:scale3D() 会触发浏览器的硬件加速(通过创建新的 合成层),将变换和滤镜的计算交给 GPU 处理。
  • 渲染顺序优化:GPU 会并行处理模糊和缩放,避免 CPU 串行渲染时的中间状态(黑色蒙层)。
  • 抗锯齿优化:3D 变换在 GPU 中会应用更好的抗锯齿算法,减少模糊边缘的锯齿感。

2. 为什么 filter: blur() 是“帮凶”?

  • 模糊滤镜对透明背景的处理:blur() 滤镜在作用于透明像素时,会将其视为黑色(这是 CSS 规范的行为)。如果图片未加载完成或伪元素背景透明,就会先显示黑色。
  • 2D 变换的“阻塞”效应:在 CPU 渲染中,scale() 会阻塞后续渲染步骤,导致黑色蒙层短暂停留;而 scale3D() 通过 GPU 加速跳过此阻塞。

3. 验证实验:隔离变量

(1) 仅用 filter: blur()(无缩放)

.element::before {
  filter: blur(10px);
  background-color: transparent; /* 透明背景 */
}
  • 结果:在移动端可能仍会看到黑色闪现(因为模糊滤镜本身会处理透明像素)。

(2) 仅用 scale(1.5)(无模糊)

  • 结果:通常不会出现黑色闪现(因为没有滤镜参与,仅缩放)。

(3) 同时用 filter: blur() + scale3D(1.5, 1.5, 1)

  • 结果:黑色闪现消失(GPU 加速优化了渲染流程)。

总结:

  • 直接原因:黑色闪现是 2D 变换 + filter: blur() + 透明背景 共同导致的渲染中间状态。
  • 根本原因:移动端浏览器对 2D 变换和滤镜的 CPU 渲染流程存在缺陷,而 3D 变换通过 GPU 加速绕过了此问题。
  • 最佳实践:在移动端同时使用 filter 和 transform 时,优先选择 scale3D,并配合 will-change 或占位策略。

通过这种方式,你可以彻底避免黑色闪现,同时保持模糊背景的平滑渲染效果。