现代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)效果预览:

相关推荐
光影少年5 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_6 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu10830189118 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾10 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu12 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym16 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫18 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫21 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat23 分钟前
前端性能优化2
前端
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js