前端基础前端

CSS 计数器

2019-12-01  本文已影响0人  CondorHero
前言

前端页面上的计数排列一般比较常见的结构就两种:


图片左边的结构是一个导航目录,图片右边的结构一般可作为电商幻灯片的导航。在 HTML 层面我们实现这种效果一般使用 ulol。当然你也可以使用别的标签来实现。HTML 的 ulol 作为序列使用是非常好用的,唯一的遗憾就是序列号可用性比较差,虽然提供了 list-style-image。要想使用 ol 来实现前面带 1.1 的这种目录结构,还是比较难的。

这时候该是 css 计数器 counter 出场了。

API 介绍

css 计数器一共涉及,两个属性一个方法,如下:

  1. 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. 干掉重置以及继承重置。

  1. counter-increment
    递增/递减变量,计数器的增量/减量,1 个或多个关键字。后面如果跟随数字,表示每次计数的变化值。如果缺省,则使用默认增值 1。
.xxx{counter-increment: name;}/*name计数器每次增加1*/
.xxx{counter-increment: name 10;}/*name计数器每次增加10*/
.xxx{counter-increment: name -10;}/*name计数器每次减少10递减效果*/
  1. 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?


代码解析:

  1. 通过 counter-reset 命名一个计数器叫 name,默认重 0 开始。
  2. 计数器在 div 标签上,它会照耀所有的子孙,计数器的递增在 p 标签上面默认增量为 1,标签展示的时候只要通过 p 就会增加 1。
  3. 计数器的展示,通过伪元素 (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.1string 就是'.', 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 计数器实现数值计算小游戏
上一篇下一篇

猜你喜欢

热点阅读