CSS自定义属性动画动不了?这个@property注册坑我踩了三次才摸清楚
我第一次用 –progress 做进度条动画的时候,transition 写了,hover 也加了,结果就是不动。F12 打开一看,属性值明明变了,但画面就是卡在那里。后来才知道,问题出在我没给这个自定义属性「注册类型」。
普通的自定义属性为什么做不了动画
CSS 自定义属性(CSS Variables)你肯定用过:
:root {
--progress: 0;
}
.bar {
width: var(--progress);
transition: width 0.5s ease;
}
.bar:hover {
--progress: 80%;
}
这个写法的 –progress 本质上是一个字符串,浏览器不知道它是数字、百分比还是颜色。遇到 transition 的时候,浏览器会走另一个分支——直接跳到终值,没有过渡。所以你的进度条会「啪」一下变过去,而不是顺滑地走过去。
@property 是什么
@property 是 CSS Houdini API 的一部分,允许你给自定义属性「注册」一个明确的类型。注册完之后,浏览器才知道这个属性是可以做插值计算的,从而触发 transition 和 animation。
基本写法就三行:
@property --progress {
syntax: "<percentage>";
inherits: false;
initial-value: 0%;
}
- syntax:定义值的类型,支持
<length>、<number>、<color>、<percentage>、<angle>、<time>等 - inherits:是否向下继承,动画场景通常 false
- initial-value:默认值,必须和 syntax 匹配
注册完再写同样的 transition,效果就完全不一样了。
三个我踩过的坑
坑一:syntax 写错了,整个注册无效
/* 错误:颜色要用 <color>,不是引号包裹的字符串 */
@property --bg {
syntax: "#c0ffee"; /* ❌ */
inherits: false;
initial-value: #c0ffee;
}
/* 正确:类型标识符写在引号外面 */
@property --bg {
syntax: "<color>"; /* ✅ */
inherits: false;
initial-value: #c0ffee;
}
syntax 里引号包裹的是类型标识符,不是值本身。写错类型浏览器直接忽略整条 @property。
坑二:initial-value 和 syntax 不匹配
/* 错误:syntax 写的是 <number>,initial-value 给的是长度值 */
@property --scale {
syntax: "<number>";
inherits: false;
initial-value: 1.5rem; /* ❌ 不匹配 */
}
/* 正确:数字就写纯数字 */
@property --scale {
syntax: "<number>";
inherits: false;
initial-value: 1.5; /* ✅ */
}
Chrome DevTools 里这条属性会显示为 invalid,失去动画能力。
坑三:在 @keyframes 里改 registered 属性不生效
@property 注册的属性不能在 @keyframes 里直接插值。要做关键帧动画,得用 transition 配合状态变化,或者用 CSS Animation 但属性值得是 registered 的。
/* 这个不生效 */
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@keyframes spin {
to { --angle: 360deg; } /* ❌ 关键帧里改 registered 属性 */
}
/* 这个可以 */
.rotate {
animation: spin 2s linear infinite;
/* 需要配合实际的 transform 属性 */
}
渐变色做动画也是同样道理——你注册了 –gradient-angle,transition 渐变角度是可以动的,但要完整过渡两个渐变值本身,还是有限制。
什么场景用最划算
@property 最适合这几类场景:
- 进度条/加载动画:数字类型注册后直接 transition,平滑且零 JS
- 颜色主题切换:注册 –accent-color,hover 切换时整个网站颜色渐变过渡
- 角度/旋转动画:注册 <angle> 类型,做三角形旋转、光晕效果
- 复杂数值动画:注册 <transform-function>,做 3D 卡片倾斜跟随鼠标
一个完整例子——渐变色主题切换:
@property --hue {
syntax: "<number>";
inherits: false;
initial-value: 220;
}
.card {
background: hsl(var(--hue), 80%, 60%);
transition: --hue 0.6s ease;
}
.card:hover {
--hue: 340;
}
鼠标放上去,背景色就会从蓝紫色平滑过渡到红紫色,完全不用 JS。
兼容性:现在能用了
@property 从 July 2024 开始进入 Baseline,Chrome、Edge、Firefox、Safari 全支持。生产环境直接用,不用加前缀。
如果你的项目还要兼容更老的浏览器,可以用 JS 注册的方式做降级:
if ("registerProperty" in CSS) {
CSS.registerProperty({
name: "--progress",
syntax: "<percentage>",
inherits: false,
initialValue: "0%"
});
}
总结
CSS 自定义属性动画动不了,根源是浏览器不知道这个属性的「类型」,无法做插值。@property 就是用来解决这个问题的——用三行注册代码,告诉浏览器这是数字、颜色还是角度,之后 transition 和 animation 就正常工作了。
三个最容易踩的坑:syntax 类型标识符别写错、initial-value 必须和 syntax 匹配、@keyframes 里不能改 registered 属性的值。
下次写 –xxx 配 transition 发现不动的时候,先检查有没有给这个属性注册类型。
评论区
登录后可评论。