纯 CSS 实现秒表:零 JavaScript 的计时器

二月 01, 2025 / Mr.x / 4阅读 / 0评论/ 分类: 创意
纯 CSS 秒表实现详解 | xgr.cab

利用 CSS @property 和 counter-reset 打造无需脚本的精密计时器

Live Demo
0
0
:
0
0
.
0
0

实现原理

这个秒表的核心魔法在于 CSS 的 @property 规则。它允许我们定义自定义属性,并指定其语法、继承性和初始值。结合 counter-resetanimation,我们可以在不借助 JavaScript 的情况下实现精确的时间计数。

💡 关键技术点

@property 是 CSS Houdini API 的一部分,它让我们能够像定义原生 CSS 属性一样定义自定义属性,包括指定数据类型(如 <integer>),这使得动画插值成为可能。

1. 定义计数器属性

首先,我们需要为每个时间位(分、秒、毫秒)定义可动画的整数属性:

CSS
@property --ms-tens {
    initial-value: 0;
    inherits: false;
    syntax: '<integer>';
}

@property --ms-singles {
    initial-value: 0;
    inherits: false;
    syntax: '<integer>';
}

2. 创建计数动画

使用 @keyframes 定义每个数字从 0 到最大值的变化:

CSS
@keyframes ms-singles {
    to { --ms-singles: 10; }
}

@keyframes s-singles {
    to { --s-singles: 10; }
}

3. 配置数字显示

每个数字元素使用 counter-reset 将自定义属性值转换为计数器,然后通过 ::after 伪元素的 content 属性显示:

CSS
.digit {
    position: relative;
    color: transparent;
    counter-reset: var(--counter-name) var(--counter-variable);
    animation: var(--name, none) var(--duration, 1s) 
               infinite steps(var(--steps)) var(--state);
}

.digit:after {
    content: counter(var(--counter-name));
    font-variant: tabular-nums;
    color: var(--digit);
    position: absolute;
    bottom: 0;
    right: 0;
}

时间精度控制

每个时间位有不同的动画周期,通过精确计算实现正确的时间流逝:

时间位 动画周期 步数 说明
毫秒个位0.1s10每 100ms 变化一次
毫秒十位1s10每秒变化一次
秒个位10s10每 10 秒循环
秒十位60s6每 60 秒循环
分钟个位600s10每 10 分钟循环
分钟十位3600s6每 60 分钟循环

状态控制机制

使用隐藏的 checkbox 和 CSS 兄弟选择器实现开始/暂停/重置功能:

CSS
/* 开始状态 */
#start:checked ~ .stopwatch__content {
    --state: running;
}

/* 暂停状态 */
#pause:checked ~ .stopwatch__content {
    --state: paused;
}

浏览器兼容性

@property 规则目前已被所有现代浏览器支持(Chrome 85+、Firefox 128+、Safari 16.4+)。对于旧版浏览器,可以提供一个静态回退方案。

总结

通过 @propertycounter-resetanimation 的组合,我们实现了一个完全不需要 JavaScript 的秒表。这种技术展示了 CSS 的强大能力,也为那些追求极致性能或需要在禁用 JavaScript 环境下工作的场景提供了解决方案。

#纯 CSS 实现秒表:零 JavaScript 的计时器(1)

评论