最可靠方案是用伪元素模拟:body::before { position: fixed; background-image: url('bg.jpg'); z-index: -1; pointer-events: none; },因background-attachment: fixed在Safari iOS等环境不支持且性能差。

背景图片固定不动,核心是用 background-attachment: fixed,但它在现代浏览器(尤其是移动端和 Safari)中存在兼容性与性能问题,不能无脑套用。
background-attachment: fixed 的基本写法
这是最直接的实现方式,让背景图随视口滚动而“静止”,产生视差效果:
body {
background-image: url('bg.jpg');
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
background-attachment: fixed;
}
注意:background-attachment: fixed 只对 body 或设置了 overflow: hidden 的容器生效时才稳定;在普通滚动容器里可能被忽略。
- 必须配合
background-position和background-size才能保证居中与缩放合理 - 若父容器有
transform(如translateZ(0))、perspective或will-change,某些 Chrome 版本会强制禁用fixed - Safari 在 iOS 上完全不支持
background-attachment: fixed(包括body和任何元素)
移动端失效?用伪元素模拟 fixed 效果
当 background-attachment: fixed 在 iOS 或安卓 WebView 中彻底失效时,主流解法是用 ::before 伪元素 + position: fixed:
立即学习“前端免费学习笔记(深入)”;
body {
margin: 0;
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('bg.jpg');
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
z-index: -1;
pointer-events: none;
}
关键点:
-
z-index: -1确保内容层在图片之上 -
pointer-events: none防止伪元素拦截点击事件 - 必须给
body清除默认margin,否则 fixed 元素可能错位 - 如果页面有横向滚动,需加
background-attachment: local或监听scroll动态修正位置(较重)
为什么不用 background-attachment: local?
background-attachment: local 表示背景图随元素内容滚动而滚动——这和“固定不动”完全相反,容易混淆:
-
scroll:背景图随容器滚动(默认值) -
fixed:背景图相对于视口固定(目标效果,但兼容差) -
local:背景图随容器内可滚动内容一起动(比如div内部有 overflow,背景会跟着文字滚)
所以想“不动”,就别选 local;它只在极少数需要背景随局部内容滑动的场景才有用,比如带滚动条的卡片背景。
性能与可访问性提醒
用 fixed 或伪元素做背景图,都可能触发频繁重绘,尤其在低端 Android 设备上卡顿明显:
- 避免大图(建议 ≤ 800KB,尺寸不超过 2000×1200)
- 慎用
background-blend-mode或多层fixed背景叠加 - 屏幕阅读器不会读取背景图,重要信息不能仅靠背景图传达
- 深色模式下,若背景图含大量黑/白区域,记得用
@media (prefers-color-scheme: dark)微调亮度或替换图
真正稳定的“固定背景”,现在基本等于“用伪元素 + fixed 定位 + 严格控制尺寸和交互”,background-attachment: fixed 更像是一个渐进增强的彩蛋,而不是可靠方案。











