现代CSS:纯 CSS 实现倒计时效果

在日常开发中,实现倒计时功能最先想到的是使用 JavaScript 定时器,随着 CSS 的发展,现代 CSS 被越来越多的浏览器所支持,本文将探索使用现代 CSS 的特性,实现倒计时效果。

1.核心知识点

实现倒计时的核心是通过 CSS Animation 实现伪元素的内容变化。用到的核心知识点包括 CSS @property 和 CSS Counter。

1.1.CSS @property

引用 MDN 的定义:

@property CSS at-rule 是 CSS Houdini API 的一部分,它允许开发者显式地定义他们的CSS 自定义属性, 允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。

@property 规则提供了一个直接在样式表中注册自定义属性的方式,而无需运行任何 JS 代码。有效的 @property 规则会注册一个自定义属性,就像 CSS.registerProperty (en-US) 函数被使用同样的参数调用了一样。

基础语法:

css 复制代码
@property --property-name {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0ffee;
}

浏览器兼容性:

1.2.CSS Counter

基本介绍:

  1. counter-reset: counter-name start-value

主要用于创建或复位计数器。

  • counter-name:计数器的唯一标识符。
  • start-value:可选项,标识计数器的初始值。如果未指定,默认值为 0。
  1. counter-increment: counter-name increment-value

主要用于增加或减少计数器的值

  • counter-name:要递增的计数器的标识符。
  • increment-value:要递增计数器的值。这是可选项,如果未指定,默认值为 1。
  1. content: counter(counter-name, style)

要显示计数器的当前值,我们可以将 content 属性与 ::before 或 ::after 伪元素结合使用。content 属性使用以下语法显示计数器:

  • counter-name:要显示的计数器的标识符。
  • style:显示计数器值的样式。这是可选项,如果未指定,默认为十进制。

浏览器兼容性:

2.具体实现

2.1.实现页面框架

通过 html:5div.countdown>svg.circle>(circle.circle-01[r=45]+circle.circle-02[r=45]) 快速创建页面及容器。在示例中除了实现倒计时的走秒效果,还通过增加 svg 元素来实现圆环进度效果,整体体验会更好。

html 复制代码
<div class="countdown">
  <svg viewBox="-50 -50 100 100" stroke-width="10" class="circle">
    <circle r="45" class="circle-01"></circle>
    <circle r="45" class="circle-02" pathLength="1"></circle>
  </svg>
</div>

2.2.增加基础样式

通过给 svg 增加 strokestroke-lineupstroke-dasharray 等样式来实现圆环效果,通过增加伪元素 ::after 作为时间容器来显示倒计时。基础样式如下:

css 复制代码
body {
  display: grid;
  place-items: center;
  height: 100vh;
  background-color: #282c34;
}

.countdown {
  display: grid;
  width: 20em;
  height: 20em;
  .circle {
    grid-column: 1;
    grid-row: 1;

    .circle-01 {
      fill: none;
      stroke: #fff;
    }

    .circle-02 {
      --t: 2;
      --k: calc(var(--t)/20);
      fill: none;
      transform: rotate(-90deg);
      stroke-linecap: round;
      stroke: color-mix(in hsl shorter hue, #8a9b0f calc(var(--k)*100%), #940a3d);
      stroke-dasharray: var(--k) 1;
    }
  }
  &::after {
    grid-column: 1;
    grid-row: 1;
    place-self: center;
    font-size: 5em;
    color: #fff;
    content: "00:19";
  }
}

初始效果如下:

2.3.增加动画

通过基础示例我们可以看到,要想实现倒计时效果,::after 元素的 content 属性值需要和 --t 变量关联上。

1)CSS Counter:

通过 CSS Counter 实现秒数打印,注意我们通过给 counter 增加 decimal-leading-zero 了以实现前导 0显示。

css 复制代码
&::after {
  --s: calc(var(--t)/1);
  counter-reset: s var(--s);
  content: "00:" counter(s, decimal-leading-zero);
}

2)CSS @property:

通过 CSS property 来实现属性动画。

css 复制代码
@property --t {
  syntax: "<number>";
  initial-value: 10;
  inherits: true;
}
@property --s {
  syntax: "<integer>";
  initial-value: 0;
  inherits: true;
}

3)增加动画:

css 复制代码
.countdown {
  animation: linear 10s linear infinite;

  .circle {
    .circle-02 {
      --k: calc(var(--t)/10);
      stroke: color-mix(in hsl shorter hue, #8a9b0f calc(var(--k)*100%), #940a3d);
      stroke-dasharray: var(--k) 1;
    }
  }
}
@keyframes linear {
  to {
    --t: 0;
  }
}

4)效果预览:

相关推荐
_AaronWong8 分钟前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
cxxcode9 分钟前
I/O 多路复用:从浏览器到 Linux 内核
前端
用户54330814419417 分钟前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo21 分钟前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
恋猫de小郭1 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木1 小时前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮1 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati1 小时前
Vue3 父子组件通信完全指南
前端·面试
是一碗螺丝粉1 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain
wuhen_n1 小时前
双端 Diff 算法详解
前端·javascript·vue.js