2

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

 1 year ago
source link: https://www.zhangxinxu.com/wordpress/2022/11/about-css-list-style-type-item/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10607 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

CSS list-style-type绿豆子

一、必须list-item水平元素

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

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

此时前面就会显示1,2,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>

此规则对于普通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>元素中的几个列表前面就不是阿拉伯数字,而是实心的点点了,实时渲染效果如下。

我将这种现象称之为伪继承特性,只有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: '❤️';
}

实时效果如下:

支持多个字符,例如:

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

实时效果如下:

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

字符串值

任意自定义

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。

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

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

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

四、::marker伪元素

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

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

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

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

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

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

  1. 项目zhang
  2. 项目xin

此特性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互联网开始冷却,足够内圈,大家比拼内力的时候,说不定,这些对于产品更好,但是需要更多精力学习的东西,会更多地出现在舞台中。

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

2022-11-05_225317.png

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

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

1f618.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK