您的位置:首页 > Web前端 > CSS

CSS counter计数器(content目录序号自动递增)详解

2016-11-17 15:58 369 查看

一、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-apple2;}/*计数器名称是'small-apple',并且默认起始值是2*/

demo:

.contaner1{
counter-reset:number;
}

.contaner1:before{
content:counter(number);
}

.contaner2{
counter-reset:number1;
}

.contaner2:before{
content:counter(number);
}

<divclass="row">
<divclass="contaner1">定义一个名称开始编号</div>
</div>
<divclass="row">
<divclass="contaner2">定义一个名称开始编号,定义初始值为1</div>
</div>


  


counter-reset
的计数重置可以是负数,例如
-2
。也可以写成小数,例如
2.99
,不过就是IE和FireFox都不识别,认为是不合法数值,直接无视,当作默认值
0
来处理;不过Chrome不嫌贫嫉富,任何小数都是向下取整,如
2.99
当成
2
处理,于是王小二还是那个王小二。

到此为止?非也非也!
counter-reset
还有一手,就是多个计数器同时命名。例如,王小二和王小三同时登台:

demo:

.contaner5{
counter-reset:number3number14;
}

.contaner5:before{
content:counter(number)'\A'counter(number1);
}


<divclass="row">
<divclass="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:number1;
counter-increment:number;
}

.contaner3:before{
content:counter(number);
}

<divclass="row">
<divclass="contaner3">定义一个名称开始编号,定义初始值为1,定义它的编码规则每次自增1(只有父元素)</div>
</div>


这里
counter-increment
普照了
p
标签,
counter-reset
值增加,默认递增
1
,于是计数从设置的初始值
2
变成了
3
wangxiaoer
就是这里的计数器,自然伪元素content值
counter(wangxiaoer)
就是
3
.

当然,也可以普照自身,也就是
counter-increment
直接设置在子元素上:

.contaner7{
counter-reset:number1;
}

.contaner7:before{
counter-increment:number;
content:counter(number);
}


<divclass="row">
<divclass="contaner7">定义一个名称开始编号,定义初始值为1,定义它的编码规则每次自增1(只有子元素)</div>
</div>



依然是1次普照,依旧全局的计数器
+1
,所以,显示的数值还是
3
().



趁热打铁。如果父元素和子元素都被
counter-increment
普照1遍,结果会如何呢?

很简单的,父元素1次普照,子元素1次普照,共两次普照,
counter-reset
设置的计数器值增加2次,计数起始值是1,于是现实的数字就是
3
啦!

.contaner4{
counter-reset:number1;
counter-increment:number;
}

.contaner4:before{
content:counter(number);
counter-increment:number;
}

<divclass="row">
<divclass="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:number1;
}

<divclass="row4row">
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
</div>


 

 

计数器的数值变化遵循HTML渲染顺序,遇到一个
increment
计数器就变化,什么时候
counter
输出就输出此时的计数值。看懂了下图,您自然就会全然明白“普照规则”了。



counter-increment其他设定
counter-reset
可以一次命名两个计数器名称,
counter-increment
自然有与之呼应的设定,也是名称留空就可以了。

正如本节开始提到的,这变化的值不一定是
1
,我们可以灵活设置。例如:

counter-increment:counter2


那就是偶数偶数的增加。例如下面这个变身:



还可以是负数,例如:

counter-increment:counter-1


.row2{
counter-reset:number0;
}

.row2.contaner6:before{
counter-increment:number-1;
content:counter(number);
}

<divclass="row2row">
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="contaner6">自动标号--递减--初始值是0(默认是0)----每次自减1(默认是1)</div>
<divclass="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:number1;
}
.row1.contaner6:before{
counter-increment:number;
content:counter(number,upper-roman);
}

<divclass="row1row">
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="contaner6">自动标号-递增---初始值是1---每次自增1(默认是1)</div>
<divclass="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:number0;}
.row3.contaner6:before{
counter-increment:number1;
content:counters(number,"-")'.';
}
<divclass="row3row">
<divclass="contaner6">自动标号----第一级
<divclass="row3">
<divclass="contaner6">
自动标号-----第二级
<divclass="row3">
<divclass="contaner6">
自动标号-----第三级
<divclass="row3">
<divclass="contaner6">自动标号-----第四级</div>
<divclass="contaner6">自动标号-----第四级</div>
<divclass="contaner6">自动标号-----第四级</div>
<divclass="contaner6">自动标号-----第四级</div>
<divclass="contaner6">自动标号-----第四级</div>
</div>
</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
</div>
</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
</div>
</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
<divclass="contaner6">自动标号</div>
</div>


  



也会遇到这样的麻烦——“咦,怎么子序列不按层级顺序来啊,命名语法正确啊?”还是要记住这一句话:“一个容器里的普照源(reset)是唯一的”,所以,

如果你不小心把计数显示和技术reset元素以兄弟元素形式放在一起(虽然HTML内容布局呈现是没有异常的),就很可能会出现计数序号乱入的情况。

会看到标红的部分的序号显示异常了!



为何会出现这个问题,我们看下HTML(主要是注释):

<divclass="reset">
<divclass="counter">我是王小二</div>
<divclass="reset"><--这里的reset与上面的counter是兄弟关系,而不是父子关系。虽然布局渲染上没有差异。但是,一个容器的reset的唯一的,一旦子元素出现reset,会改变整个容器的嵌套关系,于是,后面的“王小三”、“王小四”其实已经进入了2级嵌套,因此显示的是1-3和1-4-->
...
</div>
<divclass="counter">我是王小三</div>
<divclass="counter">我是王小四</div>
<divclass="reset">
<divclass="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,...
序号;



我们做分享时候使用的HTML5web在线幻灯片就可以使用CSS计数器标注页数等;以及一开始给小伙伴们做的果汁工具的3个选择等。

参考文章

AutomaticNumberingWithCSSCounters

http://www.w3.org/TR/CSS2/generate.html#scope

counter-reset

counter-increment

UsingCSScounters

本文原创地址:http://www.zhangxinxu.com/wordpress/?p=4303
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航