
本文详解如何使用 CSS @property 自定义属性配合 transition,让粘性导航栏在滚动时平滑地在纯色与径向渐变之间过渡,彻底解决“上滑回弹”时颜色突变的问题。
本文详解如何使用 css `@property` 自定义属性配合 `transition`,让粘性导航栏在滚动时平滑地在纯色与径向渐变之间过渡,彻底解决“上滑回弹”时颜色突变的问题。
在构建现代响应式网站时,粘性导航栏(sticky navbar)的视觉动效至关重要。许多开发者遇到一个常见问题:当页面向下滚动时,导航栏能通过 classList.add("scrolled") 平滑地从纯黑背景过渡为带透明度的径向渐变;但一旦向上滚动、触发 classList.remove("scrolled"),背景却“啪”地一下硬切回黑色——缺乏反向过渡动画,破坏了用户体验的连贯性。
根本原因在于:CSS 原生不支持对渐变(background: radial-gradient(...))中的颜色值或长度单位(如百分比)做直接过渡。传统写法中 .navbar { background: black; } 和 .navbar.scrolled { background: radial-gradient(...); } 是两个完全不同的背景声明,浏览器无法插值计算中间状态,因此移除 class 时过渡失效。
✅ 正确解法是引入 CSS 自定义属性(CSS Properties) + @property 规则,将渐变中可变的参数(颜色 --c 和位置百分比 --p)声明为可动画的受控变量:
@property --p {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --c {
syntax: "<color>";
inherits: false;
initial-value: black;
}
.navbar {
--p: 100%;
--c: black;
position: sticky;
top: 21px;
width: 100%;
/* 关键:用 var() 动态构建渐变,使 transition 生效 */
background: radial-gradient(circle, var(--c) var(--p), transparent);
transition: --p 0.5s ease, --c 0.5s ease; /* 同时过渡两个自定义属性 */
z-index: 1050;
}
.navbar.scrolled {
--p: 70%;
--c: rgba(0, 0, 0, 0.7);
}</color></percentage>
配合原有 JavaScript 逻辑(无需修改),即可实现双向平滑过渡:
window.addEventListener("scroll", () => {
const navbar = document.querySelector(".navbar");
if (window.pageYOffset > 21) {
navbar.classList.add("scrolled");
} else {
navbar.classList.remove("scrolled");
}
});
⚠️ 注意事项:
-
@property目前 不支持 Firefox(截至 2024 年),生产环境需添加降级方案(如仅对 Chrome/Edge/Safari 启用该动效,Firefox 回退为基础淡入淡出或保持静态); - 确保
transition属性明确指定要过渡的自定义属性名(如--p,--c),不可写作all或background; -
radial-gradient中transparent必须显式书写,避免浏览器解析歧义; - 若需兼容更广浏览器,可改用
background-color: rgba()+backdrop-filter: blur()模拟半透效果,但无法实现真正的径向渐变形态。
总结:通过 @property 将渐变参数“变量化”,再利用 CSS 自定义属性的可过渡特性,我们绕过了 CSS 渐变不可动画的限制,实现了真正意义上的双向、流畅、声明式滚动动效。这不仅是 navbar 的优化技巧,更是现代 CSS 动画思维的关键实践。










