
本文介绍如何使用 CSS @property 和自定义动画,为网页中多个不同目标值的数字计数器(如年份、项目数、员工数等)分别创建平滑、独立的递增动画,避免动画覆盖与逻辑冲突。
本文介绍如何使用 css `@property` 和自定义动画,为网页中多个不同目标值的数字计数器(如年份、项目数、员工数等)分别创建平滑、独立的递增动画,避免动画覆盖与逻辑冲突。
在现代 CSS 中,利用 @property 声明类型化自定义属性(如 ),配合 counter() 函数与 @keyframes,可实现纯 CSS 驱动的整数计数动画——无需 JavaScript。但一个常见误区是:重复定义同名 @keyframes counter 规则,这在 CSS 中是非法的(后定义会覆盖前定义),导致所有计数器最终都按最后一个 to 值(如 115)运行,失去独立性。
✅ 正确解法是:为每个计数器创建唯一命名的动画(如 counter-years、counter-projects),并通过 --animation 自定义属性动态绑定。同时复用基础样式,提升可维护性。
以下是优化后的完整实现:
/* 必需:声明受控的整数型自定义属性 */
@property --num {
syntax: '<integer>';
initial-value: 0;
inherits: false;
}
/* 统一基础样式:所有计数器 span 共享 */
div span {
counter-reset: num var(--num);
font: 800 40px system-ui;
padding: 2rem;
display: inline-block;
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; }
}</integer>
HTML 结构精简清晰,通过内联 style="--animation: ..." 显式指定每个 应用的动画:
<section style="display: flex; justify-content: space-around; align-items: center; height: 100vh; margin: 0; padding: 2rem;"><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 103+、Edge 103+、Safari 16.4+,Firefox 尚未支持(需降级方案或 JS 回退); - 动画时长(
5s)和缓动函数(ease-in-out)可全局调整,不影响各计数器独立性; - 若需响应式适配,建议将
font-size改为rem或clamp(),避免固定40px在小屏上溢出; - 所有
span元素默认为inline,添加display: inline-block可确保padding生效且布局稳定。
? 进阶提示: 如需“滚动触发动画”(即用户滚动到区域时才开始计数),可结合 IntersectionObserver + element.animate() 实现更精准控制,但本方案聚焦于纯 CSS 解决核心多计数器冲突问题。
此方案结构清晰、语义明确、易于扩展——只需新增一组 @keyframes 和对应 --animation 值,即可快速接入第五、第六……任意数量的独立计数器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











