CSS counter计数器(content目录序号自动递增)详解
一、CSS计数器三角关系
CSS计数器只能跟content
属性在一起的时候才有作用,而content
属性貌似专门用在before
/after
伪元素上的。于是,就有了,“计数器↔伪元素↔content属性”的铁三角关系。
二、CSS计数器成员
举例班级中成员依次报名
其中有这么几个关键点:
1. 班级命名。总不能六脉神剑一指,你,侬,汝来称呼吧~有个称呼,如生信4班,就知道谁的是谁了。
2. 报数规则。1,2,3,4递增报数,还是1,2,1,2报数,让班级的人知道。
3. 开始报数。不发口令,大眼瞪小眼,会乱了秩序。
巧的是,以上3个关键点正好对应CSS计数器的2个属性和1个方法,依次是:
1. counter-reset
2. counter-increment
3. counter()/counters()
1. counter-reset
顾名思意,就是“计数器-重置”的意思。其实就是“班级命名”,主要作用就是给计数器起个名字。如果可能,顺便告诉下从哪个数字开始计数。默认是0
, 注意,默认是0
而不是1
. 可能有同学回疑惑,尼玛网上的各种例子默认显示的第1个数字不都是1
吗?那是因为受了counter-increment
普照的影响,后面会详细讲解。
OK, 这里,我们先看两个简单的counter-reset
的例子:
.xxx { counter-reset: small-apple; } /* 计数器名称是'small-apple' */
.xxx { counter-reset: small-apple 2; } /* 计数器名称是'small-apple', 并且默认起始值是2 */
demo:
.contaner1 {
counter-reset: number;
} .contaner1:before {
content: counter(number);
} .contaner2 {
counter-reset: number 1;
} .contaner2:before {
content: counter(number);
}
<div class="row">
<div class="contaner1">定义一个名称开始编号</div>
</div>
<div class="row">
<div class="contaner2">定义一个名称开始编号,定义初始值为1</div>
</div>
counter-reset
的计数重置可以是负数,例如-2
。也可以写成小数,例如2.99
,不过就是IE和FireFox都不识别,认为是不合法数值,直接无视,当作默认值0
来处理;不过Chrome不嫌贫嫉富,任何小数都是向下取整,如2.99
当成2
处理,于是王小二还是那个王小二。
到此为止?非也非也!counter-reset
还有一手,就是多个计数器同时命名。例如,王小二和王小三同时登台:
demo:
.contaner5 {
counter-reset: number 3 number1 4;
} .contaner5:before {
content: counter(number) '\A' counter(number1);
}
<div class="row">
<div class="contaner5">定义两个计数器,第一个从3开始,第二个从4开始</div>
</div>
直接空格分隔,譬如逗号什么的都不行。
另外,counter-reset
还可以设置为none
和inherit
. 干掉重置以及继承重置。你懂的,就不展开了。
2. counter-increment
顾名思意,就是“计数器-递增”的意思。值为counter-reset
的1个或多个关键字。后面可以跟随数字,表示每次计数的变化值。如果缺省,则使用默认变化值1
(方便起见,下面的都使用默认值做说明)。
CSS的计数器的计数是有一套规则的,我将之形象地称为“普照规则”。具体来讲就是:普照源(counter-reset)唯一,每普照(counter-increment)1次,普照源增加1次计数值。
于是,我们可以解释上面提到的“默认值是0
”的问题。通常CSS计数器应用的时候,我们都会使用counter-increment
, 肯定要用这个,否则怎么递增呢!而且一般都是1
次普照,正好+1
,第一个计数的值就是1
啦(0+1=1)!
下面,通过几个例子,给大家形象地展示下普照规则。
Demo相关核心代码为:
.contaner3 {
counter-reset: number 1;
counter-increment: number;
} .contaner3:before {
content: counter(number);
}
<div class="row">
<div class="contaner3">定义一个名称开始编号,定义初始值为1,定义它的编码规则 每次自增1(只有父元素)</div>
</div>
这里counter-increment
普照了p
标签,counter-reset
值增加,默认递增1
,于是计数从设置的初始值2
变成了3
,wangxiaoer
就是这里的计数器,自然伪元素content值counter(wangxiaoer)
就是3
.
当然,也可以普照自身,也就是counter-increment
直接设置在子元素上:
.contaner7 {
counter-reset: number 1;
} .contaner7:before {
counter-increment: number;
content: counter(number);
}
<div class="row">
<div class="contaner7">定义一个名称开始编号,定义初始值为1,定义它的编码规则 每次自增1(只有子元素)</div>
</div>
依然是1次普照,依旧全局的计数器+1
,所以,显示的数值还是3
().
趁热打铁。如果父元素和子元素都被counter-increment
普照1遍,结果会如何呢?
很简单的,父元素1次普照,子元素1次普照,共两次普照,counter-reset
设置的计数器值增加2次,计数起始值是1,于是现实的数字就是3
啦!
.contaner4 {
counter-reset: number 1;
counter-increment: number;
} .contaner4:before {
content: counter(number);
counter-increment: number;
}
<div class="row">
<div class="contaner4">定义一个名称开始编号,定义初始值为1,定义它的编码规则 每次自增1(父元素和子元素都有)</div>
</div>
总而言之,无论位置在何方,只要有counter-increment
,对应的计数器的值就会变化,counter()
只是输出而已!
理解了“普照规则”,则以我们通常的计数器递增效果也可以理解了。
考虑下面这两个问题:
- 爸爸受到普照,且重置默认值
0
,爸爸有2个孩子。孩子自身都没有普照。两个孩子的计数值是? - 爸爸没有普照,重置默认值
0
,爸爸有2个孩子。孩子自身都接受普照。两个孩子的计数值是?
答案是:1,1和1,2!
哦?答案居然不一样,有什么差别呢?
很简单。什么爸爸,孩子你都不要关心。只要看被普照了几次。情况1就爸爸被普照,因此,计数器增加1次,此时两个孩子的counter
自然都是1
; 情况2,两个孩子被普照,普照2次,第1个孩子普照之时,计数器+1,也就是1;第2个孩子普照之时再+1,于是就是2. 于是,两个孩子的counter
输出就是1,2
.
.row4 .contaner6:before {
counter-increment: number;
content: counter(number);
}
.row4 {
counter-reset: number 1;
}
<div class="row4 row">
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
</div>
计数器的数值变化遵循HTML渲染顺序,遇到一个increment
计数器就变化,什么时候counter
输出就输出此时的计数值。看懂了下图,您自然就会全然明白“普照规则”了。
counter-increment其他设定counter-reset
可以一次命名两个计数器名称,counter-increment
自然有与之呼应的设定,也是名称留空就可以了。
正如本节开始提到的,这变化的值不一定是1
,我们可以灵活设置。例如:
counter-increment: counter 2
那就是偶数偶数的增加。例如下面这个变身:
还可以是负数,例如:
counter-increment: counter -1
.row2 {
counter-reset: number 0;
} .row2 .contaner6:before {
counter-increment: number -1;
content: counter(number);
}
<div class="row2 row ">
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<div class="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
</div>
就有了递减排序效果啦!
值还可以是none
或者inherit
.
3. counter()/counters()
这是个方法,不是属性。类似CSS3中才calc()
计算。这里作用很单纯显示计数。不过名称、用法有多个:
① 目前为止,我们看到的是最简单的用法:
counter(name) /* name就是counter-reset的名称 */
② 那下面这个语法是什么意思呢?
counter(name, style)
这里的style
参数还有有些名堂的。其支持的关键字值就是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
.row1 {
counter-reset: number 1;
}
.row1 .contaner6:before {
counter-increment: number;
content: counter(number,upper-roman);
}
<div class="row1 row">
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<div class="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
</div>
③ counter还支持级联。也就是一个content
属性值可以有多个counter()
方法。
上面CSS源代码使用'\A'
使用inline
水平元素换行,此技术若有兴趣,可参考之前的“使用CSS(Unicode字符)让inline水平元素换行”一文。
④ 下面介绍下counters()
方法。看似值多了个字母s
, 但表意大变身。counters
几乎可以说是嵌套计数的代名词。
我们平时的序号,不可能就只是1,2,3,4,..
, 还会有诸如 1.1,1.2,1.3,...
等的子序号。得,前者就是counter()
干的事情,后者就是counters()
干的事情。
基本用法为:
counters(name, string); /* MDN上说,要想IE8兼容,这里逗号后面的空格要去掉,但是鄙人IE11的IE8模式看,无此问题 */
其中,string
参数为字符串(需要引号包围的)(必须参数),表示子序号的连接字符串。例如1.1
的string
就是'.'
, 1-1
就是'-'
.
看上去很简单。但是,如果理解不是很深刻,日后在使用肯定会遇到麻烦——“咦?怎么没有子序列,明明语法正确的啊?”首先,记住这一句话,“普照源是唯一的”,所以,如果你在只在body
标签上设置counter-reset
,就算里面的子元素嵌套了祖宗十八代,还是不会有任何嵌套序号出现的!
所以,要想实现嵌套,必须让每一个列表容器拥有一个“普照源”,通过子辈对父辈的counter-reset
重置、配合counters()
方法才能实现计数嵌套效果。
.row3{ counter-reset:number 0;}
.row3 .contaner6:before{
counter-increment: number 1;
content:counters(number,"-") '.';
}
<div class="row3 row">
<div class="contaner6">自动标号----第一级
<div class="row3">
<div class="contaner6">
自动标号-----第二级
<div class="row3">
<div class="contaner6">
自动标号-----第三级
<div class="row3">
<div class="contaner6">自动标号-----第四级</div>
<div class="contaner6">自动标号-----第四级</div>
<div class="contaner6">自动标号-----第四级</div>
<div class="contaner6">自动标号-----第四级</div>
<div class="contaner6">自动标号-----第四级</div>
</div>
</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
</div>
</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
</div>
</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
<div class="contaner6">自动标号</div>
</div>
也会遇到这样的麻烦——“咦,怎么子序列不按层级顺序来啊,命名语法正确啊?” 还是要记住这一句话:“一个容器里的普照源(reset)是唯一的”,所以,
如果你不小心把计数显示和技术reset元素以兄弟元素形式放在一起(虽然HTML内容布局呈现是没有异常的),就很可能会出现计数序号乱入的情况。
会看到标红的部分的序号显示异常了!
为何会出现这个问题,我们看下HTML(主要是注释):
<div class="reset">
<div class="counter">我是王小二</div>
<div class="reset"><-- 这里的reset与上面的counter是兄弟关系,而不是父子关系。虽然布局渲染上没有差异。但是,一个容器的reset的唯一的,一旦子元素出现reset,会改变整个容器的嵌套关系,于是,后面的“王小三”、“王小四”其实已经进入了2级嵌套,因此显示的是1-3和1-4 -->
...
</div>
<div class="counter">我是王小三</div>
<div class="counter">我是王小四</div>
<div class="reset">
<div class="counter">我是王小四的大儿子</div>
</div>
</div>
如果上面的注释没看明白,您可以跟前面没有问题的demo做下HTML结构对比,或许就会豁然开朗!
⑤ counters()
也是支持style
自定义递增形式的。
counters(name, string, style)
与counter()
的style
参数使用一致,不赘述。
四、CSS计数器与display:none
一个元素,如果设置了counter-increment
, 但是其display
的属性值是none
或者含有hidden
属性(针对支持浏览器),则此计数值是不会增加的。而visibility:hidden
以及其他声明不会有此现象。
五、CSS计数器实际应用
相比传统的ol
,ul
列表计数,CSS计数器的优势就在于灵活与强大,不足就是IE6/IE7不支持。
普照规则第一条,普照源唯一。所以,我们可以在头尾放两个差距甚远的列表,然后,这些列表自动显示序号。而ol/ul
只能写死start
实现,很不灵活,一旦列表有删减,就嗝屁了。
由于计数器是伪元素控制显示的。因此,我们几乎可以应用各种CSS样式,各种定位等。所以,基本上,只要有有序序号呈现的地方,就能使用CSS计数器。
例如,电商首页的图片slide广告上的1,2,3,4,...
序号;
我们做分享时候使用的HTML5 web在线幻灯片就可以使用CSS计数器标注页数等;以及一开始给小伙伴们做的果汁工具的3个选择等。
参考文章
- Automatic Numbering With CSS Counters
- http://www.w3.org/TR/CSS2/generate.html#scope
- counter-reset
- counter-increment
- Using CSS counters
本文原创地址:http://www.zhangxinxu.com/wordpress/?p=4303
CSS counter计数器(content目录序号自动递增)详解的更多相关文章
- CSS计数器(序列数字字符自动递增)详解———张鑫旭
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=4303 一.挖坟不可耻 ...
- CSS中伪类及伪元素用法详解
CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的 ...
- content = "IE=edge,chrome=1" 详解
content = "IE=edge,chrome=1" 详解 < meta http-equiv = "X-UA-Compatible" content ...
- 【二次元的CSS】—— 用 DIV + CSS3 画咸蛋超人(详解步骤)
[二次元的CSS]—— 用 DIV + CSS3 画咸蛋超人(详解步骤) 2016-05-17 HTML5cn 仅仅使用div作为身体的布局,用css3的各种transform和圆角属性来绘制各部位的 ...
- web前端学习(三)css学习笔记部分(6)-- 选择器详解
9.选择器详解 9.1 属性选择器 CSS3 属性选择器,在 CSS3 中,追加了三个属性选择器分别为:[att*=val].[att^=val]和[att$=val],使得属性选择器有了通配符的概 ...
- linux系统/var/log目录下的信息详解
一./var目录 /var 所有服务的登录的文件或错误信息文件(LOG FILES)都在/var/log下,此外,一些数据库如MySQL则在/var/lib下,还有,用户未读的邮件的默认存放地点为/v ...
- Tomcat的目录结构和配置文件详解
本文转载: https://www.zybuluo.com/1234567890/note/515235 参考帖子: Tomcat(一):基础配置详解 Tomcat服务器中配置多个域名,访问不同的we ...
- 实时通讯系列目录篇之SignalR详解
一. 简单说几句 最早使用SignalR的时候大约是两年前了,记得当时是一个OA中消息的实时提醒,轮询的方式有点耗资源,WebSocket写起来又比较麻烦,最终选择了SignalR,当时是什么版本已经 ...
- Snort里如何将读取的包记录存到指定的目录下(图文详解)
不多说,直接上干货! 比如,在/root/log目录下. [root@datatest ~]# snort -dve -l /root/log 需要注意: 1) /log目录需要你自己建立,并修改权限 ...
随机推荐
- Spring的依赖注入概述
以下内容引用自http://wiki.jikexueyuan.com/project/spring/dependency-injection.html: 每个基于Java应用程序都有几个对象,这些对象 ...
- Javascript:如何调用全局变量?
怎样使用全局变量呢? window.globalVariableName 参考: https://blog.csdn.net/zyz511919766/article/details/7276089
- vim中末行去掉^M
在Ubuntu系统中打开文件,发现文件中每一个末行都有^M,我们要做的是知道这一个无关的字符是什么作用,然后删除掉这一个无关的字符. 工具/原料 ubuntu操作系统 Vim编辑器 方法/步骤 ...
- Swift下调用Touch ID实现指纹识别
iOS开发交流群:484884085 欢迎大家增加. 例如以下代码是实现调用5S以上设备指纹识别的代码,依照官网给出的代码,会出现识别成功后非常久才运行成功后调用的代码,逛了非常久的.才知道要将其放入 ...
- 搭建企业内部DNS服务器,docker 部署内部 dnsmasq
获取镜像 docker pull jpillora/dnsmasq 配置域名 # http://oss.segetech.com/intra/srv/dnsmasq.conf #log all dns ...
- firebug console说明
控制台(Console)是Firebug的第一个面板,也是最重要的面板,主要作用是显示网页加载过程中产生各类信息. 一.显示信息的命令 Firebug内置一个console对象,提供5种方法,用来显示 ...
- Adobe Flash builder破解方法
Flash Builder 4 有许多新的特性,可以结合新的功能使用新的Flex 4框架创建出更炫的应用.基于用户的反馈,对以数据中心的开发也进行了优化:对类如配置从服务器返回的数据类型这样的任务,也 ...
- 【转载】5种网络IO模型
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
- 如何理解pca和svd的关系?
主成分分析和奇异值分解进行降维有何共同点? 矩阵的奇异值分解 当矩阵不是方阵,无法为其定义特征值与特征向量,可以用一个相似的概念来代替:奇异值. 通常用一种叫奇异值分解的算法来求取任意矩阵的奇异值: ...
- WCF服务端的.NET Core支持项目Core WCF 正式启动
长期以来在wcf客户端库 https://github.com/dotnet/wcf 里反应最强烈的就是.NET Core的服务端支持 https://github.com/dotnet/wcf/is ...