
本文详解如何使用 CSS @property 和自定义动画,为 HTML 页面中多个不同目标值的数字计数器(如年份、项目数、员工数等)创建平滑、独立的递增动画效果。
本文详解如何使用 css `@property` 和自定义动画,为 html 页面中多个不同目标值的数字计数器(如年份、项目数、员工数等)创建平滑、独立的递增动画效果。
在现代 CSS 中,借助 @property(CSS 自定义属性类型注册)与 counter() 函数,我们可以实现无需 JavaScript 的纯 CSS 数字计数动画。但一个常见误区是试图复用同一 @keyframes 名称并覆盖其 to 值——这不仅无效,还会因重复定义导致浏览器仅应用最后一个规则,使所有计数器最终显示相同数值。
✅ 正确实现原理
核心在于两点:
-
每个计数器必须绑定唯一命名的
@keyframes动画(如counter-years、counter-projects),因为 CSS 不允许同名动画多次声明; -
通过
--animation自定义属性动态指定动画名称,结合animation: var(--animation)实现样式解耦与复用。
同时,@property --num 注册确保 --num 被识别为 <integer></integer> 类型,支持 counter-reset 正确解析,避免小数或字符串异常。
? 完整可运行代码示例
/* 必需:注册自定义属性类型 */
@property --num {
syntax: '<integer>';
initial-value: 0;
inherits: false;
}
/* 统一基础样式:所有计数器共享 */
div span {
counter-reset: num var(--num);
font: 800 40px system-ui;
padding: 2rem;
animation: var(--animation) 5s forwards ease-in-out;
}
/* 共享伪元素内容:自动添加 '+' 符号 */
div span::after {
content: counter(num) '+';
}
/* 独立动画定义 —— 每个目标值对应专属 keyframes */
@keyframes counter-years {
from { --num: 0; }
to { --num: 20; }
}
@keyframes counter-projects {
from { --num: 0; }
to { --num: 55; }
}
@keyframes counter-employees {
from { --num: 0; }
to { --num: 10; }
}
@keyframes counter-customers {
from { --num: 0; }
to { --num: 115; }
}<section style="display: flex; justify-content: space-around; align-items: center; height: 100vh; margin: 0; padding: 1rem;">
<div class="single-counter">
<div class="counter-contents">
<h2><span class="years-number" style="--animation: counter-years;"></span></h2>
<h3>Years of Experience</h3>
</div>
</div>
<div class="single-counter">
<div class="counter-contents">
<h2><span class="project-number" style="--animation: counter-projects;"></span></h2>
<h3>Complete Projects</h3>
</div>
</div>
<div class="single-counter">
<div class="counter-contents">
<h2><span class="employee-number" style="--animation: counter-employees;"></span></h2>
<h3>Employees</h3>
</div>
</div>
<div class="single-counter">
<div class="counter-contents">
<h2><span class="customers-number" style="--animation: counter-customers;"></span></h2>
<h3>Customers</h3>
</div>
</div>
</section>⚠️ 注意事项与最佳实践
-
浏览器兼容性:
@property目前仅支持 Chrome 102+、Edge 102+、Safari 16.4+(Firefox 尚未支持)。生产环境建议添加渐进增强方案(如 JS 回退)。 -
性能优化:避免在大量元素上同时触发长时动画;可结合
intersection-observer实现“进入视口后启动动画”。 -
可维护性提升:将
--animation值提取为 CSS 类(如.counter-years { --animation: counter-years; }),比内联样式更利于复用与主题管理。 -
数字格式化:若需千位分隔符(如
1,115),纯 CSS 无法实现,需配合Intl.NumberFormat的 JS 初始化逻辑。
通过以上结构化设计,你不仅能精准控制每个计数器的起止值与动画节奏,还能保持样式高度模块化与可扩展性——真正实现“一处定义,多处复用”的现代 CSS 工程实践。
立即学习“前端免费学习笔记(深入)”;


















