关于list-style-type项目符号你应该知道的事情

这篇文章发布于 2022年11月5日,星期六,23:13,归类于 CSS相关。 阅读 2141 次, 今日 1 次 一条评论

 

CSS list-style-type绿豆子

一、必须list-item水平元素

一段普通的有序列表 HTML 代码:

<ol>
  <li>项目1</li>
  <li>项目2</li>
  <li>项目3</li>
</ol>

此时前面就会显示1,2,3这样子的有序项目符号(实时渲染效果如下):

  1. 项目1
  2. 项目2
  3. 项目3

不知道大家有没有深入了解过项目符号生效的机制是什么?是哪个HTML元素生成的?渲染的CSS属性又是什么呢?

简单的现象背后往往藏着深入的知识。

首先,项目符号是由 <li> 元素生成的,生成的CSS是list-style-type,字面意思就是“列表样式类型”。

然后是机制,是这样的,对于HTML元素,要想有项目符号,除了使用list-style-type属性,还有一个前提条件,就是元素的 display 计算值必须是 list-item(<li> 标签缩写就是这两个单词)。

例如上面的li列表,我们如果改变第2个<li> 元素的display属性值,例如为flex,则前面的序号就会丢失,例如:

<ol>
  <li>项目1</li>
  <li style="display:flex;">项目2</li>
  <li>项目3</li>
</ol>

效果为:

  1. 项目1
  2. 项目2
  3. 项目3

此规则对于普通HTML元素同样适用,比方说下面有一个例子:

<p class="list-a">A-有点点吗?</p>
<p class="list-b">B-有点点吗?</p>
.list-a {
  list-style-type: disc;
}
.list-b {
  display: list-item;
  list-style-type: disc;
}

此时,只有第二行元素的前面才会有点点(位置在外部),截图如下:

B才有点

ol, ul例外

然而有两个元素是例外的,这两个元素虽然display计算值是block,但是设置list-style-type属性依然可以改变子<li>元素的项目符号类型,例如:

<ol style="list-style-type: disc;">
  <li>项目1</li>
  <li>项目2</li>
  <li>项目3</li>
</ol>

此时<ol>元素中的几个列表前面就不是阿拉伯数字,而是实心的点点了,实时渲染效果如下。

  1. 项目1
  2. 项目2
  3. 项目3

我将这种现象称之为伪继承特性,只有ol, ul元素才会这样,其他HTML元素并不会如此。

因此,对于CSS reset,就不要出现下面这样的代码了:

/* li 是多余的 */
ol, ul, li {
  list-style-type: none;
}

直接使用下面的代码进行CSS重置。

ol, ul {
  list-style-type: none;
}

二、支持多种属性值

list-style-type支持的关键字属性值非常的多,截图示意:

支持的关键字属性值

除了常见的圆点-disc,空心圆-circle,和实心方点-square,其余的关键字属性值都是有序符号,之所以有这么多,是因为世界上有很多语言,尤其那些使用者众多的语言,都会有一个对应的有序名称。

对于中文用户的我们而言,可能需要关注的是这几个名称,cjk-decimal或cjk-ideographic,cjk-heavenly-stem(天干)、cjk-earthly-branch(地支):

cjk是Chinese/japanese/korea的缩写,表示东亚语言体系

天干地支有序列表

字符串属性值

list-style-type还支持自定义的字符串属性值,所谓项目符号,例如使用❤这个符号作为项目符号,就会有emoji项目符号的效果。代码示意如下:

ol {
  list-style-type: '❤️';
}

实时效果如下:

  1. 项目1
  2. 项目2
  3. 项目3

支持多个字符,例如:

ol {
  list-style-type: '❤️👄';
}

实时效果如下:

  1. 项目1
  2. 项目2
  3. 项目3

字符串值的兼容性如下截图所示,所有现代浏览器均支持,基本上可以在项目中放心使用了。

字符串值

任意自定义

list-style-type还支持使用@counter-style规则自定义的项目符号列表。

例如可以自定义部分序号的字符内容:

自定义项目符号内容

自定义序号的前后缀等:

序号字符前后缀

@counter-style规则非常强大,一言以蔽之,就是凡是你能想到序号符号效果,@counter-style规则都能帮你实现。

其语法如下:

@counter-style counter-style-name {
    system: 计数系统
    symbols: 计数符号
    additive-symbols: 附加符号
    negative: 负数符号
    prefix: 前缀
    suffix: 后缀
    range: 范围
    pad: 补全
    speak-as: 如何阅读
    fallback: 备份计数规则
}

具体不展开介绍,有兴趣可以参见“CSS @counter-style规则详细介绍”一文。

目前,此特性在Chrome和Firefox下均可以自如使用,Safari还需要静待时日。

@counter-style兼容性

三、ol和type属性

HTML中的<ol>元素还支持一个名为type的html属性,可以指定有序列表的类型,支持[1, a, A, i, I]这五个值中的任意一个。

比方说有下面的例子:

<ol type="1">
  <li>第一条内容啊沙发啊
    <ol type="a">
      <li>第一条内容啊沙发啊
        <ol type="I">
          <li>第一条内容啊沙发啊
            <ol type="i">
              <li>第一条内容啊沙发啊</li>
              <li>鑫空间-鑫生活:这是第二项</li>
            </ol>
          </li>
          <li>zxx:这是第二项</li>
        </ol>
      </li>
      <li>zhangxinxu:这是第二项</li>
    </ol>
  </li>
  <li>张鑫旭:这是第二项</li>
</ol>

就可以看到各类有序符号效果。

注意:ol元素如果设置了list-style-type属性会无效,注意CSS reset的时候的保护,可以借助:not()伪类,

实时渲染效果如下(所有浏览器均支持,包括已去的IE浏览器):

  1. 第一条内容啊沙发啊
    1. 第一条内容啊沙发啊
      1. 第一条内容啊沙发啊
        1. 第一条内容啊沙发啊
        2. 鑫空间-鑫生活:这是第二项
      2. zxx:这是第二项
    2. zhangxinxu:这是第二项
  2. 张鑫旭:这是第二项

注意,type属性仅<ol>元素有效,对于<ul>元素是没有任何效果的。

除了 type 属性,<ol>元素还支持名为start的html属性,可以指定有序列表起始的序号值,例如:

<ol type="A" start="2">
  <li>项目1</li>
  <li>项目2</li>
  <li>项目3</li>
</ol>

可以看到序号是从B开始的,而不是A。

  1. 项目1
  2. 项目2
  3. 项目3

还支持一个value属性值指定序号的起始位置,不过这个属性是设置在LI元素上的,相比start属性的优势是可以分别指定,例如:

<ol type="A">
  <li value="2">项目1</li>
  <li>项目2</li>
  <li value="5">项目3</li>
</ol>

效果见下方,可见“项目3”前面的字母是E,而不是正常序号的D。

  1. 项目1
  2. 项目2
  3. 项目3

四、::marker伪元素

CSS ::marker伪元素是专门用来设置列表序号样式的,例如变成红色:

<ol>
  <li>项目zhang</li>
  <li>项目xin</li>
  <li>项目xu</li>
</ol>
li::marker {
  color: red;
}
  1. 项目zhang
  2. 项目xin
  3. 项目xu

::marker伪元素有个不足,就是只能设置与文本相关的CSS样式,例如字号,字体,颜色,字间距等属性,像是背景色,以及布局等都是不支持,如果有后面的需求,可以使用counter()计数器,本文后面会介绍。

内容替换

::marker伪元素还支持使用content属性自定义项目符号:

li::marker {
  content: '❤️';
}

此时,在非Safari浏览器会看到前面的序号是爱心么么哒~

  1. 项目zhang
  2. 项目xin
  3. 项目xu

此特性Safari浏览器并不支持(Safari16),因此实际开发,还是推荐使用list-style-type做序号字符的替换。

关于::marker伪元素更多的知识可以参见我之前这篇文章:“CSS ::marker伪元素简介”。

五、计数器中使用

CSS中的计数器非常强大,现在又有了@counter-style规则,简直就是天下无敌了。

关于CSS计数器,可以参见鄙人的这篇经典文章“CSS counter计数器(content目录序号自动递增)详解”。

通常用来模拟1,2,3这种自动递增的序号。

然后很多人都不知道,counter()函数和counters()函数(嵌套序列)还支持一个名为style的参数,如下所示:

counter(name, style)
counters(name, string, style)

这个style参数就是list-style-type属性能够支持的所有属性值,包括自定义的序号类型。

而CSS计数器是配合::before/::after伪元素实现的,相比::marker伪元素,::before::after伪元素支持几乎所有的CSS属性,也不需要display计算值是list-item,因此,适用场景非常广泛。

唯一的不足就是学习成本比较高,大多数的前端开发都需要好好看看文档,或者几篇优质文章才知道该怎么使用。

因此,我的建议是,简单效果::marker伪元素,如果是产品经理提出的高级需求(例如排行榜前三的序号是彩色的金银铜牌),则可以使用CSS计数器+@counter-style规则。

下面有个简单的案例,示意了下计数器counter()和@counter-style如何结合使用,HTML和CSS代码如下所示:

<div class="rank">
  <span>凯德·坎宁安(活塞)</span>
  <span>杰伦·格林(火箭)</span>
  <span>埃文·莫布里(骑士)</span>
  <span>斯科蒂·巴恩斯(猛龙)</span>
  <span>杰伦·萨格斯(魔术)</span>
</div>
.rank {
  display: grid;
  grid: auto / auto 1fr;
  gap: 5px;
  counter-reset: rank;
}
@counter-style nbaRank {
  system: additive;
  additive-symbols: 探花 3, 榜眼 2, 状元 1;
  range: 1 3;
  fallback: cjk-decimal;
}
.rank span {
  display: contents;
}
.rank span::before {
  counter-increment: rank;
  content: counter(rank, nbaRank);
  background-color: #333;
  color: #fff;
  padding:0 3px;
  border-radius: 3px;
  text-align: right;
}

此时的效果如下图所示:

效果截图

可以看到序号背后不仅有背景色,还有圆角,前三序号进行了特殊处理,然后布局还是grid布局。

眼见为实,您可以狠狠地点击这里:counter()计数器和@counter-style结合使用demo

六、结语

虽然现在业界讨论JS及其相关框架比较多,但实际上,CSS也是一直在不断发展,其速度某种程度上要比JS快多了,因为没有那么多的三校三审。

然而,由于 JS 能够做的事情太多了,因此CSS看起来就不那么重要了。

本文的内容就可以很好地解释,比方说要实现特殊的计数器效果,对于大多数开发者而言,直接 JS 一个循环,如果有特殊处理,例如前三,一个if语句就好了。

功能实现,效果也还行,至少能用,学习成本也低(就是简单的JS逻辑处理),不挺好的!

为何还要花那么多时间去学各种计数器语法,还有@counter-style规则,这玩意里面的参数数量比Vue都还多,怎么学?

就为了那么一点点的用户体验提升,却要让我花费如此多的心血,不划算,我不干,我不学了,谢谢,反正老板和用户对产品要求也就那样,流畅,能用就行,我的KPI也不会因为这个有所提升,能够让我快速干完活下班的技术才是好技术。

这就是现状,也是现实,在行业快速发展的阶段,这也是必然的,等Web互联网开始冷却,足够内圈,大家比拼内力的时候,说不定,这些对于产品更好,但是需要更多精力学习的东西,会更多地出现在舞台中。

最后,分享一段我认同的观点:

OK,就这些,哎呀,看起来一个简简单单的属性,深究起来居然也有这么多内容呢。

如果您觉得本文内容还不错,欢迎转发(如果有),点赞(如果有)和

(本篇完)

分享到:


发表评论(目前一条评论)

  1. XboxYan说道:

    可以预测一下吗,什么时候”Web互联网开始冷却“