CSS 计数器

作者: CondorHero | 来源:发表于2019-12-01 15:56 被阅读0次
    前言

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


    图片左边的结构是一个导航目录,图片右边的结构一般可作为电商幻灯片的导航。在 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 计数器实现数值计算小游戏

    相关文章

      网友评论

        本文标题:CSS 计数器

        本文链接:https://www.haomeiwen.com/subject/hyfnictx.html