搜索

CSS 教学

基本介绍

认识 CSS 开始使用 CSS CSS 语法规则 CSS 命名原则 CSS 常用样式属性

CSS 选择器

认识 CSS 选择器 优先级 ( 权重 ) 样式继承与联集 使用巢状结构语法 元素选择器 ID 和 Class 选择器 属性选择器 文件结构选择器 虚拟类别选择器 ( 结构 ) 虚拟类别选择器 ( 类型 ) 虚拟类别选择器 ( 输入 ) 虚拟类别选择器 ( 行为 ) 虚拟类别选择器 ( 超链接 ) 虚拟类别选择器 ( 逻辑 ) 虚拟类别选择器 ( 其他 ) 虚拟元素选择器 群组与组合选择器

数值与单位

全域关键字与文字数值 长度与角度单位 位置名称与时间单位 特殊样式属性 ( all、appearance)

规则与定义

变数 ( Variables ) 媒体查询 ( @media ) 容器查询 ( @container ) 自订属性值 ( @property ) 导入样式 ( @import ) 分层优先级 ( @layer ) 选择器作用域 ( @scope ) 定义字型 ( @font-face ) 计数规则 ( @counter-style ) 打印网页 ( @page )

函数类型

数学计算 文字与清单计数 形状与线段 路径 ( path )

颜色与滤镜

颜色单位 色彩模型 相对颜色 渐层色 图像滤镜 ( filter ) 背景滤镜 ( backdrop-filter ) 混合模式 ( mix-blend-mode )

文字与段落

设定字型 ( font-family ) 使用外部字型 文字尺寸 文字样式 ( 常用 ) 文字样式 ( 其他实用 ) 文字样式 ( 特殊用途 ) 文字换行 文字空白与 Tab 大小 文字行高与缩排 文字水平与垂直对齐 文字书写方向 文字自动分栏 使用 Color Font ( 彩色字型 ) 使用 Icon Font ( 图示文字 ) 制作自己的 Icon Font 显示生成内容与引号

元素容器

容器显示类型 ( display ) 元素 display 对照表 盒子模型 ( Box Model ) 宽高尺寸 ( width、height ) 显示与比例 ( box-sizing、aspect-ratio ) 内边距 ( padding ) 外边界 ( margin ) 边框 ( border ) 边框圆角 ( border-radius ) 图像边框 ( border-image ) 轮廓 ( outline ) 内容溢出与裁切 ( overflow ) 内容范围 ( contain ) 可见性与透明度 缩放与调整 ( zoom、resize )

背景与阴影

背景 ( 背景色、背景裁切 ) 背景图 ( 定位、尺寸 ) 背景图 ( 固定、重复 ) 背景图 ( 多重背景、混合 ) 背景缩写 ( background ) 容器阴影 ( box-shadow )

清单与表格

清单样式 清单计数器 表格基本样式 表格边框重叠与间距 表格内容宽度与对齐

基本排版与定位

元素排版方式 浮动 ( float ) 浮动形状 ( shape-* ) 定位 ( position ) 逻辑属性 ( logical properties ) 重置 CSS ( Reset CSS ) 水平置中技巧 垂直置中技巧

Flex 弹性排版

Flexbox 弹性盒子 Flex 对齐方式 Flex 弹性伸缩

Grid 网格排版

Grid 网格容器与格线 Grid 网格空间与命名 Grid 网格流向与间距 Grid 排列网格项目 Grid 项目对齐与顺序

转场与动画

转场 ( transition ) 转场触发事件 动画 ( animation ) 自订动画路径 ( offset ) 动画触发事件 多重动画的权重与顺序 动画进度控制 ( timeline )

变形、裁切与遮罩

裁切路径 ( clip-path ) 图像遮罩 ( mask ) 对象填满方式与定位 转换函数 ( transform ) 平移、旋转与缩放 3D 转换与透视

视窗与用户行为

卷轴样式 ( scrollbar ) 拉霸、滑杆样式 ( slider ) 鼠标光标图示 ( cursor ) 鼠标事件 ( pointer-events ) 用户选取 ( user-select ) 卷动行为 ( scroll、overscroll ) 打印换页 ( break-* )

CSS 预处理器

认识 CSS 预处理器 Less ( 安装、开始使用 ) Less ( 巢状结构、选择器 ) Less ( 变数、import ) Less ( Extend、Mixin ) Less ( 逻辑、循环、函数 )

范例效果

CSS 多重绕圈 3D 动画 CSS 圆饼图 CSS 跑马灯 Google 加载动画 电子时钟数字 渐层色的转场与动画 渐层色制作星空背景 渐层色边框 渐层色制作图案背景 不规则形状动画 弹跳的正方形动画 3D 正多面体 超链接底线动画效果 恶心黏黏球效果 CSS 视差滚动效果 卷轴控制放射形选单 卷轴改变文字背景色 CSS 页面卷动进度条 CSS 水波效果 圆点加载动画 ( 阴影动画 ) 字母翻牌效果 探照灯动画 立体双色跑马灯 楼梯文字动态效果 渐层色文字、双色文字 流动色彩文字 空心文字、文字水波背景 左右倾斜的背景效果 Icon 图示形状变换 故障文字效果 按钮的多种 hover 效果 点击展开或收折的选单 点击爱心图案放射效果 纯 CSS 数字加载进度条 纯 CSS 码表 ( 可计时 )

纯 CSS 码表 ( 可计时 )

这篇教学会使用非常多的 CSS 进阶技巧,包含 CSS 变数、动画控制、结构选择器、虚拟类别选择器、自订属性、清单计数器...等,透过这些技巧的互相搭配组合,就能在不使用 JavaScript 的情况下,透过纯 CSS 制作出可以计时的码表。

快速导览:

CSS 教学 - 纯 CSS 码表 ( 可计时 )

制作可以暂停和继续的数字

使用“纯 CSS”制作“可以暂停和继续”的数字需要用到许多进阶技巧,暂停和继续的控制方式是依靠“CSS 变数”和“动画暂停与继续”,数字纪录的方式依靠“自订属性”和“计数器”,最后透过虚拟元素显示数值,详细说明可参考下方范例程序码注解。

参考:CSS 变数、CSS 动画 animation、counter-set 设定清单数值、CSS @property 自订属性值、虚拟元素选择器

线上展示:https://codepen.io/oxxo/pen/QwWPQwg

<!-- HTML 程式碼 -->
<div id="stopwatch">
  <span class="ms"></span>
</div>

<!-- CSS 程式碼 -->
<style>
  /* 自訂屬性 */
  @property --ms {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  #stopwatch {
    --state: paused;            /* 自訂變數 --state 預設值 paused */
    font-size: 100px;
  }

  #stopwatch:hover {
    --state: running;           /* hover 時改變變數 --state 為 running */
  }
  .ms {
    counter-reset: count-ms  var(--ms);  /* 設定計數器名稱 count-ms,數值為 --ms 數值 */
    animation:  oxxo-ms 1s steps(10) var(--state) infinite; /* 使用 steps 方式播放動畫 */
  }
  .ms::before {
    content: counter(count-ms); /* 虛擬元素顯示 count-ms 計數器數值 */
  }
  @-webkit-keyframes oxxo-ms {
    to {
      --ms: 10;                 /* 動畫結束點為數值為 10 的自訂屬性 --ms  */
    }
  }
</style>

CSS 教学 - 纯 CSS 码表 ( 可计时 ) - 制作可以暂停和继续的数字

延伸上述程序码,将其改成使用 input 的 checkbox 元素,并将负责暂停和继续的变数移动到 checked 状态的选择器里,就能做到点击开始,再点一下就暂停的效果。

参考:“表单输入”虚拟类别选择器、兄弟选择器 ( ~ )

线上展示:https://codepen.io/oxxo/pen/dPyLdPB

<!-- HTML 程式碼 -->
<div id="stopwatch">
  <input type="checkbox" id="pause">  
  <label for="pause">點我</label>
  <br>
  <span class="ms"></span>
</div>

<!-- CSS 程式碼 -->
<style>
  /* 自訂屬性 */
  @property --ms {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  #stopwatch {
    --state: paused;
    font-size: 50px;
    margin: 30px;
  }
  .ms {
    counter-reset: count-ms  var(--ms); 
    animation:  oxxo-ms 1s steps(10) var(--state) infinite;
  }
  .ms::before {
    content: counter(count-ms); 
  }
  @-webkit-keyframes oxxo-ms {
    to {
      --ms: 10;
    }
  }

  input {
    display:none;     /* 隱藏 checkbox,使用 label + for 連動 checkbox */
  }
  input:checked ~ * {
    --state: running; /* checked 狀態時啟動動畫 */
  }
  label {
    cursor: pointer;
  }
  label::after {
    content: " ( 暫停 )"
  }
  input:checked ~ label::after {
    content: " ( 繼續 )"
  }
</style>

CSS 教学 - 纯 CSS 码表 ( 可计时 ) - 点击后可以暂停和继续的数字

加入分钟数、秒数和毫秒数

延伸上述程序码,将其改成使用 input 的 checkbox 元素,并将负责暂停和继续的变数移动到 checked 状态的选择器里,就能做到点击开始,再点一下就暂停的效果。

参考:“表单输入”虚拟类别选择器、兄弟选择器 ( ~ )

线上展示:https://codepen.io/oxxo/pen/jEORZPL

<!-- HTML 程式碼 -->
<div id="stopwatch">
  <input type="checkbox" id="pause">  
  <label for="pause">點我</label>
  <br>
  <span class="num m10"></span><span class="num m"></span>:<span class="num s10"></span><span class="num s"></span>:<span class="num ms10"></span><span class="num ms"></span>
</div>

<!-- CSS 程式碼 -->
<style>
  /* 自訂屬性,分鐘十位數 */
  @property --m10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,分鐘個位數 */
  @property --m {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數十位數 */
  @property --s10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數個位數 */
  @property --s {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數十位數 */
  @property --ms10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數個位數 */
  @property --ms {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  #stopwatch {
    --state: paused;
    font-size: 50px;
    margin: 30px;
    font-family: monospace; /* 等寬字體 */
  }
  /* 把動畫樣式集中到一個類別中,透過變數就能產生不同的動畫效果
    --a-name 變數表示動畫名稱,--a-time 變數表示動畫時間,--a-steps 變數表示動畫步驟 */
  .num {
    animation: var(--a-name) var(--a-time) steps(var(--a-steps)) var(--state) infinite;
  }
  /* 分鐘數十位數 */
  .m10 {
    counter-reset: count-m10  var(--m10); 
    --a-name: oxxo-m10;
    --a-time: 3600s;    /* 動畫持續時間為 3600 秒 */
    --a-steps: 6;       /* 分成六個步驟,也就是一個步驟 600 秒 = 10 分鐘 */
  }
  .m10::before {content: counter(count-m10);}
  @-webkit-keyframes oxxo-m10 {
    to {--m10: 6;}
  }
  /* 分鐘數個位數 */
  .m {
    counter-reset: count-m  var(--m); 
    --a-name: oxxo-m;
    --a-time: 600s;    /* 動畫持續時間為 600 秒 */
    --a-steps: 10;     /* 分成十個步驟,也就是一個步驟 60 秒 = 1 分鐘 */
  }
  .m::before {content: counter(count-m); }
  @-webkit-keyframes oxxo-m {
    to {--m: 10;}
  }
  /* 秒數十位數 */
  .s10 {
    counter-reset: count-s10  var(--s10); 
    --a-name: oxxo-s10;
    --a-time: 60s;    /* 動畫持續時間為 60 秒 */
    --a-steps: 6;     /* 分成六個步驟,也就是一個步驟 10 秒 */
  }
  .s10::before {content: counter(count-s10);}
  @-webkit-keyframes oxxo-s10 {
    to {--s10: 6;}
  }
  /* 秒數個位數 */
  .s {
    counter-reset: count-s  var(--s); 
    --a-name: oxxo-s;
    --a-time: 10s;    /* 動畫持續時間為 10 秒 */
    --a-steps: 10;    /* 分成十個步驟,也就是一個步驟 1 秒 */
  }
  .s::before {content: counter(count-s);}
  @-webkit-keyframes oxxo-s {
    to {--s: 10;}
  }
  /* 豪秒數十位數 */
  .ms10 {
    counter-reset: count-ms10  var(--ms10); 
    --a-name: oxxo-ms10;
    --a-time: 1s;    /* 動畫持續時間為 1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.1 秒 */
  }
  .ms10::before {content: counter(count-ms10);}
  @-webkit-keyframes oxxo-ms10 {
    to {--ms10: 10;}
  }
  /* 豪秒數個位數 */
  .ms {
    counter-reset: count-ms  var(--ms); 
    --a-name: oxxo-ms;
    --a-time: 0.1s;  /* 動畫持續時間為 0.1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.01 秒 */
  }
  .ms::before {content: counter(count-ms); }
  @-webkit-keyframes oxxo-ms {
    to {--ms: 10;}
  }

  input {
    display:none;     /* 隱藏 checkbox,使用 label + for 連動 checkbox */
  }
  input:checked ~ * {
    --state: running; /* checked 狀態時啟動動畫 */
  }
  label {
    cursor: pointer;
  }
  label::after {
    content: " ( 暫停 )"
  }
  input:checked ~ label::after {
    content: " ( 繼續 )"
  }
</style>

CSS 教学 - 纯 CSS 码表 ( 可计时 ) - 加入分钟数、秒数和毫秒数

加入重新启动机制

如果要单纯使用 CSS 产生重新启动的机制,必须要稍微修改 HTML 程序码,修改重点如下:

  • 使用 form 元素包覆 button 和 checkbox 元素。
  • 透过 button 的 reset 类型重置 checkbox 的状态。
  • 新增负责“开始”的 checkbox。
  • 修改原本“暂停/继续”的 checkbox,和开始的 checkbox 互相搭配。
  • 按下重置 button 时,停止 CSS 动画。
  • 按下开始 checkbox 时,启动 CSS 动画。
  • 按下暂停 checkbox 时,暂停 CSS 动画。

下方范例除了按照上述重点修改程序码,也额外让开始与暂停 checkbox“只显示其中一种”,如此就能透过 active 和 ckecked 的虚拟类别,判断目前按钮状态,进而决定动画的播放状态。

线上展示:https://codepen.io/oxxo/pen/azbxqOP

<!-- HTML 程式碼 -->
<form id="stopwatch">
  <button id="reset" type="reset">點我就會重置</button>
  <br>
  <input type="checkbox" id="start">  
  <label for="start" class="start">點我 ( 開始 )</label>
  <input type="checkbox" id="pause">  
  <label for="pause" class="pause">點我</label>
  <br>
  <span class="num m10"></span><span class="num m"></span>:<span class="num s10"></span><span class="num s"></span>:<span class="num ms10"></span><span class="num ms"></span>
</form>

<!-- CSS 程式碼 -->
<style>
  /* 自訂屬性,分鐘十位數 */
  @property --m10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,分鐘個位數 */
  @property --m {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數十位數 */
  @property --s10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數個位數 */
  @property --s {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數十位數 */
  @property --ms10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數個位數 */
  @property --ms {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  #stopwatch {
    --state: paused;
    font-size: 50px;
    margin: 30px;
    font-family: monospace; /* 等寬字體 */
  }
  /* 把動畫樣式集中到一個類別中,透過變數就能產生不同的動畫效果
    透過虛擬類別判斷按下開始按 checkbox 時,才會進行動畫,否則動畫會停止
    --a-name 變數表示動畫名稱,--a-time 變數表示動畫時間,--a-steps 變數表示動畫步驟 */
  #start:checked ~ .num {
    animation: var(--a-name) var(--a-time) steps(var(--a-steps)) var(--state) infinite;
  }
  /* 分鐘數十位數 */
  .m10 {
    counter-reset: count-m10  var(--m10); 
    --a-name: oxxo-m10;
    --a-time: 3600s;    /* 動畫持續時間為 3600 秒 */
    --a-steps: 6;       /* 分成六個步驟,也就是一個步驟 600 秒 = 10 分鐘 */
  }
  .m10::before {content: counter(count-m10);}
  @-webkit-keyframes oxxo-m10 {
    to {--m10: 6;}
  }
  /* 分鐘數個位數 */
  .m {
    counter-reset: count-m  var(--m); 
    --a-name: oxxo-m;
    --a-time: 600s;    /* 動畫持續時間為 600 秒 */
    --a-steps: 10;     /* 分成十個步驟,也就是一個步驟 60 秒 = 1 分鐘 */
  }
  .m::before {content: counter(count-m); }
  @-webkit-keyframes oxxo-m {
    to {--m: 10;}
  }
  /* 秒數十位數 */
  .s10 {
    counter-reset: count-s10  var(--s10); 
    --a-name: oxxo-s10;
    --a-time: 60s;    /* 動畫持續時間為 60 秒 */
    --a-steps: 6;     /* 分成六個步驟,也就是一個步驟 10 秒 */
  }
  .s10::before {content: counter(count-s10);}
  @-webkit-keyframes oxxo-s10 {
    to {--s10: 6;}
  }
  /* 秒數個位數 */
  .s {
    counter-reset: count-s  var(--s); 
    --a-name: oxxo-s;
    --a-time: 10s;    /* 動畫持續時間為 10 秒 */
    --a-steps: 10;    /* 分成十個步驟,也就是一個步驟 1 秒 */
  }
  .s::before {content: counter(count-s);}
  @-webkit-keyframes oxxo-s {
    to {--s: 10;}
  }
  /* 豪秒數十位數 */
  .ms10 {
    counter-reset: count-ms10  var(--ms10); 
    --a-name: oxxo-ms10;
    --a-time: 1s;    /* 動畫持續時間為 1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.1 秒 */
  }
  .ms10::before {content: counter(count-ms10);}
  @-webkit-keyframes oxxo-ms10 {
    to {--ms10: 10;}
  }
  /* 豪秒數個位數 */
  .ms {
    counter-reset: count-ms  var(--ms); 
    --a-name: oxxo-ms;
    --a-time: 0.1s;  /* 動畫持續時間為 0.1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.01 秒 */
  }
  .ms::before {content: counter(count-ms); }
  @-webkit-keyframes oxxo-ms {
    to {--ms: 10;}
  }

  input {display:none;}
  label {cursor: pointer;}
  #start:checked ~ .start {
    display: none;          /* 點擊開始 label ( 勾選 start 之後 ) 隱藏 start 的 label */
  }
  #start:checked ~ * {
    --state: running;       /* 點擊開始 label ( 勾選 start 之後 ) 播放動畫 */
  }
  .pause {display: none;}   /* 暫停的 label 預設隱藏 */
  #start:checked ~ .pause {
    display: inline;        /* 點擊開始 label ( 勾選 start 之後 ),顯示暫停 label */ 
  }
  #start:checked ~ .pause::after  {
    content: " ( 暫停 )";    /* 點擊開始 label ( 勾選 start 之後 ),讓暫停 label 顯示狀態 */ 
  }
  #start:checked ~ #pause:checked ~ * {
    --state: paused;        /* 點擊開始 label ( 勾選 start 之後 ) 同時點擊暫停 labe ( 勾選 pause ),讓動畫暫停 */ 
  }
  #start:checked ~ #pause:checked ~ .pause::after {
    content: " ( 繼續 )"     /* 點擊開始 label ( 勾選 start 之後 ) 同時點擊暫停 labe ( 勾選 pause ),,讓暫停 label 顯示狀態 */ 
  }
</style>

CSS 教学 - 纯 CSS 码表 ( 可计时 ) - 加入重新启动机制

美化程序码以及码表样式

稍微修改范例程序码,将原本单调的画面,改成类似码表的画面,就会更有码表计时的氛围,修改时使用了虚拟类别和绝对定位等相关技巧,详细说明可以参考范例注解。

参考:“用户操作行为”虚拟类别选择器、定位 position

线上展示:https://codepen.io/oxxo/pen/YPzMeyz

<!-- HTML 程式碼 -->
<form id="stopwatch">
  <div class="circle"></div>
  <button id="reset" type="reset"></button>
  <br>
  <input type="checkbox" id="start">  
  <label for="start" class="start"></label>
  <input type="checkbox" id="pause">  
  <label for="pause" class="pause"></label>
  <div class="result">
    <span class="num m10"></span><span class="num m"></span>:<span class="num s10"></span><span class="num s"></span>:<span class="num ms10"></span><span class="num ms"></span>
    <h5>oxxo.studio</h5>
  </div>
</form>

<!-- CSS 程式碼 -->
<style>
  /* 自訂屬性,分鐘十位數 */
  @property --m10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,分鐘個位數 */
  @property --m {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數十位數 */
  @property --s10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,秒數個位數 */
  @property --s {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數十位數 */
  @property --ms10 {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  /* 自訂屬性,豪秒數個位數 */
  @property --ms {
    syntax: "<integer>";
    inherits: false;
    initial-value: 0;
  }
  #stopwatch {
    --state: paused;
    font-family: monospace; /* 等寬字體 */
  }
  /* 把動畫樣式集中到一個類別中,透過變數就能產生不同的動畫效果
    透過虛擬類別判斷按下開始按 checkbox 時,才會進行動畫,否則動畫會停止
    --a-name 變數表示動畫名稱,--a-time 變數表示動畫時間,--a-steps 變數表示動畫步驟 */
  #start:checked ~ .result .num {
    animation: var(--a-name) var(--a-time) steps(var(--a-steps)) var(--state) infinite;
  }
  /* 分鐘數十位數 */
  .m10 {
    counter-reset: count-m10  var(--m10); 
    --a-name: oxxo-m10;
    --a-time: 3600s;    /* 動畫持續時間為 3600 秒 */
    --a-steps: 6;       /* 分成六個步驟,也就是一個步驟 600 秒 = 10 分鐘 */
  }
  .m10::before {content: counter(count-m10);}
  @-webkit-keyframes oxxo-m10 {
    to {--m10: 6;}
  }
  /* 分鐘數個位數 */
  .m {
    counter-reset: count-m  var(--m); 
    --a-name: oxxo-m;
    --a-time: 600s;    /* 動畫持續時間為 600 秒 */
    --a-steps: 10;     /* 分成十個步驟,也就是一個步驟 60 秒 = 1 分鐘 */
  }
  .m::before {content: counter(count-m); }
  @-webkit-keyframes oxxo-m {
    to {--m: 10;}
  }
  /* 秒數十位數 */
  .s10 {
    counter-reset: count-s10  var(--s10); 
    --a-name: oxxo-s10;
    --a-time: 60s;    /* 動畫持續時間為 60 秒 */
    --a-steps: 6;     /* 分成六個步驟,也就是一個步驟 10 秒 */
  }
  .s10::before {content: counter(count-s10);}
  @-webkit-keyframes oxxo-s10 {
    to {--s10: 6;}
  }
  /* 秒數個位數 */
  .s {
    counter-reset: count-s  var(--s); 
    --a-name: oxxo-s;
    --a-time: 10s;    /* 動畫持續時間為 10 秒 */
    --a-steps: 10;    /* 分成十個步驟,也就是一個步驟 1 秒 */
  }
  .s::before {content: counter(count-s);}
  @-webkit-keyframes oxxo-s {
    to {--s: 10;}
  }
  /* 豪秒數十位數 */
  .ms10 {
    counter-reset: count-ms10  var(--ms10); 
    --a-name: oxxo-ms10;
    --a-time: 1s;    /* 動畫持續時間為 1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.1 秒 */
  }
  .ms10::before {content: counter(count-ms10);}
  @-webkit-keyframes oxxo-ms10 {
    to {--ms10: 10;}
  }
  /* 豪秒數個位數 */
  .ms {
    counter-reset: count-ms  var(--ms); 
    --a-name: oxxo-ms;
    --a-time: 0.1s;  /* 動畫持續時間為 0.1 秒 */
    --a-steps: 10;   /* 分成十個步驟,也就是一個步驟 0.01 秒 */
  }
  .ms::before {content: counter(count-ms); }
  @-webkit-keyframes oxxo-ms {
    to {--ms: 10;}
  }

  input {display:none;}
  label {cursor: pointer;}
  #start:checked ~ .start {display: none;}
  #start:checked ~ * {
    --state: running;
  }
  .pause {
    display: none;
  }
  #start:checked ~ .pause {
    display: inline;
    background: #0c0;  /* 開始計時的時候,暫停按鈕會變成綠色 */
  }

  #start:checked ~ #pause:checked ~ .pause {
    background: #f55;  /* 暫停計時的時候,暫停按鈕會變成紅色 */
  }
  #start:checked ~ #pause:checked ~ * {
    --state: paused;
  }
  /* 設定碼表表單 form 的尺寸 */
  #stopwatch {
    margin: 50px;
    position: relative;
    width: 400px;
    height: 400px;
  }
  /* 設定碼圓形碼表的形狀,不能將表單改成圓形,因為按鈕在表單之下會無法點擊,必須額外設定另一個形狀 */
  .circle {
    display: block;
    position: relative;
    width: 400px;
    height: 400px;
    border-radius: 50%;
    background: #ccc;
    border: 3px solid #000;
    z-index: 2;
  }
  /* 三個按鈕的位置和尺寸 */
  #reset, .start, .pause {
    position: absolute;
    border: 3px solid #000;
    width: 80px;
    height: 50px;
    left: calc(50% - 40px);
    top: -30px;
    cursor: pointer;
    background: #999;
  }
  /* 按下 reset 時的按鈕往下移動 */
  #reset:active {  
    top: -20px;
  }
  /* 數字欄位 */
  .result {
    position: absolute;
    z-index: 2;
    font-size: 60px;
    background: #333;
    color: #fff;
    text-align: center;
    padding: 10px 20px;
    border-radius: 10px;
    width: 300px;
    left: calc(50% - 170px);
    top: 150px;
    pointer-events: none;
  }
  /* 小小說明文字 */
  .result h5 {
    width: 100%;
    position: absolute;
    font-size: 14px;
    left: 0;
  }
  /* 暫停按鈕移動到旁邊 */
  .start, .pause {
    transform: rotateZ(45deg);
    left: 74%;
    top: 6%;
  }
  /* 按下暫停按鈕時,按鈕往內移動 */
  .start:active, .pause:active {
    left: 72%;
    top: 8%;
  }
  /* 開始按鈕是黃色 */
  .start {
    background: #f90;
  }
</style>

CSS 教学 - 纯 CSS 码表 ( 可计时 ) - 美化程序码以及码表样式

小结

CSS 码表使用了非常多 CSS 的进阶技巧,例如变数、控制动画、定位、虚拟类别...等,这些技巧虽然都很基本,但搭配起来却能产生非常酷炫的效果,不过由于 CSS 的码表“不是真的进位”,而是使用六组各自独立的数字,因此如果要制作“真正准确”的码表,建议还是使用 JavaScript 会比较妥当。

意见反馈

微信二维码 微信扫码关注 抖音二维码 抖音扫码关注