CSS生成内容模块 第3级

W3C 工作草案

关于本文档的更多详情
本版本:
https://www.w3.org/TR/2025/WD-css-content-3-20251204/
最新发布版本:
https://www.w3.org/TR/css-content-3/
编辑草稿:
https://drafts.csswg.org/css-content-3/
历史版本:
历史记录:
https://www.w3.org/standards/history/css-content-3/
反馈:
CSSWG问题仓库
规范内反馈
编辑者:
Elika J. Etemad / fantasai (苹果,前Mozilla)
(BFO)
前编辑者:
(阿歇特出版集团)
(Opera Software)
(谷歌)
建议为本规范编辑内容:
GitHub 编辑器
测试套件:
https://wpt.fyi/results/css/css-content/

摘要

本CSS3模块描述了如何在文档中插入内容。

CSS是一种描述结构化文档(如HTML和XML)在屏幕、纸张等介质上呈现方式的语言。

本文档状态

本节描述了本文件在发布时的状态。当前W3C出版物列表及本技术报告的最新修订可在 W3C标准与草案索引 找到。

本文件由 CSS工作组工作草案方式发布,遵循 推荐规范流程。 工作草案的发布不表示 W3C及其成员的认可。

这是一个草稿文件,可能随时被更新、替换或废止为其他文档。不应将本文件作为正式引用,仅作为进行中的工作。

请通过 在GitHub提交问题(推荐)反馈意见,标题中请包含规范代码 "css-content",例如: “[css-content] …意见摘要…”。所有问题和评论都会被存档。 另外,也可以发送反馈到(已存档)公开邮件列表 www-style@w3.org

本文件受 2025年8月18日W3C流程文件管辖。

本文件由遵循 W3C专利政策的工作组制作。 W3C维护了相关专利公开列表, 该页面还包含披露专利的说明。如个人实际知晓某项专利且确信其包含必要权利要求, 必须根据W3C专利政策第6节披露相关信息。

这是非常初步的草案,不适合用于开发实现。

引言

作者有时希望用户代理呈现不来自文档树的内容。 一个熟悉的例子是带编号的标题; 作者不想显式地为数字添加标记, 而是希望用户代理自动生成它们。 使用计数器和标记可以实现这些效果。

h1::before { content: counter(section) ": "; }

类似地,作者可能希望用户代理在图注前插入“Figure”一词, 或在第七章标题之前的某一行插入“Chapter 7”。

chapter { counter-increment: chapter; }
chapter > title::before { content: "Chapter " counter(chapter) "\A"; }

另一个常见效果是用图片或其他多媒体内容替换元素。 由于并非所有用户代理都支持所有多媒体格式, 可能需要提供回退方案。

/* Replace <logo> elements with the site’s logo, using a format
 * supported by the UA */
logo { content: url(logo.mov), url(logo.mng), url(logo.png), none; }

/* Replace <figure> elements with the referenced document, or,
 * failing that, with either the contents of the alt attribute or the
 * contents of the element itself if there is no alt attribute */
figure[alt] { content: attr(href url), attr(alt); }
figure:not([alt]) { content: attr(href url), contents; }
测试

生成内容的一般测试


值定义

本规范遵循来自 CSS 属性定义约定 的约定,来源于 [CSS2],并使用来自 值定义语法 的语法,该语法来自 [CSS-VALUES-3]。 本规范中未定义的值类型在 CSS 值与单位 [CSS-VALUES-3] 中定义。 与其他 CSS 模块的组合可能会扩展这些值类型的定义。

除了定义中列出的特定属性值之外, 本规范中定义的所有属性 也接受 CSS 全局关键字 作为其属性值。 为了可读性,这些关键字未在此重复列出。

1. 插入与替换内容:content 属性

名称: content
值: normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> | <attr()> ]+ ]?
初始值: normal
适用对象: 所有元素、遵循树结构的伪元素和页面页边距框
是否继承:
百分比: 不适用
计算值: 见下文说明
规范顺序: 按语法
动画类型: 离散
测试

期望用户代理在所有媒介上支持此属性,包括非视觉媒介。

content 属性决定在元素或 伪元素 内呈现的内容。

对于元素,它只有一个用途: 指定元素按正常方式呈现, 或用图像替换元素 (并可能提供一些相关的“替代文本”)。

对于 伪元素 和页边距框, 它更强大。 它控制元素是否呈现, 可以用图像替换元素, 或用任意内联内容 (文本和图像)替换它。

normal
对于元素或页面页边距框,这会计算为 contents

对于 ::before::after,这会计算为 none

对于 ::marker::placeholder, 和 ::file-selector-button, 这会计算为自身(normal)。

none
在元素上,这表现得像 normal

伪元素 上,它抑制伪元素的创建, 就像它具有 display: none 一样。

在任何情况下,这都不会阻止以该元素或伪元素为 起始元素 的任何伪元素被生成。

<content-replacement>
等同于:
<image>

使该元素或 伪元素 成为一个 替换元素, 由指定的 <image> 填充。 它的正常内容被抑制且不生成盒子, 就好像它们是 display: none 一样。

如果 <image> 表示一个 无效图像, 则必须将其视为表示一个自然宽度和高度均为零、 且填充为透明黑色的图像。

上述 无效图像 的行为似乎是 Chrome 当前的做法。 这可以接受吗? 是否有更好的行为我们可以/应该采用?

注: 替换元素使用与普通元素不同的布局规则。 (实际上,它会等同于 HTML 中的 img 元素。)

注: 替换元素没有 ::before::after 伪元素content 属性替换它们的全部内容。

该值在历史上在 <content-list> 上被视为 ::before::after 的行为。 大概对此存在 Web 兼容性的要求,因此这些伪元素可能需要例外。 [Issue #2889]

<content-list>
用一个或多个匿名内联盒子替换元素的内容, 对应于指定的值, 按指定顺序排列。 它的正常内容被抑制且不生成盒子, 就好像它们是 display: none 一样。

每个值为元素的内容贡献一个内联盒子。 对于 <image>,这是一个匿名的内联替换元素; 对于其他值,它是一个匿名的内联文本运行。

如果 <image> 表示一个 无效图像, 用户代理必须执行以下操作之一:

  • “跳过”该 <image>,为其生成空内容。

  • 显示某种表示图像无法显示的指示,代替该 <image>, 例如“损坏图像”图标。

本规范有意不规定用户代理必须使用哪种行为, 但必须在两者中选择其一并保持一致。

注: 如果 <content-list> 的值是单一的 <image>, 它必须被解释为 <content-replacement>

测试
/ [ <string> | <counter> | <attr()> ]+
指定元素的“替代文本”。 详情见 § 1.2 可访问性的替代文本。 如果省略, 元素没有“替代文本”。
为了在不支持计数器的浏览器中正确地在“替代文本”中使用 <counter>, 应该对 content 属性指定两次。 首先,提供一个在“替代文本”中不使用计数器的回退。 其次,在“替代文本”中使用计数器。
::before {
  content: "Chapter" counter(chapter);
  content: "Chapter" counter(chapter) / "Chapter" counter(chapter);
}

是否应将 contents 关键字替换为 content()

1.1. 生成内容的可访问性

生成的内容应当可被搜索、选择,并可用于辅助技术。 content 属性适用于语音, 并且生成内容必须支持语音输出。 [CSS3-SPEECH]

开始针对CSS编写辅助访问映射(AAM)。

1.2. 无障碍的替代文本

用于视觉媒介的内容有时需要为语音输出或其他非视觉媒介提供替代文本。 因此,content 属性允许在最后的 <content-list> 后,通过斜杠(/)指定替代文本。 如果提供了替代文本, 则必须用于语音输出。

这样做可以使纯装饰性文本在语音输出中省略 (通过提供空字符串作为替代文本), 同时让作者为图片、图标或文本符号提供更易读的替代内容。

这里 content 属性为图片,因此需要为 alt 值指定替代文本。
.new::before {
 content: url(./img/star.png) / "New!";
  /* 或 DOM中的本地化属性:attr("data-alt") */
}
如果 伪元素 纯粹是装饰性的且其功能已在其他地方体现,则将 alt 设置为空字符串可避免朗读该装饰性元素。本例中的 ARIA 属性会被朗读为“collapsed”。如果没有空字符串的 alt 值,则内容也会被朗读为“黑色右指针”。
.expandable::before {
 content: "\25BA" / "";
/* 也叫 ► */
 /* DOM里已有 aria-expanded="false",
   所以该伪元素只是装饰用途 */
}

2. 生成内容值:<content-list> 类型

<content-list> 值用于 content,以用一个或多个匿名内联盒子填充元素, 包括图片、字符串、计数器的值和元素的文本值。 本节将列举这些可能性。

<content-list> 的语法定义如下:

<content-list> = [ <string> | <image> | <attr()> | contents | <quote> | <leader()> | <target> | <string()> | <content()> | <counter> ]+

2.1. 基本字符串:<string><attr()>

<string>
代表一个匿名内联盒,其内容为指定文本。

注: 字符串内的 空白符 跟文本一样处理, 并由 [CSS-TEXT-3] 及其他属性控制。 特别地,空白符字符可能被折叠, 即使跨多个字符串也如此, 例如 content: "First " " Second";, 默认渲染为 "First Second" (两个单词之间只有一个可见空格)。

<attr()>
attr() 函数表示字符串为指定属性的值。 参数为 CSS限定名qname) 表示属性名及命名空间(如有)。 详见 [CSS3-NAMESPACE]

注: 参见 属性选择器, 没有显式命名空间的属性名不关联任何默认命名空间。

2.2. 二维图片:<image>

<image>
表示一个匿名内联替换元素, 其中填充指定的 <image>

如果 <image> 表示一个 无效图像, 则该值不呈现任何内容。 (不会向元素添加内联内容,等同于跳过此值。)

CSS2.1 明确允许UA在图片无效时替换为损坏图片图标, 但没有浏览器这样做。 这样的删改可以接受吗?

2.3. 元素内容:contents 关键字

contents
元素的后代。 由于每个元素只能使用一次 (比如其中有一个是插件或表单控件,就无法复制其子级), 处理方式如下:
设置在元素上时:

总是有效。 注意这也是默认值, 因为 content 的初始值为 normalnormal 在元素上会计算为 contents

设置在元素的其他 伪元素 上时:

需要确保没被设置在“前面”的伪元素上,判断顺序为深度优先:

  1. 元素自身

  2. ::before

  3. ::after

在伪元素上是否应该表现为空字符串?

如果已经使用,则评估为没有内容(如 none)。 仅检查实际生成的伪元素。

下面这个例子:
foo { content: normal; }  /* 这是初始值 */
foo::after { content: contents; }

……该元素的 content 属性会计算为 contents,而 ::after 伪元素则没有内容 (等同于 none) 所以不会显示。

foo { content: none; }
foo::after { content: contents; }

但在这个例子中,::after 伪元素会包含 foo 元素的内容。

欢迎补充通过伪元素抑制元素内容并使用内容的实际案例。

注: 虽然在单个 content 属性中重复包含 contents 没什么用, 但这不是解析错误。 第二次只是不产生效果, 因为已经被使用了。 在 ::marker 伪元素上也不是解析错误, 只是在渲染阶段会被视为 none

需不需要这里 marker 伪元素相关说明?还是仅是旧规范遗留?

2.4. 引号

quotes 属性用于定义元素的 引号系统, 结合 content 属性的各类 *-quote 值, 可以作为生成内容插入对应的引号标记, 可自动插入开头和结尾的引号, 例如应用于 HTML q 元素。

2.4.1. 引号系统:quotes 属性

名称: quotes
值: auto | none | match-parent | [ <string> <string> ]+
初始值: auto
适用对象: 所有元素
是否继承:
百分比: 不适用
计算值: 关键字 none、关键字 automatch-parent,或一个列表,每项都是一对字符串值
规范顺序: 按语法
动画类型: 离散
测试

期望用户代理在所有媒介(包括非视觉媒介)都支持该属性。

该属性指定元素的引号系统, 用于定义 content 属性中的 open-quoteclose-quote 值的行为。 参见 § 2.4.2 插入引号:*-quote关键字。 其各个取值含义如下:

none
open-quoteclose-quote (在 content 属性中)不会生成任何引号, 等同于分别为 no-open-quoteno-close-quote
auto
用户代理会根据父级(若无父级则根据元素本身)的内容语言, 自动选择合适的引号系统

注: Unicode CLDR 数据库 [CLDR]提供了这些合适引号的信息。 用户代理也可以使用其他信息来源, 特别是因为排版习惯有时会变化; 但建议将改进提交给Unicode, 以便整个生态系统受益。

match-parent
指定与父元素相同的引号系统。 通常等价于继承父元素的计算值, 唯一不同的是auto时会用父元素用过的内容语言解析。

这里有两种做法,目前规范的是后者: a) 该值最终计算为相关字符串值,并继承该值 b) 该值实际上继承为关键字+语言代码, 即 auto,但附带该语言。

[ <string> <string> ]+
引号系统由指定的一组引号对(开、闭引号)定义。 第一对表示最外层的引用, 第二对表示下一级嵌套引用, 依此类推。 在每一对内, open-quote 取第一项 <string>close-quote 取第二项。

2.4.2. 插入引号:*-quote 关键字

<quote> = open-quote | close-quote | no-open-quote | no-close-quote
测试
open-quote
close-quote
这些值会被 quotes 属性定义的合适字符串替换, 并在嵌套层级上递增(针对 open-quote) 或递减(针对 close-quote) 引号嵌套的层级。
no-open-quote
no-close-quote
不插入任何内容(同 none), 但嵌套层级会递增(针对 no-open-quote) 或递减(针对 no-close-quote) 引号嵌套的层级。

可以通过 open-quoteclose-quote 这两个 content 属性的值, 在文档适当位置插入引号。 每次出现 open-quoteclose-quote 都会被 引号系统(由 quotes 属性指定)定义的引号字符串替换, 基于嵌套深度进行。

实际使用哪一对引号取决于引号嵌套层级 (quote depth): 即在当前内容前生成内容中的 open-quote 出现次数, 减去当前内容前及当前内容内 close-quote 的出现次数。 深度为0使用第一对,为1使用第二对,依此类推。 如果深度大于总对数,则重复使用最后一对。

注: 引号深度与源文档或格式结构中的嵌套无关。 并且类似计数器继承, 它在 [DOM] 上操作“扁平化的元素树”。

如果 close-quoteno-close-quote 导致 引号深度为负, 则视为错误并忽略(渲染时): 深度保持为0且不插入引号 (不过 content 属性值的其它部分仍然插入)。

有些排版风格要求多段引用的每一段开始时都放开引号, 只有最后一段结尾才用闭合引号。 在CSS中可以通过插入“虚拟”闭合引号实现, 关键字 no-close-quote 会递减嵌套层级但不插入引号。

下面这个样式表会在 blockquote 里的每一段都插入开引号, 只在最后一段插入闭合引号:

blockquote p::before { content: open-quote }
blockquote p::after { content: no-close-quote }
blockquote p:last-child::after { content: close-quote }

为对称性,还有 no-open-quote 关键字, 不插入内容但嵌套深度加一。

注: 如果引用内容与周围文本语言不同, 通常应该按周围文本语言插入引号, 而不是引用内容的语言。

例如英文中嵌入法语:
The device of the order of the garter is “Honi soit qui mal y pense.”

法语中嵌入英文:

Il disait: « Il faut mettre l’action en ‹ fast forward ›. »

类似如下样式表可设置 quotes 属性, 让 open-quoteclose-quote 可在所有元素上正确工作。 适用于仅含英文、法文或两者的文档。 如包含其他语言需增加规则。 注意使用子选择器(">") 按周围文本语言设置引号:

:lang(fr) > * { quotes: "\00AB\2005" "\2005\00BB" "\2039\2005" "\2005\203A" }
:lang(en) > * { quotes: "\201C" "\201D" "\2018" "\2019" }

引号写成如下形式便于输入。如能直接输入则会显示为:

:lang(fr) > * { quotes: "« " " »" "‹ " " ›" }
:lang(en) > * { quotes: "“" "”" "‘" "’" }
例如以下样式表:
/* 指定两种语言的两层引号对 */
:lang(en) > q { quotes: '"' '"' "'" "'" }
:lang(no) > q { quotes: "«" "»" "’" "’" }

/* 在 Q 元素内容前后插入引号 */
q::before { content: open-quote }
q::after  { content: close-quote }

应用于以下 HTML 片段:

<html lang="en">
  <head>
   <title>Quotes</title>
  </head>
  <body>
   <p><q>Quote me!</q></p>
  </body>
</html>

可以呈现效果:

"Quote me!"

而若 HTML 片段为:

<html lang="no">
  <head>
   <title>Quotes</title>
  </head>
  <body>
   <p><q>Trøndere gråter når <q>Vinsjan på kaia</q> blir deklamert.</q></p>
  </body>
</html>

则会呈现:

«Trøndere gråter når ’Vinsjan på kaia’ blir deklamert.»

2.5. 引导线

引导线,有时称为制表符引导线或点线, 是一种重复的模式,用于在水平方向视觉连接内容。 它们最常用于目录, 用于标题与页码之间。 leader() 函数作为 content 属性取值, 用于在 CSS 中实现引导线。 此函数接受一个字符串(引导字符串), 用于描述引导线的重复模式。

2.5.1. leader() 函数

leader( <leader-type> )
插入一个引导线。 详细信息参见引导线部分
leader() = leader( <leader-type> )
<leader-type> = dotted | solid | space | <string>

有三个关键字是常用字符串的简写:

dotted
等同于 leader(".")
solid
等同于 leader("_")
space
等同于 leader(" ")
<string>
注:需定义此项。
ol.toc a::after {
  content: leader('.') target-counter(attr(href), page);
}

<h1>Table of Contents</h1>
<ol class="toc">
<li><a href="#chapter1">Loomings</a></li>
<li><a href="#chapter2">The Carpet-Bag</a></li>
<li><a href="#chapter3">The Spouter-Inn</a></li>
</ol>

结果可能为:

Table of Contents

1. Loomings.....................1
2. The Carpet-Bag...............9
3. The Spouter-Inn.............13

引导线是否依赖于后方内容右对齐(尾对齐)的假设?

2.5.2. 引导线渲染

假设一行包括引导线前的内容(“前内容”), 引导线, 和引导线后的内容(“后内容”)。 引导线遵循如下规则:

  1. 引导字符串至少完整显示一次。

  2. 引导线应尽可能长。

  3. 引导线中的可见字符应尽量垂直对齐。

  4. 引导字符串中的换行符会被忽略。

  5. 引导字符串中的空白符按 CSS 正常规则处理。

  6. 引导线仅出现在前内容和后内容之间。

  7. 引导线只出现在一行,即使前内容和后内容在不同的行。

  8. 单独一行不能只包含引导线。

2.5.3. 引导线渲染过程

  1. 排版 前内容, 直到到达 前内容 结束的那一行。

    BBBBBBBBBB
    BBB
    
  2. 引导字符串由一个或多个字形组成, 是一个内联盒。 引导线是一排这些盒, 从尾部向头部绘制, 只显示未被前后内容覆盖的盒。 在该行中, 从尾部开始绘制引导字符串, 能重复多少次就重复多少次直到到达头部。

    BBBBBBBBBB
    ..........
    
  3. 在引导线上方绘制前后内容。 如果 前内容后内容有任何部分覆盖了引导字符串的字形, 则该字形不显示。

    BBBBBBBBBB
    BBB....AAA
    
  4. 如果引导字符串不能完整显示一次:

    BBBBBBB
    BBBBBBA
    

    前内容 后插入换行, 下一行绘制引导线, 然后在上面绘制 后内容, 隐藏未完整显示的引导字符串。

    BBBBBBB
    BBBBBB
    ......A
    

如果 后内容 比行盒更宽是否有特别处理?

引导线在表格布局中效果不佳。如何改进?

drawing leaders
绘制引导线的过程
drawing leaders
内容无法适应单行时的引导线绘制过程

2.6. 交叉引用

许多文档包含内部引用:

content属性有三种新值 可用于自动生成此类交叉引用:target-counter()target-counters()target-text()。 它们都用于显示从链接目标获取的信息。

<target> = <target-counter()> | <target-counters()> | <target-text()>

下面的章节分别介绍这些函数的具体用法。

2.6.1. target-counter() 函数

target-counter() = target-counter( [ <string> | <url> ] , <custom-ident> , <counter-style>? )

target-counter() 函数获取指定名字的最内层计数器的值。 必需参数是目标的url和计数器的名称。 可选的counter-style参数可用于设定结果的格式。

这些函数只接受指向当前文档某个位置的片段URL。 如果没有片段, 如果ID引用不存在, 或者URL指向外部文档, 用户代理必须将其视为错误。

错误处理应该怎样?

当前语法只支持本地引用。

HTML:
…将在第  页讨论。

CSS:

a::after { content: target-counter(attr(href url), page) }

效果:

…将在第 137 页讨论。
目录中的页码可自动生成:

HTML:

<nav>
  <ol>
   <li class="frontmatter"><a href="#pref_01">前言</a></li>
   <li class="frontmatter"><a href="#intr_01">引言</a></li>
   <li class="bodymatter"><a href="#chap_01">第一章</a></li>
  </ol>
</nav>

CSS:

.frontmatter a::after { content: leader('.') target-counter(attr(href url), page, lower-roman) }
.bodymatter a::after { content: leader('.') target-counter(attr(href url), page, decimal) }

效果:

前言.............vii
引言.............xi
第一章............1

2.6.2. target-counters() 函数

此函数从链接目标端获取所有指定名称的计数器值, 并按嵌套计数器之间插入指定字符串的方式进行格式化。

target-counters() = target-counters( [ <string> | <url> ] , <custom-ident> , <string> , <counter-style>? )
目前还没有发现 target-counters() 的经典用例。

已在CSS规范找到实际用例,请补充内容。

2.6.3. target-text() 函数

target-text() 函数获取 URL指向的元素的文本值。 可选的第二参数指定获取的内容类型, 用法与上面 string-set 属性一致。

target-text() = target-text( [ <string> | <url> ] , [ content | before | after | first-letter ]? )

fantasai提出了更简洁的语法方案: https://lists.w3.org/Archives/Public/www-style/2012Feb/0745.html

…将在稍后讨论。

a::after { content: ", 章节标题为 " target-text(attr(href url)) }

效果:…将在稍后讨论,章节标题为 Loomings。

2.7. 命名字符串

本节介绍命名字符串, 它与计数器类似,但有自己的命名空间。 命名字符串遵循与计数器相同的嵌套规则。 string-set 属性接受类似 content 属性的值, 包括提取计数器当前值。

命名字符串便于从文档中抽取元数据, 并插入到页眉页脚中。 例如在HTML中, 文档head中的META元素 可设置命名字符串的值。 结合属性选择器, 可构建强大的机制:

meta[c-author] { string-set: author attr(author); }
head > title { string-set: title contents; }
@page:left {
  @top {
   text-align: left;
   vertical-align: middle;
   content: string(title);
  }
}
@page:right {
  @top {
   text-align: right;
   vertical-align: middle;
   content: string(author);
  }
}

2.7.1. 字符串命名:string-set 属性

名称: string-set
值: none | [ <custom-ident> <string>+ ]#
初始值: none
适用对象: 所有元素,但不包括伪元素
是否继承:
百分比: 不适用
计算值: 关键字none,或一个列表,每项为一个标识与字符串值列表配对
规范顺序: 按语法
动画类型: 离散

期望用户代理在所有媒介(包括非视觉媒介)都支持该属性。

string-set 属性将元素的文本内容复制到 命名字符串, 该字符串可用作变量。 可通过string()函数获取该变量的值。 由于这些变量可能在页面中变更, string()函数的可选第二参数 允许作者选择页面上实际使用的值。

none
元素不设置任何命名字符串。
[ <custom-ident> <string>+ ]#
元素设定一个或多个命名字符串, 对应列表中的每个逗号分隔项。

每项中的<custom-ident>为命名字符串的名称。 其后是一个或多个<string>值, 这些值拼接形成命名字符串的实际值。

如果某元素有样式封装, 其 string-set 属性对其后代无效。

下例捕获H1元素内容, 这些内容在当前文档中代表章节名。
H1 { string-set: chapter contents; }

每遇到一个H1元素, chapter字符串会设为元素文本内容, 若已存在则覆盖前一个值。

2.7.2. 插入命名字符串:string()函数

string() = string( <custom-ident> , [ first | start | last | first-except ]? )

string() 函数通过content属性将命名字符串的值插入文档。 此函数要求提供命名字符串的名字作为参数。 由于命名字符串的值可能在页面内多次变更 (页面中可出现多个定义字符串的元素), 可选的第二参数用于指定所用值的规则。

string()函数的第二参数为以下关键字之一:

first
采用页面中第一次赋值的内容。 若页面内未赋值, 使用入口值。 未提供第二参数时, 此为默认值。
start
如果元素是页面第一个元素, 使用第一次赋值的内容。 否则使用入口值。 若命名字符串尚未出现,则start值可能为空。
last
使用当前页面末尾时的出口值
first-except
性能与first相同, 但在赋值所在页面返回空字符串。

或许整个内容字符串都需清空。有必要吗?

命名字符串的值 在元素的内容盒首次生成时赋值 (或者元素display为none时也赋值)。 入口值为前一页结束时的有效赋值。 出口值为当前页结束时的有效赋值。

CSS:
@page {
  size: 15cm 10cm;
  margin: 1.5cm;

  @top-left {
  content: "first: " string(heading, first);
  }
  @top-center {
  content: "start: " string(heading, start);
  }
   @top-right {
   content: "last: " string(heading, last);
  }
  }

h2 { string-set: heading content() }

下列图示展示了“heading”字符串在不同页面上的first、start和last赋值效果。

由于页面开始时字符串还未设定,start值为空。
该页以h2开头,start值即为该标题内容。
该页顶部没有h2,start值为上一页的出口值

2.7.3. content() 函数

content() = content( [ text | before | after | first-letter | marker ]? )
text
元素的字符串值。 如果 content() 没有指定值, 则等同于指定 text
before
::before 伪元素的字符串值。
after
::after 伪元素的字符串值。
first-letter
元素的首字母,详见 ::first-letter 伪元素
marker
::marker 伪元素的字符串值。
HTML:
<h1>Loomings</h1>

CSS:

h1::before { content: 'Chapter ' counter(chapter); }
h1 { string-set: header content(before) ':' content(text); }
h1::after { content: '.'; }

名为“header”的字符串值会是“Chapter 1: Loomings”。

HTML:
<section title="Loomings">

CSS:

section { string-set: header attr(title) }

“header”字符串的值会是“Loomings”。

2.8. 自动计数器与编号

详见 CSS Lists 3 § 4 自动计数与编号

这部分是否应该回归 CSS Content?

3. 书签

有些文档格式, 尤其是 PDF, 支持使用 书签 进行导航。 书签为文档元素提供链接列表, 并显示链接文本与层级值。 书签有三个属性:bookmark-levelbookmark-label、以及 bookmark-state

当用户激活书签时, 用户代理必须将该引用点带到用户视野, 就像通过片段URL导航到该元素一样。 这也会触发 :target 伪类。

如果某元素有 样式封装,则 bookmark-levelbookmark-labelbookmark-state 属性对其后代无效。

3.1. 设置书签:bookmark-level 属性

bookmark-level 属性决定是否创建书签, 以及层级。 若无此属性, 或值为 none, 不生成书签; 无论 bookmark-labelbookmark-state 如何设置。

名称: bookmark-level
值: none | <integer [1,∞]>
初始值: none
适用对象: 所有元素
是否继承:
百分比: 不适用
计算值: 关键字 none 或指定整数
规范顺序: 按语法
动画类型: 按计算值类型
<integer [1,∞]>
定义书签层级,顶层为1(负值和零值无效)。
none
不生成书签。
section h1 { bookmark-level: 1; }
section section h1 { bookmark-level: 2; }
section section section h1 { bookmark-level: 3; }

注: 书签不要求层级严格递进。

display:none 的元素是否需要生成书签?

3.2. 标注书签:bookmark-label 属性

名称: bookmark-label
值: <content-list>
初始值: content(text)
适用对象: 所有元素
是否继承:
百分比: 不适用
计算值: 指定值
规范顺序: 按语法
动画类型: 离散
<content-list>
<content-list> 定义见上文 string-set 属性部分。<content-list> 的值即为书签标签的文本内容。
HTML:
<h1>Loomings</h1>

CSS:

h1 {
bookmark-label: content(text);
bookmark-level: 1;
}

书签标签将会是“Loomings”。

3.3. 初始书签切换状态:bookmark-state 属性

bookmark-state 可为 open 或 closed。用户必须能切换书签状态。

名称: bookmark-state
值: open | closed
初始值: open
适用对象: 块级元素
是否继承:
百分比: 不适用
计算值: 指定关键字
规范顺序: 按语法
动画类型: 离散
open
后续 bookmark-level 大于该书签的书签会被显示, 直到遇到另一个层级相同或更低的书签。 若后续书签为 closed, 以同样规则判断其后续书签是否显示。
closed
后续 bookmark-level 层级更高的书签不会显示, 直到遇到另一相同或更低层级的书签。

书签的初始状态,由UA还是作者决定?

4. 变更

2019年8月2日工作草案以来的主要变动,包括:

另见以前变更

致谢

Stuart Ballard, David Baron, Bert Bos,Tantek Çelik, 和 James Craig 为本规范提供了宝贵建议。

隐私注意事项

本规范未报告新的隐私注意事项。

安全注意事项

本规范未报告新的安全注意事项。

一致性

文档约定

一致性要求采用叙述性断言和 RFC 2119 术语结合表达。规范部分的关键词“MUST”(必须)、“MUST NOT”(禁止)、“REQUIRED”(必需)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(建议)、“SHOULD NOT”(不建议)、“RECOMMENDED”(推荐)、“MAY”(可以)、“OPTIONAL”(可选),应按照 RFC 2119 的解释理解。但为便于阅读,本规范未将这些词全部大写。

除明显标注为非规范性内容、示例和注释的章节外,本规范的所有文本均为规范性内容。[RFC2119]

本规范中的示例以“例如”开头或用 class="example" 标记,与规范性文本区分,如下所示:

这是一个信息性示例。

信息性注释以“注”开头,并用 class="note" 标记,与规范性文本区分,如下所示:

注:这是一个信息性注释。

规范性建议部分会特别强调,并用 <strong class="advisement"> 标记,与其他规范性文本区分,如下所示: 用户代理必须提供可访问的替代方案。

测试

与本规范内容相关的测试可在本块记录。此类块均为非规范性内容。


一致性类别

本规范的一致性定义有三种类别:

样式表
CSS 样式表
渲染器
解释样式表语义并渲染其文档的 UA
创作工具
编写样式表的 UA

若样式表所有采用本模块语法的语句均符合通用 CSS 语法和各功能模块的语法,则该样式表符合本规范。

渲染器符合本规范需在解析样式表时除执行相关规范要求外,还能正确解析和渲染本规范所有功能。但设备本身限制导致渲染能力不足不影响 UA 一致性认定。(如单色显示器上的 UA 不要求支持颜色渲染。)

创作工具符合本规范需按通用 CSS 语法和本模块功能语法正确输出样式表并满足所有样式表一致性要求。

部分实现

为便于作者利用前向兼容性解析规则实现回退值,CSS 渲染器必须将所有无法支持的 at-规则、属性、属性值、关键字及其它语法结构视为无效并适当忽略。特别是,用户代理不得在多值声明中仅忽略不支持的值而保留支持值:如有值被视为无效(即不支持),整个声明必须被 CSS 忽略。

不稳定与专有特性的实现

为避免与未来 CSS 稳定特性冲突,CSS 工作组建议遵循最佳实践以实现不稳定专有扩展特性。

非实验性实现

当规范进入候选推荐(CR)阶段时,可以进行非实验性实现,且实现者应发布非前缀的实现版本,只要能根据规范证明实现正确。

为确保 CSS 实现间的互操作性,CSS 工作组要求非实验性渲染器在发布非前缀实现前向 W3C 提交实现报告(如需还应提交测试用例)。CSS 工作组可对提交的测试用例进行审核和修正。

关于测试用例与实现报告提交的更多信息请见 CSS 工作组网站:https://www.w3.org/Style/CSS/Test/。如有疑问请联系public-css-testsuite@w3.org邮件列表。

索引

本规范定义的术语

引用文献定义的术语

参考文献

规范性引用

[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承 Level 5. 2022年1月13日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS 封装模块 Level 2. 2022年9月17日. WD. URL: https://www.w3.org/TR/css-contain-2/
[CSS-COUNTER-STYLES-3]
Tab Atkins Jr.. CSS计数器样式 Level 3. 2021年7月27日. CR. URL: https://www.w3.org/TR/css-counter-styles-3/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS显示模块 Level 4. 2025年11月6日. WD. URL: https://www.w3.org/TR/css-display-4/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS图片模块 Level 3. 2023年12月18日. CRD. URL: https://www.w3.org/TR/css-images-3/
[CSS-IMAGES-4]
Elika Etemad; Tab Atkins Jr.; Lea Verou. CSS图片模块 Level 4. 2025年9月30日. WD. URL: https://www.w3.org/TR/css-images-4/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.. CSS列表和计数器模块 Level 3. 2020年11月17日. WD. URL: https://www.w3.org/TR/css-lists-3/
[CSS-PSEUDO-4]
Elika Etemad; Alan Stearns. CSS伪元素模块 Level 4. 2025年6月27日. WD. URL: https://www.w3.org/TR/css-pseudo-4/
[CSS-TEXT-4]
Elika Etemad; et al. CSS文本模块 Level 4. 2024年5月29日. WD. URL: https://www.w3.org/TR/css-text-4/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS值与单位模块 Level 3. 2024年3月22日. CRD. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS值与单位模块 Level 4. 2024年3月12日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS值与单位模块 Level 5. 2024年11月11日. WD. URL: https://www.w3.org/TR/css-values-5/
[CSS2]
Bert Bos; et al. 层叠样式表 Level 2 修订版 (CSS 2.1) 规范. 2011年6月7日. REC. URL: https://www.w3.org/TR/CSS2/
[CSS3-NAMESPACE]
Elika Etemad. CSS命名空间模块 Level 3. 2014年3月20日. REC. URL: https://www.w3.org/TR/css-namespaces-3/
[CSS3-SPEECH]
Léonie Watson; Elika Etemad. CSS语音模块 Level 1. 2023年2月14日. CRD. URL: https://www.w3.org/TR/css-speech-1/
[HTML]
Anne van Kesteren; et al. HTML标准. 活标准. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. 用于RFC要求级别的关键词. 1997年3月. 最佳现行实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器 Level 4. 2022年11月11日. WD. URL: https://www.w3.org/TR/selectors-4/

参考性引用

[CLDR]
Unicode 通用区域数据仓库. URL: https://cldr.unicode.org/
[CSS-TEXT-3]
Elika Etemad; Koji Ishii; Florian Rivoal. CSS文本模块 Level 3. 2024年9月30日. CRD. URL: https://www.w3.org/TR/css-text-3/
[DOM]
Anne van Kesteren. DOM标准. 活标准. URL: https://dom.spec.whatwg.org/

属性索引

名称 初始 适用对象 继承性 %百分比 动画类型 规范顺序 计算值
bookmark-label <content-list> content(text) 所有元素 不适用 离散 按语法 指定值
bookmark-level none | <integer [1,∞]> none 所有元素 不适用 按计算值类型 按语法 关键字 none 或指定整数
bookmark-state open | closed open 块级元素 不适用 离散 按语法 指定关键字
content normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> | <attr()> ]+ ]? normal 所有元素、遵循树结构的伪元素和页面页边距框 不适用 离散 按语法 见下文说明
quotes auto | none | match-parent | [ <string> <string> ]+ auto 所有元素 不适用 离散 按语法 关键字 none, auto 或 match-parent,或一组字符串值对
string-set none | [ <custom-ident> <string>+ ]# none 所有元素,但不包括伪元素 不适用 离散 按语法 关键字 none 或每项一标识及字符串值列表

问题索引

上述 无效图像 的行为似乎是 Chrome 当前的做法。 这可以接受吗?是否有更好的行为我们可以/应该采用?
该值历史上在 <content-list> 上被视为 ::before::after 的行为。大概对此存在 Web 兼容性要求,因此这些伪元素可能需要例外。 [Issue #2889]
是否应将 contents 关键字替换为 content()
开始针对CSS编写辅助访问映射(AAM)。
CSS2.1 明确允许UA在图片无效时替换为损坏图片图标, 但没有浏览器这样做。 这样的删改可以接受吗?
在伪元素上是否应该表现为空字符串?
欢迎补充通过伪元素抑制元素内容并使用内容的实际案例。
需不需要这里 marker 伪元素相关说明?还是仅是旧规范遗留?
这里有两种做法,目前规范的是后者: a) 该值最终计算为相关字符串值,并继承该值 b) 该值实际上继承为关键字+语言代码,即 auto,但附带该语言。
引导线是否依赖于后方内容右对齐(尾对齐)的假设?
如果 后内容 比行盒更宽是否有特别处理?
引导线在表格布局中效果不佳。如何改进?
错误处理应该怎样?
当前语法只支持本地引用。
已在CSS规范找到实际用例,请补充内容。
fantasai提出了更简洁的语法方案: https://lists.w3.org/Archives/Public/www-style/2012Feb/0745.html
或许整个内容字符串都需清空。有必要吗?
这部分是否应该回归 CSS Content?
display:none 的元素是否需要生成书签?
书签的初始状态,由UA还是作者决定?