Safari新版本中mix-blend-mode:difference渲染异常问题求助
问题:Safari 17+中mix-blend-mode: difference在opacity过渡后失效
我开发的网站有一个屏保效果:闲置4秒后将#bg元素的opacity设为1,该元素使用了mix-blend-mode: difference。
相关代码
CSS
#bg{ background-image: repeating-linear-gradient(black 10px, gray 16px, white 20px, black 17px); pointer-events: none; mix-blend-mode: difference; width: 100%; position: fixed; height: 100vh; z-index: 10; opacity: 1; transition: opacity 1s ease-in-out; transform: translate3d(0,0,0); }
JavaScript
function startTimer() { clearTimeout(timeoutId); timeoutId = setTimeout(() => { (x = 1); document.getElementById("bg").style.transition = "opacity 1s ease-in-out" document.getElementById("bg").style.opacity = (x) }, 4000); }
问题现象
- Safari 16.1版本效果正常;
- Safari 17及以上版本:页面加载时混合模式生效,但闲置后元素显示为纯色(开发者工具仍显示
mix-blend-mode: difference); - 在开发者工具中修改该属性再改回后效果恢复正常;
- 若将混合模式改为
multiply则全程正常; - 已尝试设置白色背景、
translate3d修复,均无效。
可行替代方案
1. 强制触发元素重绘
在设置opacity后,通过修改元素的transform属性触发重绘,强制Safari重新计算混合模式:
function startTimer() { clearTimeout(timeoutId); timeoutId = setTimeout(() => { const bgEl = document.getElementById("bg"); bgEl.style.opacity = 1; // 触发重绘 bgEl.style.transform = "translate3d(0, 0, 0.1px)"; // 立即还原transform,避免视觉影响 setTimeout(() => { bgEl.style.transform = "translate3d(0, 0, 0)"; }, 0); }, 4000); }
2. 改用伪元素实现过渡
将opacity过渡放在伪元素上,让混合模式始终作用在父元素上,避免过渡导致的渲染异常:
#bg{ background-image: repeating-linear-gradient(black 10px, gray 16px, white 20px, black 17px); pointer-events: none; mix-blend-mode: difference; width: 100%; position: fixed; height: 100vh; z-index: 10; transform: translate3d(0,0,0); } #bg::after { content: ""; position: absolute; inset: 0; background: #fff; /* 需与页面实际背景色一致 */ opacity: 0; transition: opacity 1s ease-in-out; }
function startTimer() { clearTimeout(timeoutId); timeoutId = setTimeout(() => { document.getElementById("bg").querySelector("::after").style.opacity = 1; }, 4000); }
3. 纯CSS实现交互控制
用CSS的:hover/:focus-within结合过渡延迟替代JS,完全避免JS操作样式带来的渲染问题:
#bg{ background-image: repeating-linear-gradient(black 10px, gray 16px, white 20px, black 17px); pointer-events: none; mix-blend-mode: difference; width: 100%; position: fixed; height: 100vh; z-index: 10; opacity: 0; transition: opacity 1s ease-in-out; transform: translate3d(0,0,0); } /* 页面无交互4秒后显示 */ body:not(:hover):not(:focus-within) #bg { opacity: 1; transition-delay: 4s; } /* 有交互时立即隐藏 */ body:hover #bg, body:focus-within #bg { opacity: 0; transition-delay: 0s; }
关于问题修复
这是Safari 17+的WebKit渲染引擎bug,你可以通过WebKit官方Bugzilla提交bug报告并附上复现案例。WebKit团队通常会关注这类渲染一致性问题,后续版本有修复的可能,但具体时间无法确定。
内容的提问来源于stack exchange,提问作者Einar Zotterman
相关产品推荐
相关产品推荐

