1. 简介
本规范定义了 ::marker 伪元素、生成标记的 list-item 显示类型,以及用于控制标记放置和样式的若干属性。
它还定义了 计数器 (counters),这是一种特殊的数值对象,常用于生成标记的默认内容。
< style > li :: marker { content : "(" counter( list-item , lower-roman ) ")" ; } li { display : list-item ; } </ style > < ol > < li > This is the first item.< li > This is the second item.< li > This is the third item.</ ol >
它应产生类似于以下的效果
(i) This is the first item. (ii) This is the second item. (iii) This is the third item.
注意: 请注意,此示例在 HTML 中比通常需要的要繁琐得多,因为 UA 的默认样式表已经处理了大部分必要的样式。
通过后代选择器和子选择器,可以根据嵌套列表的深度指定不同的标记类型。
1.1. 值定义
本规范遵循 CSS 属性定义约定([CSS2]),使用 值定义语法([CSS-VALUES-3])。本规范未定义的值类型在 CSS Values & Units [CSS-VALUES-3] 中定义。与其他 CSS 模块的组合可能会扩展这些值类型的定义。
除了定义中列出的属性特定值外,本规范中定义的所有属性也都接受 CSS 全局关键字 作为其属性值。为了可读性,未明确重复列出。
2. 声明列表项
列表项 (list item) 是指任何将其 display 属性设置为 list-item 的元素。列表项会生成 ::marker 伪元素;其他元素则不会。此外,列表项会自动递增一个隐式的 list-item 计数器(参见 § 4.6 隐式 list-item 计数器)。
3. 标记 (Markers)
列表项 显示类型的定义特征是其 标记 (marker),即有助于表示列表中每个列表项开头的符号或序数。在 CSS 布局模型中,列表项 标记由与每个列表项相关联的标记框 (marker box)表示。此标记的内容可以通过列表项上的 list-style-type 和 list-style-image 属性进行控制,也可以通过为其 ::marker 伪元素分配属性来控制。
3.1. ::marker 伪元素
标记框由列表项的 ::marker 伪元素生成,作为列表项的第一个子元素,位于 ::before 伪元素之前(如果该元素上存在此伪元素)。其填充内容由 § 3.2 生成标记内容定义。
< style > p { margin-left : 12 em ; } p . note { display : list-item ; counter-increment : note-counter ; } p . note :: marker { content : "Note " counter( note - counter ) ":" ; } </ style > < p > This is the first paragraph in this document.< p class = "note" > This is a very short document.< p > This is the end.
它应渲染出类似于以下的效果
This is the first paragraph
in this document.
Note 1: This is a very short
document.
This is the end.
< style > p { margin-left : 8 em } /* Make space for counters */ li { list-style-type : lower-roman ; } li :: marker { color : blue ; font-weight : bold ; } </ style > < p > This is a long preceding paragraph ...< ol > < li > This is the first item.< li > This is the second item.< li > This is the third item.</ ol > < p > This is a long following paragraph ...
前面的文档应渲染出类似于以下的效果
This is a long preceding
paragraph ...
i. This is the first item.
ii. This is the second item.
iii. This is the third item.
This is a long following
paragraph ...
以前,设置标记样式的唯一方法是通过继承;用户必须在列表项上放置所需的标记样式,然后在列表项实际内容的包装元素上还原该样式。
标记框仅针对列表项存在:对于任何其他元素,::marker 伪元素的 content 属性必须计算为 none,这会抑制其创建。
3.1.1. 适用于 ::marker 的属性
所有属性都可以设置在 ::marker 伪元素上,并将具有 计算值;然而,实际上只有以下 CSS 属性适用于 标记框
- text-combine-upright, unicode-bidi, 和 direction 属性(参见 [CSS-WRITING-MODES-3])
- content 属性(参见下文 § 3.2 生成标记内容)
- 所有动画和过渡属性(参见 [CSS-ANIMATIONS-1] 和 [CSS-TRANSITIONS-1])
预期未来的规范将扩展此属性列表;但目前由于尚未完全定义外部标记框布局,因此仅允许使用这些属性。
当在级联的作者源 (author origin)中设置时,其他属性不得对标记框产生影响。UA 可以将此类属性视为不适用,或通过设置用户代理源 (user-agent origin) 的 !important 规则来强制执行其值。但是,适用于文本的可继承属性可以设置在 ::marker 伪元素上:这些属性将继承并作用于其文本内容。
- white-space, text-transform, letter-spacing (参见 [CSS-TEXT-3])
- 所有字体属性(参见 [CSS-FONTS-3] 及其后继版本)
- color 属性(参见 [CSS-COLOR-3])
UA 必须在默认样式表中添加以下规则
::marker, ::before::marker, ::after::marker {
unicode-bidi: isolate;
font-variant-numeric: tabular-nums;
white-space: pre;
text-transform: none;
}
注意: 虽然 ::marker 伪元素可以代表 ::before 或 ::after 伪元素的标记框,但复合选择器 ::marker(扩展为 *::marker [SELECTORS-4])不会选择这些标记——必须在选择器中显式指定作为伪元素的原始元素,例如 ::before::marker。
white-space: pre 的行为不完全正确;text-space-collapse: preserve-spaces + text-space-trim: discard-after 可能更接近此处所需的功能。请参阅 Issue 4448 和 Issue 4891 中的讨论。
3.2. 生成标记内容
标记框的内容由以下第一个为真的条件决定
- ::marker 本身的 content 不为 normal
- 标记框的内容由 content 属性定义,与 ::before 完全相同。
- 原始元素上的 list-style-image 定义了一个 标记图像
- 标记框包含一个代表指定标记图像的匿名行内替换元素,后跟一个由单个空格(U+0020 SPACE)组成的文本运行 (text run)。
- 原始元素上的 list-style-type 定义了一个 标记字符串
- 标记框包含一个由指定的标记字符串组成的文本运行。
- 否则
- 标记框没有任何内容,且 ::marker 不生成框。
此外,UA 可以将任何保留的强制换行符转换为空格或将其丢弃。
3.3. 图像标记:list-style-image 属性
| 名称 | list-style-image |
|---|---|
| 值 | <image> | none |
| 初始值 | none(无) |
| 应用于 | 列表项 |
| 可继承 | 是 |
| 百分比 | 不可用 |
| 计算值 | 关键字 none 或计算出的 <image> |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
指定标记图像,当其 content 为 normal 时,用于填充列表项的标记。其值如下
- <image>
- 如果 <image> 代表一个有效图像,则将元素的标记图像指定为该 <image>。否则,该元素没有标记图像。
- none(无)
- 该元素没有标记图像。
li{ list-style-image : url ( "http://www.example.com/ellipse.png" ) }
3.4. 文本标记:list-style-type 属性
| 名称 | list-style-type |
|---|---|
| 值 | <counter-style> | <string> | none |
| 初始值 | disc |
| 应用于 | 列表项 |
| 可继承 | 是 |
| 百分比 | 不可用 |
| 计算值 | 指定的值 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
指定标记字符串,当其 content 值为 normal 且没有标记图像时,用于填充列表项的标记。其值如下
- <counter-style>
- 指定元素的标记字符串为使用指定的 <counter-style> 表示的 list-item 计数器的值。
具体而言,标记字符串是使用指定的 <counter-style> 生成计数器表示 list-item 计数器值的结果,前缀为 <counter-style> 的 prefix,后缀为 <counter-style> 的 suffix。如果指定的 <counter-style> 不存在,则默认为 decimal。
- <string>
- 元素的标记字符串为指定的 <string>。
- none
- 该元素没有标记字符串。
ul{ list-style-type : "★" ; } /* Sets the marker to a "star" character */ p.note{ display : list-item; list-style-type : "Note: " ; list-style-position : inside; } /* Gives note paragraphs a marker consisting of the string "Note: " */ ol{ list-style-type : upper-roman; } /* Sets all ordered lists to use the upper-roman counter-style (defined in the Counter Styles specification [[CSS-COUNTER-STYLES]]) */ ul{ list-style-type : symbols ( cyclic'○' '●' ); } /* Sets all unordered list items to alternate between empty and filled circles for their markers. */ ul{ list-style-type : none; } /* Suppresses the marker entirely, unless list-style-image is specified with a valid image. */
3.5. 定位标记:list-style-position 属性
| 名称 | list-style-position |
|---|---|
| 值 | inside | outside |
| 初始值 | outside (外侧) |
| 应用于 | 列表项 |
| 可继承 | 是 |
| 百分比 | 不可用 |
| 计算值 | 关键字,但请参阅正文 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
此属性决定 ::marker 是作为行内元素渲染,还是定位在列表项的正外部。其值如下
- inside (内侧)
- 无特殊效果。(::marker 是位于列表项内容开头的行内元素。)
- outside (外侧)
- 如果列表项是一个块容器:标记框是一个块容器,并放置在主块框之外;然而,邻近浮动元素的列表项标记的位置未定义。CSS 未指定标记框的精确位置或其在绘制顺序中的位置,但确实要求将其放置在盒子的行内起始 (inline-start)侧,使用由 marker-side 指示的盒子书写模式 (writing mode)。标记框相对于主块框的边框是固定的,且不随主块框的内容滚动。如果元素的 overflow 不是 visible,UA 可能会隐藏标记。(此规定在未来可能会改变。)标记框的大小或内容可能会影响主块框的高度和/或其第一行框的高度,并在某些情况下可能导致创建新的行框;此交互也未定义。
或者,outside 可以将标记布局为前一个主行内框的兄弟节点。
<style>
ul.compact { list-style: inside; }
ul { list-style: outside; }
</style>
<ul class=compact>
<li>first "inside" list item comes first</li>
<li>second "inside" list item comes first</li>
</ul>
<hr>
<ul>
<li>first "outside" list item comes first</li>
<li>second "outside" list item comes first</li>
</ul>
上述示例可以格式化为
* first "inside" list item comes first * second "inside" list item comes second ======================== * first "outside" list item comes first * second "outside" list item comes second
3.6. 设置标记样式:list-style 简写属性
| 名称 | list-style |
|---|---|
| 值 | <'list-style-position'> || <'list-style-image'> || <'list-style-type'> |
| 初始值 | 见各个属性 |
| 应用于 | 列表项 |
| 可继承 | 见各个属性 |
| 百分比 | 见各个属性 |
| 计算值 | 见各个属性 |
| 动画类型 | 见各个属性 |
| 规范顺序 | 按语法 |
list-style 属性是一个简写符号,用于在样式表的同一位置设置 list-style-type、list-style-image 和 list-style-position 这三个属性。
ul{ list-style : upper-roman inside} /* Any UL */ ul ul{ list-style : circle outside} /* Any UL child of a UL */
在简写属性中使用 none 值可能会产生歧义,因为 none 是 list-style-image 和 list-style-type 属性的有效值。为了消除这种歧义,简写属性中的 none 值必须应用于尚未由简写属性设置的这两个属性中的任意一个。
list-style : none disc; /* Sets the image to "none" and the type to "disc". */ list-style: noneurl ( bullet.png ); /* Sets the image to "url(bullet.png)" and the type to "none". */ list-style: none; /* Sets both image and type to "none". */ list-style: none discurl ( bullet.png ); /* Syntax error */
注意: list-style-type 的 <counter-style> 值也会产生语法歧义。由于此类值最终是 <custom-ident> 值,因此适用 [CSS-VALUES-3] 中的解析规则。
li)上指定 list-style 信息,但应小心使用。考虑以下规则ol.alpha li{ list-style : lower-alpha; } ul li{ list-style : disc; }
上述做法不会按预期工作。如果你在 ol class=alpha 中嵌套了一个 ul,第一个规则的特指度 (specificity) 将使 ul 的列表项使用 lower-alpha 样式。
ol.alpha > li{ list-style : lower-alpha; } ul > li{ list-style : disc; }
这些按预期工作。
ol.alpha{ list-style : lower-alpha; } ul{ list-style : disc; }
这些更好,因为继承会将 list-style 值传递给列表项。
3.7. marker-side 属性
| 名称 | marker-side |
|---|---|
| 值 | match-self | match-parent |
| 初始值 | match-self |
| 应用于 | 列表项 |
| 可继承 | 是 |
| 百分比 | 不可用 |
| 计算值 | 指定关键字 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
marker-side 属性指定outside 标记框是根据列表项本身(即其原始元素)的方向性来定位,还是根据列表容器(即原始元素的父元素)的方向性来定位。在前一种情况下,标记的位置可能因列表中的不同项目而异,取决于为每个列表项单独分配的方向性;在后一种情况下,它们都将对齐在同一侧,由为整个列表分配的方向性决定。
- match-self
- 标记框使用 ::marker 的原始元素的方向性进行定位。
- match-parent
- 标记框使用 ::marker 的原始元素的父元素的方向性进行定位。
- 内带有不同“dir”属性的多个
- ),有时将所有标记对齐在同一侧会更有用,这样作者可以在该侧指定单一的“槽 (gutter)”,并确保所有标记都位于该槽中并且可见。
以下两个渲染示例均由相同的 HTML 生成,唯一的区别是列表上 marker-side 的值
< ul > < li > english one< li dir = rtl > OWT WERBEH< li > english three< li dir = rtl > RUOF WERBEH</ ul > match-self match-parent * english one OWT WERBEH * * english three RUOF WERBEH ** english one * OWT WERBEH * english three * RUOF WERBEH
为了使该顺序标点符号正确地位于标记内部,它还需要获取父元素的 direction 值。<https://github.com/w3c/csswg-drafts/issues/4202>
关于重命名关键字以及与 list-style-position 合并的问题均处于开放状态。
4. 使用计数器进行自动编号
一个 计数器 (counter) 是一种特殊的数值跟踪器,除其他用途外,还用于自动对 CSS 中的列表项进行编号。每个元素都有一组零个或多个计数器,它们以类似于继承属性值的方式通过文档树进行继承。计数器具有一个 名称 (name) 和 创建者 (creator)(用于识别计数器),以及一个整数 值 (value)。它们使用 计数器属性 counter-increment, counter-set 和 counter-reset 进行创建和操作,并与 counter() 和 counters() 函数符号 (functional notations) 一起使用。
计数器在 CSS 语法中使用 <counter-name> 类型进行引用,该类型将其名称表示为 <custom-ident>。<counter-name> 名称不能匹配关键字 none;作为 <counter-name>,此类标识符是无效的。
在给定元素上解析计数器值是一个多步骤过程
-
现有的计数器从前一个元素继承而来。
-
新的计数器被实例化 (counter-reset)。
-
计数器值被递增 (counter-increment)。
-
计数器值被显式设置 (counter-set)。
-
计数器值被使用 (counter()/counters())。
UA 可能对计数器的最大值或最小值有实现相关的限制。如果计数器的重置、设置或递增会导致值超出该范围,则该值必须被钳制在该范围内。
4.1. 创建计数器:counter-reset 属性
| 名称 | counter-reset |
|---|---|
| 值 | [ <counter-name> <integer>? ]+ | none |
| 初始值 | none(无) |
| 应用于 | 所有元素 |
| 可继承 | 否 |
| 百分比 | 不可用 |
| 计算值 | 关键字 none 或一个列表,其中每一项是一个与整数配对的标识符 |
| 规范顺序 | 按语法 |
| 动画类型 | 按计算值类型 |
用户代理应在所有媒体(包括非视觉媒体)上支持此属性。
counter-reset 属性在元素上实例化新的计数器,并将它们设置为指定的整数值。其值定义如下
- none(无)
- 此元素不创建任何新计数器。
- <counter-name> <integer>?
- 实例化一个给定 <counter-name> 的计数器,起始值为给定的 <integer>,默认为 0。
h1{ counter-reset : section-1 } h1{ counter-reset : imagenum99 }
将仅重置 imagenum。要重置两个计数器,必须将它们一起指定
H1{ counter-reset : section-1 imagenum99 }
同样的原则也适用于 counter-set 和 counter-increment 属性。请参阅 [css-cascade-4]。
如果属性值中出现多个相同的 <counter-name>,仅最后一个会被采纳。
4.2. 操作计数器值:counter-increment 和 counter-set 属性
| 名称 | counter-increment |
|---|---|
| 值 | [ <counter-name> <integer>? ]+ | none |
| 初始值 | none(无) |
| 应用于 | 所有元素 |
| 可继承 | 否 |
| 百分比 | 不可用 |
| 计算值 | 关键字 none 或一个列表,其中每一项是一个与整数配对的标识符 |
| 规范顺序 | 按语法 |
| 动画类型 | 按计算值类型 |
用户代理应在所有媒体(包括非视觉媒体)上支持此属性。
| 名称 | counter-set |
|---|---|
| 值 | [ <counter-name> <integer>? ]+ | none |
| 初始值 | none(无) |
| 应用于 | 所有元素 |
| 可继承 | 否 |
| 百分比 | 不可用 |
| 计算值 | 关键字 none 或一个列表,其中每一项是一个与整数配对的标识符 |
| 规范顺序 | 按语法 |
| 动画类型 | 按计算值类型 |
用户代理应在所有媒体(包括非视觉媒体)上支持此属性。
counter-increment 和 counter-set 属性操作现有计数器的值。它们仅在元素上尚不存在给定名称的计数器时才会实例化新计数器。其值定义如下
- none
- 此元素不更改任何计数器的值。
- <counter-name> <integer>?
- 设置(对于 counter-set)或递增(对于 counter-increment)元素上命名计数器的值,增量/设定为指定的 <integer>。如果省略 <integer>,则默认为 1(对于 counter-increment)或 0(对于 counter-set)。
如果元素上当前不存在给定名称的计数器,该元素在设置或递增其值之前,会实例化一个给定名称且起始值为 0 的新计数器。
以下示例展示了如何使用 “Chapter 1”、 “1.1”、 “1.2” 等方式为章节与小节编号。
h1 : :before{ content : "Chapter " counter ( chapter) ". " ; counter-increment : chapter; /* Add 1 to chapter */ counter-reset: section; /* Set section to 0 */ } h2::before{ content : counter ( chapter) "." counter ( section) " " ; counter-increment : section; }
如果属性值中出现多个相同的 <counter-name>,则它们会按顺序全部处理。因此递增会复合,但仅最后一个设定值生效。
4.3. 嵌套计数器与作用域
计数器是“自嵌套”的;在一个从其父元素继承了同名计数器的元素上实例化一个新计数器,会创建一个同名的新计数器,嵌套在现有计数器内部。这对于 HTML 中的列表等情况很重要,因为列表可以嵌套在任意深度的列表中:为每一层定义唯一命名的计数器是不可能的。counter() 函数仅检索元素上给定名称的最内层计数器,而 counters() 函数则使用所有包含该元素的给定名称的计数器。
因此,计数器的 作用域 (scope) 从文档中第一个实例化该计数器的元素开始,并包括该元素的后代及其后续兄弟元素及其后代。但是,它不包括由该元素后续兄弟元素上的 counter-reset 创建的同名计数器的作用域中的任何元素,从而允许此类显式计数器实例化掩盖那些较早的兄弟元素。
请参阅 § 4.4 创建与继承计数器,了解管辖计数器作用域及其值的确切规则。
ol{ counter-reset : item} li{ display : block} li::before{ content : counter ( item) ". " ; counter-increment : item}
在此示例中,ol 将创建一个计数器,并且该 ol 的所有子元素都将引用该计数器。
如果我们用 itemn 表示 item 计数器的第 n 个实例,那么以下 HTML 片段将使用所指示的计数器。
<ol> 创建 item0,设置为 0<li> item0 递增为 1<li> item0 递增为 2<ol> 创建 item1,设置为 0,嵌套在 item0 中<li> item1 递增为 1<li> item1 递增为 2<li> item1 递增为 3<ol> 创建 item2,设置为 0,嵌套在 item1 中<li> item2 递增为 1</ol>
<li> item1 递增为 4<ol> 创建 item3,设置为 0,嵌套在 item1 中<li> item3 递增为 1</ol>
<li> item1 递增为 5</ol>
<li> item0 递增为 3<li> item0 递增为 4</ol>
<ol> 创建 item4,设置为 0<li> item4 递增为 1<li> item4 递增为 2</ol>
4.4. 创建与继承计数器
文档中的每个元素或伪元素在其作用域内都有一组(可能为空)计数器,要么通过从另一个元素继承,要么通过直接在元素上进行实例化。这些计数器表示为 CSS 计数器集合 (CSS counters set),这是一个 集合,其值均为 元组 (tuple):一个 字符串(代表计数器的名称)、一个元素(代表计数器的创建者)以及一个整数(代表计数器的值)。该集合中给定名称的最新计数器代表该名称的最内层计数器。
4.4.1. 继承计数器
-
令 element counters(表示 element 自身的 CSS 计数器集合)为 element 父元素的 CSS 计数器集合的副本。
-
令 sibling counters 为 element 前一个兄弟元素(如果有)的 CSS 计数器集合,否则为一个空的 CSS 计数器集合。
对于 sibling counters 中的每个 counter,如果 element counters 尚不包含名称相同的计数器,则将 counter 的副本追加到 element counters 中。
-
令 value source 为在树序中紧邻 element 之前的元素的 CSS 计数器集合。
对于 value source 中的每个 source counter,如果 element counters 包含一个名称和创建者相同的计数器,则将该计数器的值设置为 source counter 的值。
<ul style='counter-reset: example 0;'>
<li id='foo' style='counter-increment: example;'>
foo
<div id='bar' style='counter-increment: example;'>bar</div>
</li>
<li id='baz'>
baz
</li>
</ul>
回想一下,树序将文档树转换为有序列表,其中元素出现在其子元素之前,而子元素出现在其下一个兄弟元素之前。换句话说,对于像 HTML 这样的语言,它是解析器在读取文档时遇到开始标签的顺序。
在这里,ul 元素建立了一个名为 example 的新计数器,并将其值设置为 0。作为 ul 的第一个子元素,#foo 元素继承了此计数器。其父元素也是其在树序中紧邻的前一个元素,因此它随之继承了值 0,然后立即将该值递增为 1。
#bar 元素也是如此。它从 #foo 继承了 example 计数器,同时也从其继承了值 1 并将其递增为 2。
然而,#baz 元素略有不同。它从其前一个兄弟元素 #foo 继承了 example 计数器。但是,它并没有随计数器一起从 #foo 继承值 1,而是从树序中的前一个元素 #bar 继承了值 2。
这种行为允许在整个文档中使用单个计数器,持续递增,而作者无需担心文档的嵌套结构。
注意: 计数器继承与常规 CSS 继承一样,在 [DOM] 上下文中的“扁平化元素树”上操作。
4.4.2. 实例化计数器
4.5. 不生成框的元素中的计数器
不生成框的元素(例如,display 设置为 none 的元素,或者 content 设置为 none 的伪元素)不能设置、重置或递增计数器。计数器属性在此类元素上仍然有效,但它们必须不产生任何影响。
h2{ counter-increment : count2; } h2.secret{ display : none; }
注意: 其他“隐藏”元素的方法,例如将 visibility 设置为 ,仍然会导致元素生成框,因此此处不予排除。
是否替换元素的后代(例如 HTML option 或 SVG rect)可以设置、重置或递增计数器尚不明确。
注意: 由于不同实现间缺乏互操作性,替换元素后代的行为目前未定义。
4.6. 隐式 list-item 计数器
除了作者在样式中编写的任何显式定义的计数器外,列表项还会自动递增一个特殊的 list-item 计数器,该计数器用于在列表项上生成默认的标记字符串(参见 list-style-type)。
具体而言,除非 counter-increment 属性显式为 list-item 计数器指定了不同的增量,否则它必须在每个列表项上递增 1,同时在计数器正常递增时递增(完全就像列表项的 counter-increment 值被追加了 list-item 1 一样,包括副作用,例如可能实例化一个新的计数器等)。这不会影响 counter-increment 的指定值或计算值。
然而,由于如果 列表项 的 counter-increment 显式提到了 list-item 计数器,则自动的 list-item 递增不会发生,因此 li { counter-increment: list-item 2; } 会按规定将 list-item 增加 2,而不是像无条件追加 list-item 1 那样增加 3。
这也允许通过显式覆盖来关闭自动的 list-item 计数器递增,例如 counter-increment: list-item 0;。
在所有其他方面,list-item 计数器 的行为与其他任何 计数器 相同,并且可以被作者使用和操作,以调整 列表项 样式或用于其他目的。
在以下示例中,列表被修改为以二为单位进行计数
ol.evens > li { counter-increment: list-item 2; }
一个三项列表将被渲染为
2. First Item 4. Second Item 6. Third Item
用户代理 (UA) 和宿主语言应确保在用户代理样式表和表现提示样式映射中设置列表项样式时,默认的 list-item 计数器值反映了宿主语言语义所决定的潜在数值。参见,例如 附录 A:HTML 示例样式表。
ol > li::marker { content: counters(list-item,'.') '.'; }
使用此规则的嵌套列表将被渲染为
1. First top-level item
5. Second top-level item, value=5
5.3. First second-level item, list start=3
5.4. Second second-level item, list start=3
5.4.4. First third-level item in reversed list
5.4.3. Second third-level item in reversed list
5.4.2. Third third-level item in reversed list
5.4.1. Fourth third-level item in reversed list
5.5. Third second-level item, list start=3
6. Third top-level item
给定如下标记
<ol>
<li>First top-level item
<li value=5>Second top-level item, value=5
<ol start=3>
<li>First second-level item, list start=3
<li>Second second-level item, list start=3
<ol reversed>
<li>First third-level item in reversed list
<li>Second third-level item in reversed list
<li>Third third-level item in reversed list
<li>Fourth third-level item in reversed list
</ol>
</ol>
<li>Third second-level item, list start=3
<li>Third top-level item
</ol>
4.7. 输出计数器:counter() 和 counters() 函数
计数器 本身没有可见效果,但其值可以与 counter() 和 counters() 函数一起使用,这些函数的 使用值 (used values) 将计数器值表示为字符串或图像。它们定义如下
<counter> = <counter()> | <counters()> counter() = counter( <counter-name>, <counter-style>? ) counters() = counters( <counter-name>, <string>, <counter-style>? )
其中 <counter-style> 指定了 计数器样式,用于 生成 命名计数器的表示形式,如 [css-counter-styles-3] 中所定义,并且
- counter()
- 表示元素 CSS 计数器集合 中名为 <counter-name> 的 最内层 计数器 的值,使用名为 <counter-style> 的 计数器样式。
- counters()
- 表示元素 CSS 计数器集合 中所有名为 <counter-name> 的 计数器 的值,使用名为 <counter-style> 的 计数器样式,按从最外层到 最内层 的顺序排序,并由指定的 <string> 连接。
在这两种情况下,如果省略 <counter-style> 参数,则默认为 decimal。
如果在某个元素上使用了 counter() 或 counters(),但该元素上不存在名为 <counter-name> 的 计数器,则首先 实例化 一个起始值为 0 的计数器。
H1::before { content: counter(chno, upper-latin) ". " }
/* Generates headings like "A. A History of Discontent" */
H2::before { content: counter(section, upper-roman) " - " }
/* Generates headings like "II - The Discontent Part" */
BLOCKQUOTE::after { content: " [" counter(bq, decimal) "]" }
/* Generates blockquotes that end like "... [3]" */
DIV.note::before { content: counter(notecntr, disc) " " }
/* Simply generates a bullet before every div.note */
P::before { content: counter(p, none) }
/* inserts nothing */
< ul > < li > one</ li > < li > two< ul > < li > nested one</ li > < li > nested two</ li > </ ul > </ li > < li > three</ li > </ ul > < style > li :: marker { content : '(' counters ( list-item , '.' ) ') ' ; } </ style >
前面的文档应渲染出类似于以下的效果
(1) one (2) two (2.1) nested one (2.2) nested two (3) three
< h1 > First H1</ h1 > ...< h2 > First H2 in H1</ h2 > ...< h2 > Second H2 in H1</ h2 > ...< h3 > First H3 in H2</ h3 > ...< h1 > Second H1</ h1 > ...< h2 > First H2 in H1</ h2 > ...< style > body { counter-reset : h1 h2 h3 ; } h1 { counter-increment : h1 ; counter-reset : h2 h3 ;} h2 { counter-increment : h2 ; counter-reset : h3 ; } h3 { counter-increment : h3 ; } h1 :: before { content : counter( h1 , upper-alpha ) ' ' ; } h2 :: before { content : counter( h1 , upper-alpha ) '.' counter( h2 , decimal ) ' ' ; } h3 :: before { content : counter( h1 , upper-alpha ) '.' counter( h2 , decimal ) '.' counter( h3 , lower-roman ) ' ' ; } </ style >
前面的文档应渲染出类似于以下的效果
A First H1 ... A.1 First H2 in H1 ... A.2 Second H2 in H1 ... A.2.i First H3 in H2 ... B Second H1 ... B.1 First H2 in H1 ...
其他用例涉及带有相互之间略有不同的变换(transforms)的嵌套或兄弟元素。目前,您必须使用预处理器以合理的方式执行此操作,但计数器将使其在“普通”CSS 中良好运行。
(您目前可以通过使用 自定义属性 和堆叠嵌套的 calc() 来构建嵌套情况下的连续值,但这稍微有点笨拙,并且不适用于兄弟元素。)
建议添加一个 counter-value(<counter-name>) 函数,它返回命名计数器的值作为整数,而不是返回字符串。
参见 问题 1026。
附录 A:HTML 示例样式表
本节仅供参考,不具规范性。[HTML] 渲染 章节定义了适用于 HTML 列表的规范默认属性;提供此示例样式表是为了说明使用熟悉的标记惯例的 CSS 特性。
关于如何在 CSS 中支持 ol[reversed] 列表编号的讨论正在进行中。参见,例如 问题 4181。
/* Set up list items */
li {
display: list-item; /* implies 'counter-increment: list-item' */
}
/* Set up ol and ul so that they scope the list-item counter */
ol, ul {
counter-reset: list-item;
}
/* Default list style types for lists */
ol { list-style-type: decimal; }
ul { list-style-type: toggle(disc, circle, square); }
/* The type attribute on ol and ul elements */
ul[type="disc"] { list-style-type: disc; }
ul[type="circle"] { list-style-type: circle; }
ul[type="square"] { list-style-type: square; }
ol[type="1"] { list-style-type: decimal; }
ol[type="a"] { list-style-type: lower-alpha; }
ol[type="A"] { list-style-type: upper-alpha; }
ol[type="i"] { list-style-type: lower-roman; }
ol[type="I"] { list-style-type: upper-roman; }
/* The start attribute on ol elements */
ol[start] {
counter-reset: list-item calc(attr(start integer, 1) - 1);
}
/* The value attribute on li elements */
li[value] {
counter-set: list-item attr(value integer, 1);
}
/* Box Model Rules */
ol, ul {
display: block;
margin-block: 1em;
marker-side: match-parent;
padding-inline-start: 40px;
}
ol ol, ol ul, ul ul, ul ol {
margin-block: 0;
}
li {
text-align: match-parent;
}
致谢
本规范的实现得益于 Aharon Lanin, Arron Eicholz, Brad Kemper, David Baron, Emilio Cobos Álvarez, Mats Palmgren, Oriol Brufau, Simon Sapin, Xidorn Quan 的投入
变更
本节记录了自上次发布以来的变更。
自 2020 年 7 月 9 日工作草案 (WD) 以来的变更
- 澄清了适用于 ::marker 框与适用于 ::marker 框内容的属性。(问题 4568)
- 将 text-transform: none 添加到 ::marker 的 UA 默认样式表中。(问题 4206)
- 将计数器继承改为优先从父级获取,仅在它是新计数器时才从兄弟级获取。(问题 5477)
自 2019 年 8 月 17 日工作草案 (WD) 以来的变更
- 规定 outside 列表标记 块容器 (block containers)。(它们的 外部显示类型 仍未定义。)
- 从 [CSS-PSEUDO-4] 中引入了适用于 ::marker 的属性列表,并添加了动画、过渡和 white-space。
- 将 white-space: pre 添加到 ::marker 的 UA 默认样式表中。(问题 4448)但请注意,标记框的确切空白处理行为仍在制定中。
自 2019 年 4 月 25 日工作草案 (WD) 以来的变更
- 重写了 § 4 计数器自动编号 章节,以获得更好的精确度、编辑清晰度,并与 CSS2 同步。
自 2014 年 3 月 20 日工作草案 (WD) 以来的变更
- 在计数器名称中始终使用 <custom-ident>。
- 删除了 position: marker(标记定位现在大部分未定义,如 CSS2 中所述)。
- 完全重写了关于标记的章节,以使其更加紧凑、符合当前期望并进行编辑改进。
- 将 list-item 计数器定义放入其自己的章节,添加了示例,并做了一些澄清。
- 重命名了 marker-side 的值,以符合框/文本对齐的惯例。
- 定义了 counter-set 在 counter-increment 之后而非之前应用。(问题 3810)
- 确立了 list-style 序列化的规范顺序,将 <'list-style-type'> 放在最后。(问题 2624)
与 CSS Level 2 的变更
如引言部分所述,与 CSS2.1 相比,此模块有显著变化。
- 引入了 ::marker 伪元素,以允许直接对列表标记进行样式设置。
- list-style-type 现在接受 <string> 以及来自 [css-counter-styles-3] 的扩展 <counter-style> 值。
- 引入了 list-item 预定义计数器标识符。
- 添加了 counter-set 属性。
- 允许 行内级 (inline-level) 列表项,如 [CSS-DISPLAY-3] 中所引入。