前言
前端页面上的计数排列一般比较常见的结构就两种:
图片左边的结构是一个导航目录,图片右边的结构一般可作为电商幻灯片的导航。在 HTML 层面我们实现这种效果一般使用
ul
或 ol
。当然你也可以使用别的标签来实现。HTML 的 ul
和 ol
作为序列使用是非常好用的,唯一的遗憾就是序列号可用性比较差,虽然提供了 list-style-image
。要想使用 ol
来实现前面带 1.1
的这种目录结构,还是比较难的。
这时候该是 css 计数器 counter 出场了。
API 介绍
css 计数器一共涉及,两个属性一个方法,如下:
- counter-reset
功能是可以创建计数器即是给计数器命名的,也可以重置计数器。默认是 0。
.xxx{counter-reset: name;}/*创建一个为name的计数器,默认从0开始计数*/
.xxx{counter-reset: name 10;}/*创建一个为name的计数器,默认从10开始计数*/
多个计数器还可以这样写:
.xxx { counter-reset: name 1 name 2; }
另外,counter-reset 还可以设置为 none 和 inherit. 干掉重置以及继承重置。
- counter-increment
递增/递减变量,计数器的增量/减量,1 个或多个关键字。后面如果跟随数字,表示每次计数的变化值。如果缺省,则使用默认增值 1。
.xxx{counter-increment: name;}/*name计数器每次增加1*/
.xxx{counter-increment: name 10;}/*name计数器每次增加10*/
.xxx{counter-increment: name -10;}/*name计数器每次减少10递减效果*/
- counter()/counters()
将计数器的值添加到元素。计数的结果将通过counter()/counters()
展示出来。
counter(name)/*把叫name的计数器展示出来,格式为1、2、3......*/
还有一种用法:
counter(name,style)
name 就是计数器的名字,style 是什么?默认递增递减是数字,style 就是用来自定义递增递减不是数字,例如可以是 a、b、c。 其支持的关键字值和 list-style-type 支持的那些值相同。
list-style-type:disc | circle | square | decimal | lower-roman | upper-roman | lower-alpha | upper-alpha | none | armenian | cjk-ideographic | georgian | lower-greek | hebrew | hiragana | hiragana-iroha | katakana | katakana-iroha | lower-latin | upper-latin
一个content属性值还可以有多个counter()方法。
一个简单的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
html{
background-color: #ffc9eb;
}
div{
counter-reset: name;
}
p{
counter-increment: name;
}
p::after{
content: counter(name);
}
</style>
</head>
<body>
<div>
<p>section</p>
</div>
</body>
</html>
看 section 后面是不是多了个 1?
代码解析:
- 通过
counter-reset
命名一个计数器叫name
,默认重 0 开始。 - 计数器在 div 标签上,它会照耀所有的子孙,计数器的递增在 p 标签上面默认增量为 1,标签展示的时候只要通过 p 就会增加 1。
- 计数器的展示,通过伪元素 (before 和 after) 里面的 content 配合 counter 或 counters。
下面讲一下最难得增量 counter-increment
,因其放的位置不同会引发不同的递增递减效果。
counter-increment 的位置
counter-increment 负责自增,只要其位置在 counter-reset 和 counter/counters 之间,展示时就会有增加的效果,计数器的解析规则和 HTML 的解析规则相同。所以 counter-increment 达到增加一次的效果,针对案例可以写的几种方式为:
自增一次
第一种:写在计数器定义和展示的中间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS计数器</title>
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name 9;
}
.increment{
counter-increment: name;
}
p::after{
content: counter(name);
}
</style>
</head>
<body>
<div class="reset">
<div class="increment">自增
<p>我后面是一个</p>
</div>
</div>
</body>
</html>
第二种:写在计数器定义的位置
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name 9;
counter-increment: name;
}
p::after{
content: counter(name);
}
</style>
第三种:写在计数器展示的位置
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name 9;
}
p::after{
counter-increment: name;
content: counter(name);
}
</style>
猜猜下面 h1 标签的伪类应该显示什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS计数器</title>
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name 10;
}
.increment{
counter-increment: name 5;
}
h1::after,p::after{
content: counter(name);
}
</style>
</head>
<body>
<div class="reset">
<div class="increment">自增
<p>我后面是一个</p>
</div>
<h1>猜猜我的结果</h1>
</div>
</body>
</html>
猜猜看
p 标签后面是 15,是没有问题的,h1 后面也是 15。不知道你猜对了没?根据 HTML 解析规则和计数器使用规则,到 p 标签的时候是 15 ,h1 显示的又是相同的计数器,所以 h1 和 p 计数相等。
针对上面代码,我们不动 HTML 里面的,只更改 CSS 里面的代码,改成如下代码所示,再次猜猜看:
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name 10;
counter-increment: name 5;
}
.increment{
counter-increment: name 5;
}
h1::after,p::after{
counter-increment: name 5;
content: counter(name);
}
</style>
是不是很简单计数器的数值变化遵循 HTML 渲染顺序,遇到一个 increment 计数器就变化,什么时候 counter 输出就输出此时的计数值。
counters() 这个方法还是要说下的。虽然和 counter 相比就多了个字母 s, 但两者的功能还是有很大的不同。counters 可以理解为嵌套计数。
我们平时的序号,不可能就只是1,2,3,4,.., 还会有诸如 1.1,1.2,1.3,...等的子序号。前者就是counter()干的事情,后者就是counters()干的事情。
counters 的用法:
counters(name, string, style)
name 就是计数器的名字,string 表示子序号的连接字符串。例如 1.1
的 string
就是'.', 1-1
就是 '-'
。style 与 counter() 的 style 参数使用一致。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS计数器</title>
<style>
html{
background-color: pink;
}
.reset{
counter-reset: name;
}
.item{
text-indent: 2em;
}
.d2{
text-indent: 4em;
}
.d3{
text-indent: 6em;
}
.item::before{
counter-increment: name;
content:counters(name,"-") '. ';
}
</style>
</head>
<body>
<div class="reset">
<div class="content">目录</div>
<div class="item">
术语
<div class="reset">
<div class="item d2">docker client</div>
<div class="item d2">docker host</div>
<div class="item d2">docker daemon</div>
<div class="item d2">container</div>
<div class="item d2">registry</div>
</div>
</div>
<div class="item">
安装 docker
<div class="reset">
<div class="item d2">
守护进程配置
</div>
</div>
</div>
<div class="item">
底层原理
<div class="reset">
<div class="item d2">
namespace
<div class="reset">
<div class="item d3">pid: 隔离进程</div>
<div class="item d3">net: 隔离网络</div>
<div class="item d3">ipc: 隔离 IPC</div>
<div class="item d3">mnt: 隔离文件系统挂载</div>
<div class="item d3">uts: 隔离hostname</div>
<div class="item d3">user: 隔离uid/gid</div>
</div>
</div>
<div class="item d2">control groups</div>
<div class="item d2">union file system</div>
</div>
</div>
<div class="item">
镜像
<div class="reset">
<div class="item d2">镜像仓库与拉取</div>
<div class="item d2">构建镜像与发布</div>
</div>
</div>
<div class="item">
Dockerfile
<div class="reset">
<div class="item d2">FROM</div>
<div class="item d2">ADD</div>
<div class="item d2">COPY</div>
<div class="item d2">CMD</div>
<div class="item d2">ENTRYPOINT</div>
</div>
</div>
<div class="item">
容器
<div class="reset">
<div class="item d2">创建容器</div>
<div class="item d2">容器管理</div>
</div>
</div>
</div>
</body>
</html>
代码测试结果:
写给前端工程师的 docker 简易入门目录
最后注意:
一个元素,如果设置了 counter-increment 属性, 这个元素还设置了
display:none
或在标签上直接设置 hidden 属性 (<span hidde></span>
)计数在此元素上失效。
感兴趣的还可以研究下下面这个案例,没写 JS 代码但是是动态的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS计数器</title>
<style>
body {
counter-reset: icecream;
}
input:checked {
counter-increment: icecream;
}
.total::after {
content: counter(icecream);
}
</style>
</head>
<body>
<strong>下面中国十大冰淇淋你吃过几个?</strong>
<ol>
<li><input type="checkbox" id="icecream1"><label for="icecream1">哈根达斯</label></li>
<li><input type="checkbox" id="icecream2"><label for="icecream2">和路雪wall's</label></li>
<li><input type="checkbox" id="icecream3"><label for="icecream3">八喜冰淇淋</label></li>
<li><input type="checkbox" id="icecream4"><label for="icecream4">DQ冰淇淋</label></li>
<li><input type="checkbox" id="icecream5"><label for="icecream5">蒙牛冰淇淋</label></li>
<li><input type="checkbox" id="icecream6"><label for="icecream6">雀巢冰淇淋</label></li>
<li><input type="checkbox" id="icecream7"><label for="icecream7">伊利冰淇淋</label></li>
<li><input type="checkbox" id="icecream8"><label for="icecream8">乐可可冰淇淋</label></li>
<li><input type="checkbox" id="icecream9"><label for="icecream9">新城市冰淇淋</label></li>
<li><input type="checkbox" id="icecream10"><label for="icecream10">明治MEIJI</label></li>
</ol>
你总共选择了 <strong class="total"></strong> 款冰淇淋!
</body>
</html>
还可以使用 CSS 计数器实现数值计算小游戏
网友评论