我本来只是想给个弹窗整个毛玻璃,Chrome 上美滋滋,一上 iOS Safari 我人就傻了——页面一滚动,背景糊成了一锅粥,毛玻璃不仅没糊住后面的图,反而自己闪个不停。嘿,你说气不气。
这事还得从前几天说起。前几天我在 arXiv 上刷到一篇编号 2608.06069 的论文,叫啥 Training-Free Token-Level Steering for LLM Personalized Co-Writing。里面弄了个叫 SteerWrite 的框架,说是免训练,能学你的个性化风格来搞合著。我当时第一反应就是:行,那你来学学我的 vibe coding,来给我写个带 backdrop-filter 的组件试试?这头牛,我今天非钻穿不可。
AI 写 CSS 现在的水平,多半还停留在“看起来对”。你让它写个表单骨架、切个图,那都没问题;一到这种阴间合成层的交互细节,它就开始一本正经地胡说八道了。让 AI 帮我生成个 demo?骨架凑合用,交互细节、边界情况?想都别想。它在自己那个跑得欢的 Chrome 里“美滋滋”,一换浏览器就现原形。这报应来得太快。
我就一个一个控制变量往下切。先是我自己写的基础代码,非常干净,就一个中心弹窗:
.modal {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.5);
}
Chrome 上一点事没有,Safari 也看起来挺好的。就离谱,难道是我错怪它了?
然后我把页面拉长,给背景塞了张死长死长的图,让外层容器 overflow: auto。这回我拖动滚动条,好戏开场了。Safari 里的毛玻璃直接抽了,画面肉眼可见地撕裂。
.scroll-container {
overflow-y: auto;
height: 200px;
}
.modal {
position: absolute;
top: 50px;
backdrop-filter: blur(10px);
}
哎,翻车了。为了排除是不是缺前缀的弱智问题,我老老实实加上了 -webkit-。没用。Safari 照样在那儿装死。
我又去试了一下给它套个 transform: translateZ(0)。因为一般遇到这种阴间闪烁,大伙儿第一反应都是强行把它提成一个独立的合成层。结果你猜怎么着?更离谱了。玻璃不闪了,但背后的背景图直接不跟着滚了,活见鬼。玻璃是透了,但透过去看的是一具静态的尸体。🤔
中间我一度拍桌子骂这是 Safari 的 bug。后来我把 will-change 也加进去反复试,把父元素的 transform 去掉又加上,才发现不对劲。文档我之前扫过一眼、没往心里去,这就是不细看的报应。
原来这货在 Safari 里,一旦它的某个祖宗节点也触发了合成层(比如你为了流畅加了个 transform 动画),backdrop-filter 的重算就会出岔子。它本来应该实时去采样它盖住的那一层,结果由于 Safari 对合成层的合并处理跟 Chrome 的引擎走向不一样,它采样的目标错乱了,甚至直接把那一帧给吞了。你说气不气?Chrome 的 Bionic 和 Safari 的 WebCore 在合成层合并这块儿本来就各怀鬼胎,偏偏 backdrop-filter 又是个极其依赖底层合成的属性,硬刚准没好果子吃。
这还没完,我又在弹窗里加了点东西,手贱输了个文字进去。文字直接渲染得跟锯齿一样,边缘全是马赛克。这谁受得了?
为了把这玩意儿逼到求饶,我试了无数种排列组合。最后发现,解法极其阴间:在触发滚动的容器和 .modal 之间,绝对不能有额外的 transform 隔断;而且必须显式声明 will-change: backdrop-filter,强制引擎开个小灶。谁能在不亲自上手摸的情况下,试出这种连错三回才得出的破结论?换 AI 来,它早甩给你三五个方案让你自己挨个试了,它根本没在真 Safari 上跑过。
| 浏览器 | 支持 | 备注 |
|---|---|---|
| Chrome | 76+ | 全绿,合成层表现完美 |
| Edge | 79+ | 跟 Chrome 一致 |
| Firefox | 103+ | 全绿,默认开启无需特殊关照 |
| Safari | 18.0+ (iOS 18.0+) | 部分支持,14-17 版本极度拉胯,跨合成层必撕裂,需要 will-change 兜底 |
拉胯的还是 Safari——你永远可以相信它在交互细节上给你整点阴间活儿。尤其是 17 以下的版本,真的是谁用谁知道。移动端要稳,建议直接用 @supports 查一下,不行就给个纯色背景,别硬撑毛玻璃。QA 都救不了那种在 iOS 上稀碎的视觉效果。
最后,说个跟这篇八竿子打不着的。昨晚热得睡不着,我就盯着我家那只猫看。它打呼噜的时候,我脑子里突然冒出一个念头:你说这猫打呼噜的动静,是不是也算一种免训练的 Token 级别的个性化输出?就像那个叫 SteerWrite 的框架似的,不用梯度更新,全靠天生那股子劲儿。扯远了,反正——AI 想学我钻牛角尖?下辈子吧。嘿嘿,下次见。
