前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS custom property transition animation
CSS层叠与选择器

自定义属性能做过渡动画吗?需要什么条件?

普通的自定义属性对浏览器来说就是一段字符串,没法计算中间值,过渡时只能在 50% 处直接跳变。用 @property 注册属性、指定 syntax(比如 <color> 或 <length>)之后,浏览器知道值的类型了,就能做平滑插值。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#层叠与选择器#动画
先看核心答案读代码示例
理解线索

自定义属性动画的前提

  1. 未注册浏览器当字符串处理,过渡时 50% 处跳变
  2. 注册后@property 指定类型,浏览器能算中间值,平滑过渡
  3. 三个描述符syntax、inherits、initial-value 缺一不可

@property 不只是为了动画。注册之后初始值也会从「保证无效值」变成你指定的值,继承行为也可以控制。

核心回答

先记住这个答案

普通的自定义属性在浏览器眼里就是一段字符串。你写 transition: --color 0.3s,浏览器不知道 --color 是颜色还是长度还是别的什么,没法算中间值,所以过渡到一半直接跳变。想要平滑过渡,必须用 @property 把这个属性注册一下,告诉浏览器它的类型。注册之后浏览器知道怎么插值了,比如 <color> 类型会在两个颜色之间做渐变计算,<length> 会在两个数值之间做线性插值。

  • 未注册的自定义属性是字符串,过渡时直接跳变
  • @property 注册后指定类型,浏览器才能计算中间值
  • 注册属性要声明语法、继承和初值
  • 注册后可以给渐变背景、阴影等不能直接过渡的属性加动画

未注册时过渡是怎样的

没有注册的自定义属性,过渡效果其实就是一个延迟的跳变。在过渡时间走到 50% 之前保持旧值,50% 的瞬间切到新值。因为浏览器完全不知道 red 到 blue 之间应该经过什么中间值,它没法做任何插值计算。

未注册的属性直接跳变CSS
.box {
  --bg: red;
  background: var(--bg);
  transition: --bg 0.5s;
}
.box:hover {
  --bg: blue;
}

鼠标移上去的时候,背景不会从红色平滑过渡到蓝色,而是在 0.25 秒处突然变成蓝色。这和 visibility 的过渡行为类似,都是离散型跳变。 很多人写完这段代码看到没有动画效果,就以为自定义属性不支持 transition。其实不是不支持,是浏览器缺少类型信息。

用 @property 注册后就能平滑过渡

@property 是 CSS Houdini 的一部分,用来注册自定义属性并声明它的类型。注册需要三个描述符:syntax 说明值的类型,inherits 说明是否继承,initial-value 给出初始值。三个缺一不可,少写任何一个都会导致注册无效。

注册后的平滑过渡CSS
@property --bg {
  syntax: '<color>';
  inherits: false;
  initial-value: red;
}

.box {
  --bg: red;
  background: var(--bg);
  transition: --bg 0.5s;
}
.box:hover {
  --bg: blue;
}

加了 @property 声明之后,浏览器知道 --bg 是颜色类型了,鼠标移上去的时候背景会从红色平滑过渡到蓝色,经过紫色的中间态。 注册的效果是全局的,一个 @property 声明会影响整个文档里所有用到这个属性名的地方。不需要在每个选择器里重复注册。

借助注册属性给渐变加动画

自定义属性过渡最实用的场景是给渐变背景加动画。background: linear-gradient(...) 本身是不支持 transition 的,因为浏览器不知道怎么在两个渐变之间插值。但如果渐变里用了注册过的自定义属性,属性值可以过渡,渐变就会跟着动起来。

渐变色的平滑变化CSS
@property --start {
  syntax: '<color>';
  inherits: false;
  initial-value: #ff6b6b;
}

.card {
  --start: #ff6b6b;
  background: linear-gradient(135deg, var(--start), #4ecdc4);
  transition: --start 0.6s;
}
.card:hover {
  --start: #a855f7;
}

鼠标移到卡片上时,渐变的起始色从红色平滑过渡到紫色,终止色保持不变。以前实现这个效果需要用两个伪元素叠在一起做 opacity 动画,现在用 @property 几行就够了。 同样的思路可以用在圆锥渐变做的饼图、径向渐变做的光晕效果上。只要把想要动画的那个值抽成注册过的自定义属性,就能用 transition 或 @keyframes 驱动它变化。

syntax 支持哪些类型

syntax 的值是一个字符串,描述属性接受什么类型。常用的有 <color>(颜色)、<length>(长度,比如 px、rem)、<number>(纯数字)、<percentage>(百分比)、<angle>(角度)、<length-percentage>(长度或百分比)。

你也可以用 | 组合多个类型,比如 '<length> | <percentage>'。如果设成 '*',等于没有类型限制,和不注册一样没法过渡。

设了 syntax 之后,赋给属性的值会被类型检查。如果写了不合规的值(比如给 <color> 类型赋了 10px),这条声明不会生效,属性保留之前的值或回退到 initial-value。

回答前,多想一步

容易答错的地方

以为 transition 写了就会过渡
不注册的自定义属性写 transition 不会报错,但不会有平滑效果。浏览器只是在 50% 处做了一次离散跳变。必须用 @property 注册并指定类型才能真正插值。
漏了 initial-value
@property 的三个描述符必须全部写。漏了 initial-value 整个注册无效,浏览器会忽略这条 @property,属性回到未注册状态,过渡又变成跳变。
试着用自己的话回答

面试官还会怎么问?

除了 CSS 的 @property,还有别的注册方式吗?

JavaScript 里可以用 CSS.registerProperty() 达到同样的效果。参数是一个对象,包含 name、syntax、inherits、initialValue。好处是可以动态注册,坏处是注册后不能修改或取消,页面生命周期内持续有效。

@keyframes 动画里自定义属性也需要注册吗?

需要。@keyframes 和 transition 一样,都依赖浏览器做值的插值计算。未注册的自定义属性在关键帧之间也是离散跳变,注册之后才能平滑过渡。

@property 的浏览器兼容性怎么样?

Chrome 85+、Edge 85+、Safari 15.4+、Firefox 128+ 都支持。如果要兼容不支持的浏览器,可以写一个不依赖 @property 的回退样式,让动画降级为跳变,功能不受影响,只是没有平滑效果。

从一道题,走向一组知识

把知识连起来

层叠与选择器

var(--x) 的值不是合法颜色,color 最终会是什么?

注册后的自定义属性有明确的类型检查,赋了不合规的值会走「计算值时无效」的回退,和未注册时行为不同。

层叠与选择器

CSS 自定义属性怎么做到只在某个组件内生效?

@property 注册是全局的,不受组件作用域限制,做组件级变量时需要注意命名冲突。

参考资料

  • CSS:层叠与选择器参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 未注册时过渡是怎样的
  3. 用 @property 注册后就能平滑过渡
  4. 借助注册属性给渐变加动画
  5. syntax 支持哪些类型
  6. 容易答错的地方
  7. 面试官还会怎么问
  8. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑