前面介绍过 CSS 里的::before 和::after 这两个伪元素,以及 content 相关的用法,这篇将针对 content 搭配 counter(计数器)进行一些有趣的应用,相信熟练之后搞不好很好玩也说不定。
counter 基本用法
在 CSS 里头,counter 是个很有意思的功能,最常见得就是如果我们使用 list 清单,样式选择 decimal 十进制,当清单变多的时候数字也会跟着增加,底层貌似就是使用 counter 来做的,也因为 counter 所产生的数值并不存在于网页的元素内,所以如果我们要在清单元素之外使用,就必须透过::before 或::after 的 content 来实现。
counter 最的基本用法一定要有一个父元素和子元素(类似 list 的原理,使用 ul 包着 li),所以长相会类似下面这段 html:
<div>
<span> 钢铁人 </span>
<span> 美国队长 </span>
<span> 雷神索尔 </span>
</div>
在 CSS 里头,先针对 div 父元素使用 counter-reset:num;进行计数器归零的设置,里面 num 是计数器累加数值的变数,接着可以在 span::before 里面看到 counter-increment:num;这一段,这段的作用是把 num 累加上去,预设数值为加 1,接着就透过 content 显示出来。
计数器预设的显示语法为:counter(计数器名称,list-style-type)
div{
counter-reset:num;
}
span{
display:block;
}
span::before{
counter-increment:num;
content:counter(num) ‘. ‘;
}
透过指定一开始 counter-reset 的起始数值,还有 counter-increment 累加的间隔数值,就可以做出从某个数值开始或只显示偶数、奇数的效果。
div{
counter-reset:num 3;
}
span{
display:block;
}
span::before{
counter-increment:num 2;
content:counter(num) ‘. ‘;
}
如果要更换数字的样式,也可以透过计数器的第二个设定值 list-style-type 来更改,下面的例子就是将样式更改为 georgian。
div{
counter-reset:num;
}
span{
display:block;
}
span::before{
counter-increment:num;
content:counter(num, georgian) ‘. ‘;
}
counter 进阶用法
除了指定单一个变数外,counter 也可以同时指定多个变数,例如下面这段 HTML,有三个类别在里面,我分别用 span、i 和 b 来分类。
<div>
<span> 钢铁人 </span>
<span> 美国队长 </span>
<span> 雷神索尔 </span>
<i> 宙斯盾局 </i>
<i> 神鬼局 </i>
<i> 神经局 </i>
<b> 九头蛇 </b>
<b> 九头牛 </b>
<b> 九头猪 </b>
</div>
CSS 一开始 counter-reset 可以指定多个变数,透过一个空白字元分隔,如果空白字元后面接着数字则是起始值,没有数字预设为 0,当这样设定之后,就可以看到不同类别的数字代号就不同。
如果遇到了巢状结构,需要一层层的展开(例如:1 > 1.1 > 1.1.1),采用上述的作法可能就会复杂许多,好在 counter 还提供了另外一个 counters 的功能,目的就是来解决巢状结构的麻烦事,在开始前可以先看看透过 ul 和 li 组合的清单长相:
<ul>
<li> 第一层
<ul>
<li> 第二层
<ul>
<li> 第三层 </li>
<li> 第三层 </li>
<li> 第三层 </li>
</ul>
</li>
<li> 第二层 </li>
<li> 第二层 </li>
</ul>
</li>
<li> 第一层 </li>
<ul>
<li> 第二层 </li>
<li> 第二层 </li>
</ul>
</ul>
传统的清单如果将 list-style 设为 decimal,同样可以具备数字接续的功能,但相对来说要做一些特殊变化就办不到了。
li{
list-style:decimal;
}
透过 content 和 counters 的搭配,我们就可以告别预设值的困扰,甚至可以在不使用清单 ul 和 li 的状况下,实现和清单一模一样的效果,举例来说,我们纯粹透过 div 模拟一个清单的长相(状态仍然必须是有父元素和子元素的概念),里面的样式 b 就等于是 ul,样式 a 就等于是 li:
<div class=”a”> 第一层
<div class=”b”>
<div class=”a”> 第二层
<div class=”b”>
<div class=”a”> 第三层 </div>
<div class=”a”> 第三层 </div>
<div class=”a”> 第三层 </div>
</div>
</div>
<div class=”a”> 第二层 </div>
<div class=”a”> 第二层 </div>
</div>
</div>
<div class=”a”> 第一层
<div class=”b”>
<div class=”a”> 第二层 </div>
<div class=”a”> 第二层 </div>
</div>
</div>
由于 b 的外层没有东西,所以一开始要把 body 和 b 都进行 counter reset 的动作,接着透过 counters 的使用,让计数器的数值可以一个接着一个放进去,如此一来就可以做到原本清单不容易实现的效果了。
counters 使用语法:counters(计数器名称,分隔字,list-style-type)
body, .b{
counter-reset:c;
}
.a::before{
content:counters(c, “.”) “:”;
counter-increment:c;
}
div{
margin-left:10px;
}
了解原理之后,透过 ::before 和 ::after 的交互应用,就可以做出颇具特色的列表效果。
body, .b{
counter-reset:c;
}
.a{
box-sizing:border-box;
position:relative;
line-height:40px;
}
.a .a{
padding-left:30px;
}
.a::after{
content:”;
box-sizing:border-box;
display:inline-block;
position:absolute;
z-index:-1;
top:0;
left:0;
width:100%;
height:40px;
margin-left:30px;
box-shadow:inset 0 2px #666;
background:#eee;
}
.a::before{
content:counter(c, upper-roman);
counter-increment:c;
display:inline-block;
width:30px;
height:40px;
background:#666;
color:#fff;
text-align:center;
margin-right:5px;
}