滚动背景色变化本质是背景位置偏移而非修改background-color,通过渐变背景图+background-attachment:fixed或动态background-position模拟;纯css无法读取滚动值,依赖fixed锚定或scroll-driven动画实现。

滚动时背景色变化的本质是背景位置偏移
不是真的在改 background-color,而是用渐变背景图 + background-attachment: fixed 或动态 background-position 模拟“随滚动变色”。真正生效的是背景图像的可视区域切换,人眼感知为颜色过渡。
关键限制:纯 CSS 无法读取滚动值,所以必须依赖 background-attachment: fixed 的视口锚定行为,或配合 scroll-margin/scroll-snap 做分段触发。
用 fixed 背景 + 线性渐变实现平滑变色
这是最轻量、兼容性最好的方案。把整个页面(或某容器)的背景设为垂直渐变,再固定它,滚动时露出不同色带:
body {
background: linear-gradient(to bottom,
#ff9a9e, #fad0c4, #a1c4fd, #c2e9fb, #e0c3fc);
background-attachment: fixed;
background-size: 100% 500vh; /* 拉伸渐变高度,避免重复 */
margin: 0;
}
-
background-attachment: fixed让背景相对于视口不动,内容滚动时“划过”背景 -
background-size: 100% 500vh必须远大于视口高度,否则渐变会平铺重复,破坏连续感 - 渐变色点数量决定过渡段数,建议 4–6 个色值,太多易糊,太少显生硬
- 不支持 Safari 旧版本对
background-attachment: fixed在body上的渲染(可改用包裹层<div class="bg-wrapper">)<h3>用 <code>background-position+scroll()函数做精确控制(CSS Scroll-driven Animations)Chrome 115+、Firefox 119+ 支持原生滚动驱动动画,能真正绑定滚动位置到背景定位:
@keyframes bgShift { from { background-position: 0 0; } to { background-position: 0 -200vh; } } .section { background: linear-gradient(to bottom, #3a7bd5, #00d2d3); animation: bgShift 1s linear forwards; animation-timeline: scroll(root auto); animation-range: entry 0% exit 100%; }-
animation-timeline: scroll(root auto)表示以页面滚动为时间轴 -
animation-range定义该元素进入/退出视口时动画起止,需搭配scroll-margin微调触发点 - 目前仅支持
background-position、opacity等少数属性,不能直接驱动background-color - 若要多段变色,得拆成多个
.section,每段配独立渐变和 range
别踩这些坑
实际写的时候最容易卡在这几个地方:
- 在
body上用background-attachment: fixed,Safari 可能失效 → 改用全屏<div class="fixed-bg"> 层并设 <code>position: fixed; top: 0; left: 0; z-index: -1; - 渐变方向写成
to right却横向滚动 → 确保滚动方向与渐变轴一致(垂直滚动配to bottom) - 没设
background-size,导致渐变被压缩成条纹 → 至少设100% 300vh起步 - 用
scroll()动画但没加scroll-margin-top: 1px,导致首屏不触发 → 所有参与animation-range的元素都应设scroll-margin
滚动变色看着炫,但核心就两条路:靠
fixed背景的视差错觉,或者靠新标准的scroll()时间线。前者稳,后者准,选哪个取决于你要支持的浏览器和控制精度。 -











