CSS 字体模块第 4 级

W3C 工作草案,

更多关于此文档的详细信息
此版本:
https://www.w3.org/TR/2026/WD-css-fonts-4-20260303/
最新发布版本:
https://www.w3.org/TR/css-fonts-4/
编辑草案:
https://drafts.csswg.org/css-fonts-4/
以前的版本:
历史:
https://www.w3.org/standards/history/css-fonts-4/
反馈:
CSSWG 问题库
规范内联
编辑:
Chris Lilley (W3C)
前编辑:
John Daggett (特邀专家)
(前 Apple Inc.)
建议对此规范进行编辑:
GitHub 编辑器
测试套件:
https://wpt.fyi/results/css/css-fonts/

摘要

本规范在现有的 CSS Fonts 3 规范基础上进行了修改,并增加了用于字体特性控制、可变字体以及彩色(色彩)字体的附加功能。

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

本文件的状态

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

本文件由 CSS 工作组(CSS Working Group) 作为一份工作草案(Working Draft),按照 推荐 路线(Recommendation track) 发布。 作为工作草案发布 并不意味着 W3C 及其成员对此予以认可。

本文件是一份草案, 可能在任何时间被更新、替换 或被其他文件废止。 因此不适合作为除“进行中的工作”之外的其他用途进行引用。

请通过以下方式发送反馈: 首选方式是在 GitHub 中提交 issue, 在标题中包含规范代码 “css-fonts”,例如: “[css-fonts] …意见概要…”。 所有的 issue 和评论都会被归档。 或者,也可以将反馈发送到(同样会被归档的)公共邮件列表 www-style@w3.org

本文件受 2025 年 8 月 18 日版 W3C 过程文档 管辖。

本文件由一个遵循 W3C 专利政策 运作的小组编制。 W3C 维护着一份 关于该小组成果相关专利披露的公共列表; 该页面还包含如何披露专利的说明。 任何个人如果确实知悉某项专利并认为该专利 包含必要权利要求(Essential Claim), 必须根据 W3C 专利政策第 6 节 披露相关信息。

以下功能为“有风险(at-risk)”,在 CR 阶段期间可能会被删除:

“At-risk” 是 W3C 过程中的术语,并不一定表示该功能有被删除或延迟的危险。 它的含义是工作组(WG)认为该功能在及时实现互操作性方面可能存在困难, 将其标记为 at-risk,可以让工作组在转入“拟推荐标准(Proposed Rec)”阶段时,如有必要删除该功能, 而无需先发布一份不含该功能的新“候选推荐标准(Candidate Rec)”。

1. 简介

本规范包含并扩展了CSS3字体规范中描述的基本字体功能 ([CSS-FONTS-3])。

1.1. 值定义

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

除了在其定义中列出的特定于属性的值外, 本规范中定义的所有属性 还接受作为其属性值的CSS范围关键词。 为了可读性,未明确重复列出。

2. 基本字体属性

用于呈现字符的特定字体面由 字体系列和应用于给定元素的其他字体属性决定。 此结构允许独立调整设置。

2.1. 字体系列:font-family 属性

名称: font-family
值: [ <family-name> | <generic-family> ]#
初始值: 取决于用户代理
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 列表,每个项为字符串和/或<generic-family> 关键词
规范顺序: 按照语法
动画类型: 离散
测试

此属性指定了字体系列名称或通用字体系列名称的优先列表。 一个字体系列定义了一组在粗细、宽度或倾斜度上有所变化的字形。 CSS 使用字体系列名称与其他字体属性的组合来选择单个字形。 使用这种选择机制, 而不是像设计应用程序中常用的通过样式名称选择字形, 允许在回退发生时文本显示具有一定的规则性。

组件值是一个逗号分隔的替代列表。 用户代理会遍历字体系列名称列表, 直到匹配到可用的字体, 其中包含要渲染字符的字形。 (参见 § 5.3 字符簇匹配。) 这允许跨平台的可用字体不同, 以及各个字体支持的字符范围不同。

body {
    font-family: Helvetica, Verdana, sans-serif;
}

如果 Helvetica 可用,则会在渲染时使用。 如果 Helvetica 和 Verdana 都不可用, 那么将使用通用字体系列 sans-serif 字体。

字体系列名称有三种类型,其中两种可用于此属性:

<family-name>
字体族名称,例如上一个示例中的 Helvetica 或 Verdana。

这可以是本地安装的字体,也可以是 Web 字体。

<generic-family>
每个 <generic-family> 关键字都表示 一个通用字体选择, 并作为指定通用字体类别中 一个或多个本地安装字体的潜在别名。 因此,<generic-family> 可以用作回退, 以便在作者更具体的字体选择不可用时使用。

通用字体家族共有三种类型:

  1. 适用于所有 Unicode 字符, 并且始终会匹配到本地安装字体的通用字体。 例如,monospaced

  2. 适用于所有 Unicode 字符, 但在某些系统上可能无法匹配到本地安装字体的通用字体。 例如,ui-rounded

  3. 针对特定书写系统的通用字体, 只适用于 Unicode 字符的子集, 并且在某些系统上可能无法匹配到本地安装字体。 例如,generic(fangsong)

鼓励作者在最后追加一个通用字体家族以提高健壮性, 并在适用时使用更具体的通用字体家族, 以便在单独命名的字体家族不可用时,仍能偏向某种特定风格。

注意,<generic-family> 关键字不能加引号 (否则会被解释为 <family-name>)。

通用字体家族关键字的集合定义见 § 2.1.5 通用字体家族

<system-family-name>
本地安装的系统字体,其使用受一定约束。 特别是,它不能与 font-family 属性一起使用, 但可以用于 font 速记属性。

以下取值引用系统字体:

caption
用于带标题控件(例如按钮、下拉框等)的字体。
icon
用于标注图标的字体。
menu
用于菜单(例如下拉菜单和菜单列表)的字体。
message-box
用于对话框的字体。
small-caption
用于标注小型控件的字体。
status-bar
用于窗口状态栏的字体。
Tests

2.1.1. <family-name> 语法

<family-name> = <string> | <custom-ident>+

除了通用字体系列或系统字体系列外,字体系列名称必须用 <string> 引号括起来,或不加引号作为一个或多个 <custom-ident> 序列。

注:这意味着,如果你确实有一个字体, 它的名称 与某个 <generic-family> 名称相同, 或与系统字体名称相同, 或与 CSS 全局关键字(CSS-wide keywords)相同, 那么它必须加引号。

为了说明这一点, 下面这些不寻常的字体族名称是合法的, 因为它们被加上了引号:
font-family: "sans-serif", sans-serif;
font-family: "default", sans-serif;
font-family: "initial", sans-serif;
font-family: "inherit", sans-serif;

如果将一串标识符作为 <family-name> 给出, 则计算值是将这一串标识符 用单个空格连接后 转换得到的字符串。

为避免转义错误, 建议对包含空格、数字, 或连字符以外标点符号的字体族名称加引号:

给字体族加引号可以避免转义错误。
body { font-family: "New Century Schoolbook", serif }

<body style="font-family: '21st Century', fantasy">

字体族名称如果恰好与某个 font-family 关键字取值相同 (例如 CSS 全局关键字(CSS-wide keywords),如 inherit,或 <generic-family> 关键字,如 serif), 则必须加引号,以避免与同名关键字混淆。 用户代理(UA)不得将这些关键字视为匹配 <family-name> 类型。

2.1.2. <generic-family> 语法

<generic-family> = <generic-script-specific>| <generic-complete> | <generic-incomplete>
<generic-script-specific> = generic(fangsong) | generic(kai) | generic(khmer-mul) |  generic(nastaliq)
<generic-complete> = serif | sans-serif | system-ui | cursive | fantasy | math | monospace
<generic-incomplete> = ui-serif | ui-sans-serif | ui-monospace | ui-rounded

为了让语法不那么容易与其他内容冲突,较新的通用字体家族通过函数式语法来标识。

body { font-family: "Adobe Fangsong Std R", generic(fangsong), serif}

此示例中的首选项是一个采用仿宋风格的特定命名字体。 由于字体族名称包含空格字符,因此用引号括了起来。 第二个是新近添加的、针对特定书写系统的通用字体;它是基于 unicode-range 的, 因而在某些系统上可能不会匹配到实际安装的字体; 但如果存在,它将是所请求风格的一个示例。 第三个是通用的(全局)通用字体,在所有系统上都保证可以匹配到。

2.1.3. <system-family-name> 语法

<system-family-name> = caption | icon | menu | message-box | small-caption | status-bar

2.1.4. 字体族与字体面之间的关系

字体家族名称仅指定一组字体面的名称;它不指定单个字体面。

例如,给定以下字体的可用性,Futura 会匹配,但 Futura Medium 不会:
family and face names
字体族与个别字体面名称

注意: CSS 对选择时使用的字体属性的定义明确不旨在定义字体分类法。 字体设计师对字体家族的定义通常会扩展到沿着标准轴之外的轴变化的字体面集合,如 粗细 (font-weight), 宽度 (font-width) 和 倾斜度 (font-style)。 一个家族可以沿着该家族独有的轴变化。CSS 字体选择机制仅提供在需要替换时确定“最接近”匹配的方式。

注意: 将一组字体分组到字体家族中的具体方式因平台字体管理 API 而异。 例如,Windows GDI API 只允许将四个字体面分组到一个家族中, 而 DirectWrite API、Core Text API 和其他平台支持带有各种粗细、宽度和倾斜度的字体家族 (有关更多详细信息,请参阅 附录 A: 将平台字体属性映射到 CSS 属性)。

有关字体家族名称如何匹配的信息,请参阅下文中的 § 5.1 本地化名称匹配

2.1.5. 通用字体系列

通用字体家族是一个具有标准名称的字体家族(由 CSS 定义),但它是系统上现有安装字体家族的别名。 然而,单个通用字体系列可能是基于字符的 Unicode 范围、 包含元素的内容语言、 用户偏好、系统设置等因素的不同字体组合面。 不同的通用字体系列可能映射到同一个字体。

Tests

注意: 通用字体家族旨在广泛地在许多平台上实现, 不像通常是平台特定名称的任意<family-name>。 预计它们会在不同平台上映射到不同的字体。如果作者希望文本在许多平台上遵循特定的设计, 并且不在乎这些平台上选择的是哪个具体字体,他们可以指定这些通用字体家族名称。

用户代理应为通用字体系列提供合理的默认选择, 以尽可能表达每个系列的特点, 在基础技术允许的范围内。 鼓励用户代理允许用户为通用字体系列选择替代字体。

serif
衬线字体(Serif fonts)表示 具有收笔笔画、 外扩或渐细的末端, 或带有实际衬线结尾(包括 slab serif)的字形。 衬线字体通常是按比例间距的。 与 sans-serif 通用字体家族中的字体相比, 它们在粗细笔画之间往往表现出更大的变化。

Note: serifsans-serif 只适用于少数几种书写体系。 它们作为 CSS 通用字体家族的使用具有历史原因, 反映了早期 Web 开发中 以拉丁文字为中心的特性。 更好且适用范围更广的名称本可以是 例如 “modulated” 和 “monoline”。 然而,出于 Web 兼容性的原因, 这些名称无法更改。

CSS 使用 “serif” 这一术语来指代任何书写体系的字体, 尽管对于某些具体书写体系, 可能有更加熟悉的名称, 如日文的 Mincho, 中文的 Sung 或 Song, 韩文的 Batang。 对于阿拉伯文,Naskh 风格就对应于 serif

serif 必须始终映射到至少一个匹配的字体字面。

Note: 对该字体 字面不对其字符覆盖范围作任何保证。 因此,映射到字体 serif 的结果,可能不会被用于所有内容。

sample serif fonts
示例 serif 字体
sans-serif
在 CSS 中, 无衬线字体(sans-serif fonts)中的字形 通常为低对比度 (竖笔和横笔粗细大致相同), 且笔画结尾较为朴素 (没有外扩、横向收笔或其他装饰)。 无衬线字体通常是按比例间距的。 与 serif 家族中的字体相比, 它们在粗细笔画之间通常只有很小的变化。 CSS 使用 “sans-serif” 这一术语来指代任何书写体系的字体, 尽管对于某些具体书写体系, 可能有更加熟悉的名称, 如日文的 Gothic, 中文的 Hei, 或韩文的 Gulim。

sans-serif 必须始终映射到至少一个匹配的字体字面。

Note: 对该字体 字面不对其字符覆盖范围作任何保证。 因此,映射到字体 sans-serif 的结果,可能不会被用于所有内容。

sample sans-serif fonts
示例 sans-serif 字体
cursive
手写体字体(cursive fonts)中的字形通常采用连笔书写风格, 显示效果更像手写的钢笔或毛笔字, 而非印刷体字形。 CSS 使用 “cursive” 一词来指代任何书写体系的字体, 尽管在字体名称中也会使用其他名称, 如 Chancery、Brush、Swing 和 Script 等。
sample cursive fonts
示例 cursive 字体
fantasy
Fantasy 字体主要是装饰性或表现性字体, 其中包含对字符的装饰性或表现性呈现。 这不包括不代表实际字符的 Pi 或 Picture 字体。
sample fantasy fonts
示例 fantasy 字体
monospace
等宽字体(monospace font)的唯一判定标准是: 所有字形具有相同的固定宽度。 它通常用于呈现计算机代码示例。

monospace 必须始终映射到至少一个匹配的字体字面。

Note: 对该字体 字面不对其字符覆盖范围作任何保证。 因此,映射到字体 monospace 的结果,可能不会被用于所有内容。

sample monospace fonts
示例 monospace 字体
system-ui
这一通用字体家族使文本可以使用 用户界面默认字体进行渲染 (同所有 § 2.1.5 Generic font families 一样,它可能是一个复合字体)。 使用的是 UA 运行的平台上的字体。 跨平台 UA 应在其支持的不同平台上使用不同的字体。 system-ui 的目的是让 Web 内容 能够与原生操作系统的外观和感觉相融合。 这对于混合应用、Web 应用或跨平台应用非常有用。
Tests

具体使用哪一种字体将取决于诸如 平台支持、平台语言、区域设置、 用户偏好、Unicode 覆盖范围以及内容语言 等因素。 UA 可以选择在使用 system-ui 时,选用平台提供的文本渲染引擎, 以更贴近默认用户界面外观。

与其他通用字体家族一样, 将具体已安装字体替换为 system-ui 并不会影响计算样式。
<div id="system-text" style="font-family: system-ui"></div>
...
window.getComputedStyle(document.getElementById("system-text")).getPropertyValue("font-family");

上述脚本不应了解 system-ui 是如何被展开为一组系统用户界面字体的。 尤其是,上述脚本在所有平台上都应返回 "system-ui" 这一结果。

Note: system-ui 在很大程度上依赖平台环境,因为有多种因素可能 影响默认用户界面字体,并且可能具有不同水平的文本渲染支持。 这可能导致某些终端用户看到的字体并不理想 (例如,使用简体中文的用户在旧版本 Windows 上可能会得到等宽衬线字体; 在诸如俄语区域设置下的 lang="uk" 或中文区域设置下的 lang="ja" 等情况下, lang 属性可能不会影响显示字体)。 一些操作系统厂商不提供自定义 system-ui 的方式, 不同于通常允许用户自定义通用 sans-serifserif 字体家族的 UA。 顾名思义,system-ui 旨在用于 Web 应用中的界面元素,而不是用于大段文本或文章。

math
此字体家族用于排版数学表达式。

此类字体可能包含额外的数据 (例如 OpenType 的 MATH 表), 以辅助分层的公式布局过程。 尤其是,它们可能包含 在排版数学公式时有用的 风格变体字形和可伸缩字形变体。

generic(fangsong)
此字体家族用于中文的仿宋(Fang Song,仿宋)字形。 仿宋是一种介于 宋体(Song,serif)和楷体(Kai,generic(kai))之间的 较为舒展的中间形式。 通常来说,其横画略带倾斜, 收笔装饰更小, 与宋体风格相比, 笔画粗细变化也较少。 仿宋常用于中国政府的正式文件中。

Note: generic(fangsong) 可能不会映射到任何 本地安装字体, 但如果映射到了,该字体将是仿宋风格。

使用示例仿宋字体显示的中文文本
generic(kai)
此字体家族用于 简体和繁体中文。 这是一类主要字体,为中文文本提供书法风格。 显示效果具有明显的手写特征。 楷体常用于正式文件和教科书。 台湾的大多数公文都全文使用楷体。 楷体也可以与其他字体搭配, 用于需要与正文区分的文本, 例如标题、参考文献、引文和对话内容等。

Note: generic(kai) 可能不会映射到任何本地安装字体, 但如果映射到了,该字体将是楷体风格。

使用示例楷体字体显示的中文文本
generic(khmer-mul)
此字体家族用于 柬埔寨使用的高棉语, 主要用于标题和小标题, 或用于强调重要的名称或名词。 与用于正文的直体(âksâr chôr)风格相比, âksâr mul 的特点是 字形更粗、更圆润, 并且可能包含更多连写形式。

尽管风格在视觉上更为粗重, 但在 generic(khmer-mul) 中用于 正文文本的字体粗细并未改变(400)。

Note: generic(khmer-mul) 可能不会映射到 任何本地安装字体, 但如果映射到了,该字体将是 âksâr mul 风格。

显示高棉文文本的示例: (上)âksâr chôr 风格,使用 Khmer OS Battambang 排版; (中)âksâr mul 风格,使用 Khmer OS Moul v6 排版,无连写; (下)âksâr mul 风格,使用 Khmer OS Moul v4 排版,包含两个连写。所有字体由 Dan Hong 设计。
generic(nastaliq)
此字体家族是书写乌尔都语和克什米尔语的标准方式, 同时也经常是波斯语和其他语言文本的首选风格, 尤其是在诗歌等文学体裁中。 其主要特征包括连写字母所形成的倾斜基线, 以及对基本字母和附标记都进行复杂的字形塑形和定位。 许多字形和连写形式也有独特的形状。 对于乌尔都语和克什米尔语等语言, 非常重要的一点是不要回退到 naskh 风格。

Note: generic(nastaliq) 可能不会映射到任何 本地安装字体, 但如果映射到了,该字体将是 Nastaliq 风格。

السلام علیکم
使用示例 nastaliq 字体(Noto Nastaliq Urdu)显示的乌尔都文文本
السلام علیکم
使用回退 naskh 字体(Scheherazade New)显示的乌尔都文文本
ui-serif
此字体家族用于系统 用户界面中的衬线变体。ui-serif 的目的是让 Web 内容能够与原生操作系统的外观和感觉相融合。

Note: ui-serif 在 不具备相应系统字体的平台上, 预期不会映射到任何字体。

Note: 潜在问题请参见 system-ui 的相关说明。

sample ui-serif font
macOS Catalina 和 iOS 13 上示例 ui-serif 字体:New York
ui-sans-serif
此字体家族用于系统 用户界面中的无衬线变体。ui-sans-serif 的目的是让 Web 内容能够与原生操作系统的外观和感觉相融合。

Note: ui-sans-serif 在不具备相应系统字体的 平台上,预期不会映射到任何字体。

Note: 潜在问题请参见 system-ui 的相关说明。

sample ui-sans-serif font
macOS Catalina 和 iOS 13 上示例 ui-sans-serif 字体:San Francisco
ui-monospace
此字体家族用于 系统用户界面的等宽变体。ui-monospace 的目的是 让 Web 内容能够与原生操作系统的 外观和感觉相融合。

Note: ui-monospace 在不具备相应系统字体的 平台上,预期不会映射到任何字体。

Note: 潜在问题请参见 system-ui 的相关说明。

sample ui-monospace font
macOS Catalina 和 iOS 13 上示例 ui-monospace 字体:SF Mono
ui-rounded
此字体家族用于系统 用户界面的圆角变体。ui-rounded 的 目的是让 Web 内容能够与原生操作系统的外观和感觉相融合。

Note: ui-rounded 在不具备相应系统字体的 平台上,预期不会映射到任何字体。

Note: 潜在问题请参见 system-ui 的相关说明。

sample ui-rounded font
macOS Catalina 和 iOS 13 上示例 ui-rounded 字体:SF Rounded

2.2. 字体粗细: font-weight 属性

名称: font-weight
取值: <font-weight-absolute> | bolder | lighter
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 一个数字,见下文
规范顺序: 按语法
动画类型: 按计算值类型
Tests

font-weight 属性指定字体字形的粗细权重, 即其黑度程度或笔画粗细。

此属性接受下列取值:

<font-weight-absolute> = [ normal | bold | <number [1,1000]> ]

各取值含义如下:

<number [1,1000]>
每个数字表示的字重至少与其前一个数字一样深(不更浅)。 只有大于等于 1 且小于等于 1000 的值是有效的, 其他所有值都是无效的。 数值通常与下列常用字重名称相对应。
  • 100 - Thin(极细)
  • 200 - Extra Light(Ultra Light,特细)
  • 300 - Light(细体)
  • 400 - Normal(常规)
  • 500 - Medium(中等)
  • 600 - Semi Bold(Demi Bold,半粗体)
  • 700 - Bold(粗体)
  • 800 - Extra Bold(Ultra Bold,更粗)
  • 900 - Black(Heavy,极粗)

Note: 字体内部可能提供其自身的 字重名称映射, 但这些字体内部的映射在 CSS 中会被忽略。

normal
等同于 400
bold
等同于 700
bolder
指定比继承来的值更粗的字重。 参见 § 2.2.1 Relative Weights
lighter
指定比继承来的值更细的字重。 参见 § 2.2.1 Relative Weights

使用非九级刻度的字体格式, 应将其刻度映射到 CSS 的刻度上, 使 400 大致对应标记为 Regular、Book、Roman 的字面, 而 700 大致对应标记为 Bold 的字面。 或者,也可以从样式名称中推断字重, 使其大致与上述刻度相对应。 该刻度是相对的, 因此较大字重值对应的字面绝不能看起来更细。 如果通过样式名称推断字重, 则在处理不同地域语言环境中的样式名称差异时 需要格外小心。

2.2.1. 相对权重

指定的 bolderlighter 值表示相对于父元素字体粗细的权重。 计算出的粗细值基于继承的 font-weight 值,并使用下表进行计算。

继承的值 (w) bolder lighter
w < 100 400 不变
100 ≤ w < 350 400 100
350 ≤ w < 550 700 100
550 ≤ w < 750 900 400
750 ≤ w < 900 900 700
900 ≤ w 不变 700

注意: 上表相当于在字体家族中选择下一个相对的粗体或细体, 包含普通和粗体的字体,以及极细和极重的字体。 如果需要对某个元素使用更精确的权重值, 作者可以使用数字值来代替相对权重。

2.2.2. 缺失的权重

某些字体家族通常只提供少数几种粗细。 当指定的权重没有对应的字体时,会使用一个相邻权重的字体。 一般来说,粗字体映射到权重大于的字体,细字体映射到权重更轻的字体。 (详见 § 5 字体匹配算法 的准确定义。)

以下示例说明不同权重情况下使用的字体。 灰色表示没有存在所需权重的字体,因此使用了相邻权重的字体。
权重为400、700和900的字体家族的权重映射
权重为400、700和900的字体家族的权重映射
权重为300和600的字体家族的权重映射
权重为300和600的字体家族的权重映射

大多数用户代理将字体建模为具有特定的权重, 通常对应于上述九步标度中的一个数值。 虽然这适用于大多数字体,但有些字体可能是可配置的,支持一定范围的权重。 在这种情况下,用户代理会使用一个与所请求的权重尽可能接近的字体 (参见 § 5 字体匹配算法 了解具体算法)。 特别是,对于支持权重范围的字体, 用户代理应表现得像字体在该范围内的每个权重都有存在一样。 对于使用变体的 TrueType / OpenType 字体, 使用 wght 变体来实现变化的权重。 分数权重是有效的。

尽管排版设计师并不热衷于此, 用户代理经常为缺乏实际粗体的字体家族合成粗体。 在字体匹配的过程中, 这些合成的粗体必须被视为字体家族中的一部分。 作者可以通过使用 font-synthesis 属性显式避免这种行为。

2.3. 字体宽度:font-width 属性

名称: font-width
取值: normal | <percentage [0,∞]> | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不解析
计算值: 一个百分比,见下文
规范顺序: 按语法
动画类型: 按计算值类型
Tests

font-width 属性在字体家族中选择 正常、紧缩或扩展的字面。 取值可以是百分比, 也可以是映射为百分比的关键字, 如下表所定义:

绝对关键字值 数值
ultra-condensed 50%
extra-condensed 62.5%
condensed 75%
semi-condensed 87.5%
normal 100%
semi-expanded 112.5%
expanded 125%
extra-expanded 150%
ultra-expanded 200%

<percentage [0,∞]> 值表示字形的宽度比例, 100% 表示“正常”字形宽度 (由字体设计者定义)。 小于 0% 的值是 无效的

当不存在特定宽度的字形时, 小于 100% 的值映射到更窄的字形(如果存在),否则映射到更宽的字形。 相反,值大于或等于 100% 时映射到更宽的字形(如果存在),否则映射到更窄的字形。 某些字体可能支持一定范围的宽度值; 如果字体不支持请求的宽度值, 将使用最接近的支持值,并使用相同的映射规则 (参见 § 5 字体匹配算法 了解具体算法)。 对于支持变体的 TrueType / OpenType 字体, 使用 wdth 变体来实现变化的宽度。

下图显示了九个 font-width 属性设置 对字体家族匹配的影响,字体家族包含各种离散宽度。 灰色表示不存在该宽度的字形,因此替换了不同宽度的字形:
宽度映射:包含压缩、正常和扩展字形的字体家族
宽度映射:包含压缩、正常和扩展字形的字体家族

getComputedStyle() 始终将其值序列化为 <percentage>,无论作者如何指定值, 也无论关键字是否恰好映射到该值。

2.3.1. 字体宽度:font-stretch 旧名称别名

出于历史原因,存在一个 font-stretch 属性, 它是旧名称别名,功能与 font-width 相同。

例如,这里在一级标题中使用了旧的 font-stretch
h1 {font-stretch: condensed; }

这些标题上 font-width 的指定值变为 condensed

例如,这里在一级标题中使用了 font-width
h1 {font-width: condensed; }

这些标题上 font-stretch 的指定值变为 condensed

Tests

用户代理不得为缺少相应字形且没有宽度变体轴的字体家族合成压缩或扩展字形。 特别是,用户代理不得对这些字形进行几何拉伸。

2.4. 字体样式:font-style 属性

名称: font-style
取值: normal | italic | left | right | oblique <angle [-90deg,90deg]>?
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的关键字,如果指定了角度则再加上以度为单位的角度
规范顺序: 按语法
动画类型: 按计算值类型;normaloblique 0deg 进行动画
Tests

font-style 属性允许选择斜体(italic)或倾斜体(oblique)字面。 斜体形式通常具有手写特征,而倾斜体通常是常规字面的倾斜版本。

将灰色显示的 Palatino “a” 和 Baskerville “N” 的人工倾斜渲染, 与真正的斜体版本进行比较:
artificial sloping vs. real italics
人工倾斜与真实斜体的对比

各取值含义如下:

normal
匹配被归类为正常字面的字体, 即既不是斜体也不是倾斜体的字面。 这表示倾斜值为 “0” 的 oblique。
italic
匹配被标记为斜体字面的字体, 如果不存在斜体字面,则匹配倾斜体字面。 倾斜的角度和方向未作指定。
left
匹配被标记为斜体字面的字体, 且具有正值(顺时针方向)的倾斜; 如果不存在这样的斜体,则匹配具有正向倾斜的倾斜体字面。
right
匹配被标记为斜体字面的字体, 且具有负值(逆时针方向)的倾斜; 如果不存在这样的斜体,则匹配具有负向倾斜的倾斜体字面。
oblique <angle [-90deg,90deg]>?
控制与倾斜体字面的匹配。 正角度表示顺时针方向的倾斜; 负角度表示逆时针方向的倾斜。 省略 <angle> 时表示 14deg。 (注意字体内部可能会为 “oblique” 提供自己的映射, 但字体内部的映射在 CSS 中会被忽略。) 接受小数和负值;然而, 小于 -90deg 或大于 90deg 的值是无效的。 如果不存在任何倾斜体字面, 且 font-synthesis-style 的值为 auto, 则会生成一个合成的倾斜体字面。
negative slant
具有负倾斜的斜体字面。 字体为 Mf Autumn Breeze, 由 Misti Hammers 设计。

一个字体家族可能不包含任何斜体或倾斜体, 只包含斜体而不包含倾斜体, 只包含倾斜体而不包含斜体, 同时包含倾斜体和斜体, 包含多个不同角度的倾斜体, 或上述多种情况的任意组合。 字体匹配过程将选择一个要使用的字体, 其倾斜符号(正或负)与请求的角度一致, 并且(如果存在多个这样的字面)与请求角度最接近。 一般来说,对于请求角度大于或等于 11deg 的情况, 更大的角度更优先; 否则,更小的角度更优先。 (参见 § 5 Font Matching Algorithm。) 对于使用变体的 TrueType / OpenType 字体, 使用 slnt 变体来实现 oblique 取值, 并使用取值为 1 的 ital 变体来实现 italic 取值。

Note: OpenType 的 slnt 轴被定义为 正角度表示逆时针方向的倾斜, 这与 CSS 的方向相反。 CSS 在使用变体生成倾斜体字面时 会考虑到这一点。

在竖排书写模式下, 正值和负值的 oblique 应该向哪个方向倾斜? 我们如何在相反方向上实现倾斜 (竖排书写时需要这种效果)?

如果没有可用的斜体或倾斜体字面, 可以通过对非倾斜字面进行人工倾斜操作 来合成倾斜体字面。 可以使用 font-synthesis 属性禁用 这些合成倾斜体字面的使用。

Note: 虽然可以通过对常规字面的字形进行人工倾斜 来模拟倾斜体, 但这并不等同于真正的倾斜体, 真正的倾斜体在倾斜的同时能正确保持光学笔画粗细。 始终优先使用真正的倾斜字体,而不是依赖合成版本。

在字体匹配的语境下, 用户代理可以将 italic 视为 oblique 的同义词。 对于将这两个取值区分对待的用户代理, 不得对 italic 执行合成。

Note: 作者还应注意,合成方式可能不适用于 某些书写体系,例如西里尔文字,其中斜体形式的字形形状与常规体差异很大。 始终优先使用真正的斜体字体,而不是依赖合成版本。

Note: 许多书写体系缺乏在普通字面文本中混用 手写体形式的传统。 中文、日文和韩文字体几乎总是缺乏斜体或倾斜体字面。 支持多种书写体系的字体 有时会在斜体字面中省略特定书写体系(如阿拉伯文)的字形集合。 在跨字体实现合成时,用户代理在进行 character map 相关假设时应当谨慎, 因为同一家族中斜体字面与罗马体字面 可能具有不同的 character map

2.5. 字体大小:font-size 属性

名称: font-size
取值: <absolute-size> | <relative-size> | <length-percentage [0,∞]> | math
初始值: medium
适用于: 所有元素和文本
是否继承:
百分比: 相对于父元素的字体大小
计算值: 一个绝对长度
规范顺序: 按语法
动画类型: 按计算值类型
Tests

该属性表示字体中字形的期望高度。 对于可缩放字体,font-size 是应用于字体 EM 单位的缩放因子。 对于不可缩放字体,font-size 会被转换为绝对单位, 并与字体声明的字体大小进行匹配, 二者使用相同的绝对坐标空间。

Note: 对字形应当与其 EM 盒的契合程度 没有任何要求。 各个字体在同一 font-size 下渲染时, 其表观视觉大小可能不同。 此外,字形的渲染可能任意远地超出其 EM 盒; 如果溢出其包含块, 则可能引发墨水溢出(ink overflow)

取值含义如下:

<absolute-size>
<absolute-size> 关键字引用 用户代理计算并维护的字体大小表中的某一项。 参见 § 2.5.1 绝对大小关键字映射表

可能的取值为:

[ xx-small | x-small | small | medium | large | x-large | xx-large | xxx-large ]
<relative-size>
<relative-size> 关键字 是相对于父元素的计算后 font-size 以及字体大小表进行解释的。可能取值为:
[ larger | smaller ]

如果父元素在绝对大小关键字映射表中具有关键字字体大小, larger 可以将字体大小计算为表中的下一项, 而 smaller 可以将字体大小计算为上一项。 例如,如果父元素的字体大小是 font-size:medium, 为子元素指定 larger 值 可以使其字体大小为 font-size:large

用户代理也可以不使用上述关键字表中的前后项, 而改用一个简单的比例, 相对于父元素来放大或缩小字体大小。 具体比例未作规定, 但应在 1.2–1.5 左右。 不同元素之间该比例可以不同。

Note: 视力受损的用户可能会要求用户代理 使用比默认值更大的比例, 以帮助提高可读性。 另外,用户代理在检测到段落文本与标题文本时 也可以选择使用不同的比例。

<length-percentage [0,∞]>
长度值指定一个绝对字体大小 (独立于用户代理的字体表)。 负长度是无效的。

百分比值指定一个绝对字体大小, 相对于父元素计算后的 font-size。 负百分比是无效的。

Note: 使用百分比值或字体相对长度 (例如 emrem) 有助于获得更健壮且更易级联的样式表。

math
在确定 font-size 属性的计算值时, 必须应用特殊的 数学缩放规则
下列样式表演示了 各种指定字体大小的方式。
p { font-size: 12pt; }
blockquote { font-size: larger }
em { font-size: 150% }
em { font-size: 1.5em }

Note: 由于 font-size-adjust, 该属性的使用值(used value) 可能与其计算值不同。 但是,子元素继承的是计算后的 font-size, 它不受 font-size-adjust 影响 (否则 font-size-adjust 的效果会被叠加)。

由于某些字体大小不可用, 该属性的实际值可能与使用值不同。

可以通过限制 font-size 来实现响应式排版。
font-size: clamp(10px, ..., 36px);

2.5.1. 绝对大小关键字映射表

下表为用户代理提供了绝对大小缩放因子及其与 HTML 标题和绝对字体大小的映射指南。 medium 值用作参考的中间值。 用户代理可以为不同的字体或显示设备类型微调这些值。

CSS 绝对大小(absolute-size)值 xx-small x-small small medium large x-large xx-large xxx-large
缩放系数(scaling factor) 3/5 3/4 8/9 1 6/5 3/2 2/1 3/1
HTML 标题(headings) h6 h5 h4 h3 h2 h1
HTML font 大小(sizes) 1 2 3 4 5 6 7

Note: 在 CSS1 中,相邻索引之间建议的缩放系数为 1.5, 但用户体验证明这一数值过大。 在 CSS2 中,针对计算机屏幕,相邻索引之间建议的缩放系数为 1.2, 但这在较小字号上仍然造成问题。 新的缩放系数在各索引之间有所不同,以提供更好的可读性。

为了保持可读性,遵循这些指南的 UA 仍应避免创建每个 EM 单位 少于 9 个设备像素的字体大小。

2.6. 相对大小:font-size-adjust 属性

名称: font-size-adjust
取值: none | <number [0,∞]>
初始值: none
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 一个数字或关键字 none
规范顺序: 按语法
动画类型: 按计算值类型
Tests

对于任意给定的字体大小,不同字体之间 文本的表观大小与有效可读性会有所差异。 对于如拉丁文或西里尔文等区分大小写字母 的双字母表书写体系, 小写字母相对于对应大写字母的相对高度 是决定可读性的关键因素。 这通常被称为 aspect value(纵横比值), 等于字体的 x 高度 除以字体大小。

Note: 对于使用附标记(变音符号)的文本, 过大的 x 高度实际上会降低可读性, 因为附标记会显得过于拥挤。

在发生字体回退的情况下, 回退字体可能与期望的字体家族 不具有相同的纵横比值, 因而可读性会下降。 font-size-adjust 属性是在字体回退发生时, 保持文本可读性的一种方式。 它通过调整 font-size, 使得无论使用哪种字体, x 高度都保持不变。

下述样式将 Verdana 定义为期望的字体家族, 但如果 Verdana 不可用,则使用 Futura 或 Times。 其中一段文本还指定了 font-size-adjust。
p {
  font-family: Verdana, Futura, Times;
}
p.adj {
  font-size-adjust: 0.545;
}

<p>Lorem ipsum dolor sit amet, ...</p>
<p class="adj">Lorem ipsum dolor sit amet, ...</p>

Verdana 具有相对较高的纵横比值 0.545, 这意味着小写字母相对于大写字母 相对更高,因此在小字号下文本 依然显得可读。 Times 的纵横比值较低,为 0.447, 因此,如果发生字体回退, 若未同时指定 font-size-adjust, 在小字号下文本的可读性 将不如 Verdana。

下图展示了使用这些字体渲染文本时的对比, 各列分别显示 Verdana、Futura 和 Times。 每一行内所有单元格 使用相同的 font-size 值,并加上红线以显示 x 高度的差异。 在上半部分,每一行都以相同的 font-size 值渲染。 下半部分同样如此, 但在这一部分中还将 font-size-adjust 属性设置为 0.545, 这样实际字体大小会被调整, 以在每一行中保持 Verdana 的 x 高度。 注意下半部分中小字号文本 在各行之间仍保持相对可读。

text with and without 'font-size-adjust'
使用与不使用 font-size-adjust 的文本

该属性允许作者为元素指定一个 aspect value, 以有效地在是否发生替换的情况下 都保持首选字体的 x 高度。 取值含义如下:

none
不保持字体的 x 高度。
<number [0,∞]>
指定用于下面计算中的 aspect value, 用以计算调整后的字体大小:
c  =  ( a / a' ) s

其中:

s  =  font-size 值
a  =  由 aspect value 指定的、'font-size-adjust' 属性的值
a' =  实际字体的 aspect value
c  =  需要使用的调整后 font-size

负值是无效的。

该值适用于任何被选中的字体, 但在典型用法中,它应基于字体列表中 第一个字体的 aspect value。 如果指定得足够准确, 上式中的 (a/a') 项 对于第一个字体而言实际上等于 1, 因此不会发生调整。 如果取值不准确, 在不支持 font-size-adjust 的旧版用户代理中, 使用该家族列表中首个字体渲染的文本 将呈现出不同的显示效果。

font-size-adjust 的取值会影响 font-size 的使用值, 但不会影响其计算值。 它会影响基于字体度量的 相对单位的大小, 例如 exch, 但不会影响 em 单位的大小。 由于 line-height 的数值 是相对于 font-size 的计算值而言的, 因此 font-size-adjust 不影响 line-height 的使用值。

Note: 在 CSS 中,作者通常将 line-height 指定为 font-size 的倍数。 由于 font-size-adjust 属性会影响 font-size 的使用值, 因此在使用 font-size-adjust 时, 作者在设置行高时应特别小心。 在这种情况下,行高设置得过小 会导致文本行彼此重叠。

作者可以通过比较内容相同但 font-size-adjust 属性不同的 span, 来计算给定字体的 aspect value。 如果使用相同的 font-size,且 font-size-adjust 的取值 对于给定字体是准确的,则这两个 span 会对齐。

使用两个带边框的 span 来确定某一字体的 aspect value。 两个 span 的 font-size 相同, 但仅右侧的 span 指定了 font-size-adjust。 从 0.5 的取值开始, 可以调整纵横比值, 直到两个字母周围的边框完全重合。

p {
  font-family: Futura;
  font-size: 500px;
}

span {
  border: solid 1px red;
}

.adjust {
  font-size-adjust: 0.5;
}

<p><span>b</span><span class="adjust">b</span></p>
Futura with an aspect value of 0.5
Futura 的 aspect value 为 0.5 时的示例

右侧的盒子略大于左侧的那个,因此该字体的 aspect value 略小于 0.5。 通过调整该值直到两个盒子对齐即可。

2.7. 简写字体属性: font 属性

名称: font
取值: [ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-width-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'># ] | <system-family-name>
初始值: 见各独立属性
适用于: 所有元素和文本
是否继承:
百分比: 见各独立属性
计算值: 见各独立属性
规范顺序: 按语法
动画类型: 见各独立属性
Tests

该属性的语法基于传统 排版中的速记记法, 用于同时设置多个与字体相关的属性。 出于历史及向后兼容性的原因, 它几乎是一个简写属性。

font 属性, 除下文说明的情形外, 是一个用于同时设置 font-stylefont-variantfont-weightfont-widthfont-sizeline-heightfont-family 的简写属性, 它们在样式表中的同一位置被设置。

font-variant 属性的取值也可以包含在其中, 但仅限 CSS 2.1 支持的那些值; 在 CSS Fonts Level 3 或 4 中添加的 font-variant 取值 都不能用于 font 简写中:

<font-variant-css2>= normal | small-caps

font-width 属性的取值也可以包含在其中, 但仅限 CSS Fonts Level 3 支持的那些, 本规范中新增的任何 font-width 取值 都不能用于 font 简写中:

<font-width-css3>= normal | ultra-condensed | extra-condensed | condensed |
semi-condensed | semi-expanded | expanded | extra-expanded |
ultra-expanded

因此,我们对与字体相关的属性 及其与 font 属性的交互 做如下分类:

显式设置

这些长写属性也可以通过 font 简写属性设置:

隐式重置

这些属性是 font 属性的仅重置子属性(reset-only sub-property), 因此不能通过该简写设置,而是被重置为其初始值:

独立级联

这些属性(尽管属性名以 "font-" 开头) 不是简写属性, 因此既不会被 font 属性设置,也不会被重置:

font 属性的所有子属性中, 属于“显式设置”和“隐式重置”这两组的属性, 都会首先被重置为其初始值。

然后,在“显式设置”组中, 那些在 font 简写中 被显式赋值的属性, 会被设置为这些值。 关于允许的取值与初始值的定义, 见各长写属性的定义。

p { font: 12pt/14pt sans-serif }
p { font: 80% sans-serif }
p { font: x-large/110% "new century schoolbook", serif }
p { font: bold italic large Palatino, serif }
p { font: normal small-caps 120%/120% fantasy }
p { font: condensed oblique 12pt "Helvetica Neue", serif; }
p { font: condensed oblique 25deg 753 12pt "Helvetica Neue", serif; }

在第二条规则中,字号的百分比值(“80%”) 是相对于父元素计算后的 font-size 而言的。 在第三条规则中,行高的百分比(“110%”) 是相对于元素自身的字号而言的。

前三条规则没有显式指定 font-variantfont-weight, 因此这些属性 会获得其初始值(normal)。 注意字体族名称 "new century schoolbook" 因为包含空格, 所以被放在引号中。 第四条规则将 font-weight 设置为 bold, 将 font-style 设置为 italic, 并隐式将 font-variant 设置为 normal

第五条规则设置了 font-variantsmall-caps), font-size(父元素字号的 120%), line-height(该字号的 120%),以及 font-familyfantasy)。 因此关键字 normal 会应用到剩余两个属性: font-stylefont-weight

第六条规则设置了 font-stylefont-widthfont-sizefont-family, 其他字体属性则被设置为它们的初始值。

第七条规则将 font-style 设置为 oblique 25deg, 将 font-weight 设置为 753, 并将 font-width 设置为 condensed。 注意此规则中的 25deg 必须 紧跟在 "oblique" 关键字之后。

由于 font-width 属性在 CSS 2.1 中尚未定义, 因此在 font 规则中使用 font-width 取值时, 作者应额外包含一份适配旧版用户代理的规则:

p {
  font: 80% sans-serif;   /* for older user agents */
  font: condensed 80% sans-serif;
}

系统字体只能整体设置; 即字体族、字号、字重、样式等 必须一次性全部设置。 之后如有需要,可以再单独修改这些值。 如果在某个平台上不存在 具有所指示特征的字体, 用户代理应进行智能替换 (例如,可以使用 caption 字体的缩小版本 作为 small-caption 字体), 或替换为用户代理的默认字体。 与普通字体相同, 如果对于某个系统字体, 某些单独属性 不属于操作系统可用的用户首选项, 则这些属性 应被设置为其初始值。

这也是该属性“几乎”是简写属性的原因: 系统字体只能通过该属性指定, 不能通过 font-family 本身指定, 因此 font 允许作者做到的事情 超出了其子属性的简单总和。 但是,各个独立属性 (例如 font-weight) 仍然会从系统字体中获取相应值, 且可以被独立修改。

注意,上述列出的系统字体关键字 只有在出现在最前面时 才会被当作关键字处理; 在其他位置时,相同的字符串 会被当作字体族名称的一部分处理:

font: menu;        /* 使用系统菜单字体的设置 */
font: large menu;  /* 使用名为 "menu" 的字体族 */
button { font: 300 italic 1.3em/1.7em "FB Armada", sans-serif }
button p { font: menu }
button p em { font-weight: bolder }

如果在某个系统上 用于下拉菜单的字体 正好是,例如, 9 点、字重 600 的 Charcoal, 那么作为 BUTTON 后代的 P 元素 的显示效果等同于 应用了如下规则:

button p { font: 600 9pt Charcoal }

由于 font 简写 会将所有未显式赋值的属性 重置为其初始值, 这与下面的声明 具有相同的效果:

button p {
  font-style: normal;
  font-variant: normal;
  font-weight: 600;
  font-size: 9pt;
  line-height: normal;
  font-family: Charcoal
}

2.8. 控制合成字体

合成字体是一种回退策略,当字体系列缺少合适的字形时,用以提供接近请求字体的替代方案。

例如,用户代理可能:

合成是一种回退策略,因为最终效果,虽然比没有任何字体要好,但并没有达到为此目的设计的字体的质量。

可变字体,设计者提供了一个或多个变化轴,它们算作字体合成,并且它们的使用不受font-synthesis属性的影响。

2.8.1. 控制合成粗体:font-synthesis-weight属性

名称: font-synthesis-weight
值: auto | none
初始值: auto
适用于: 所有元素和文本
是否继承:
百分比: N/A
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
媒体: 视觉
Tests

该属性控制当某个字体家族缺少粗体字面时, 用户代理是否被允许合成粗体字面。

auto
允许合成粗体字面
none
不允许合成粗体字面

2.8.2. 控制合成倾斜:font-synthesis-style属性

名称: font-synthesis-style
取值: auto | none | oblique-only
初始值: auto
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
媒体: 视觉
Tests

该属性控制当某个字体家族缺少倾斜体字面时, 用户代理是否被允许合成倾斜体字面。

auto
允许合成倾斜体字面
none
不允许合成倾斜体字面
oblique-only
允许合成倾斜体字面, 但在指定 italic 时, 不得将其用作回退

在纵向文本中, 对于正的倾斜角度, 字形会被倾斜, 使得行上缘(line-over)向行右侧(line-right)偏移, 而行下缘(line-under)向行左侧(line-left)偏移。 对于负的倾斜角度, 字形会被倾斜, 使得行上缘向行左侧偏移, 而行下缘向行右侧偏移。 倾斜是围绕字形中心进行的。

Tests
synthetic oblique in vertical text
纵向文本中的合成倾斜体,正倾斜角度

2.8.3. 控制合成小型大写字母:font-synthesis-small-caps属性

名称: font-synthesis-small-caps
值: auto | none
初始值: auto
适用于: 所有元素和文本
是否继承:
百分比: N/A
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
测试

该属性控制是否允许用户代理合成小型大写字体字形,当字体系列缺少小型大写字形时。

auto
允许合成小型大写字形
none
不允许合成小型大写字形

2.8.4. 控制合成上标和下标:font-synthesis-position属性

名称: font-synthesis-position
值: auto | none
初始值: auto
适用于: 所有元素和文本
是否继承:
百分比: N/A
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
测试

该属性控制是否要求用户代理为font-variant-position合成上标和下标字形,当字体缺少这些字形时。

auto
要求合成上标和下标字形
none
不允许合成上标和下标字形

2.8.5. 控制合成字体:font-synthesis 简写属性

名称: font-synthesis
值: none | [ weight || style || small-caps || position]
初始值: weight style small-caps position
适用于: 所有元素和文本
是否继承:
百分比: N/A
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
Tests

该属性是 font-synthesis-weightfont-synthesis-stylefont-synthesis-small-capsfont-synthesis-position 这些属性的简写形式。取值的映射如下:

font-synthesis 取值 font-synthesis-weight 取值 font-synthesis-style 取值 font-synthesis-small-caps 取值 font-synthesis-position 取值
none none none none none
weight auto none none none
style none auto none none
small-caps none none auto none
position none none none auto
weight style auto auto none none
weight small-caps auto none auto none
weight position auto none none auto
style small-caps none auto auto none
style position none auto none auto
small-caps position none none auto auto
weight style small-caps auto auto auto none
weight style position auto auto none auto
weight small-caps position auto none auto auto
style small-caps position none auto auto auto
weight style small-caps position auto auto auto auto
下面的样式规则禁用了阿拉伯文的合成倾斜体:
*:lang(ar) { font-synthesis: none; }

3. 字体渲染控制

3.1. 字体渲染控制介绍

使用 @font-face 下载 Web 字体时,用户代理需要知道在字体加载过程中该如何处理。 大多数浏览器采用了一定的超时机制:

浏览器 超时 回退 替换
Chrome 35+ 3 秒
Opera 3 秒
Firefox 3 秒
Internet Explorer 0 秒
Safari 3 秒

尽管这些默认行为在某种程度上是合理的,但在不同浏览器之间不一致。 更糟的是,没有一种方法能够覆盖现代用户体验和性能敏感的应用程序所需的所有用例。

Font Loading API [CSS-FONT-LOADING-3] 允许开发者覆盖上述行为, 但这需要编写脚本,且需要大量的工作,并最终无法覆盖 所有 合理的情况。 此外,开发者需要将加载脚本内联到页面中或加载外部库,这会引入额外的网络延迟,进而延迟文本渲染。

注重设计/性能的 Web 开发者通常非常清楚特定 Web 字体对用户体验的重要性。 本规范为开发者提供了控制字体超时和渲染行为的能力。 具体来说,它允许开发者:

3.2. 字体显示时间线

当用户代理首次尝试在页面上使用下载的字体时,启动该字体的字体下载计时器。 该计时器经历三个与字体相关的时间段——阻止期交换期失败期——这决定了使用该字体的任何元素的渲染行为:

要为某个元素使用回退字体进行渲染, 用户代理必须找到该元素的font-family列表中已加载的第一个字体,并使用该字体渲染文本。 执行此操作时不得触发任何回退字体的加载。

要为某个元素使用不可见的回退字体进行渲染, 按照“使用回退字体进行渲染”的方式找到一个字体。 创建一个匿名字体,其指标与选定字体相同,但所有字形均为“不可见”(不包含“墨水”),并使用该字体渲染文本。 执行此操作时不得触发任何回退字体的加载。

fallbackoptional 可能会导致同一字体家族中的某些字体被使用,而其他字体被要求回退,从而呈现出“赎金信”效果。 或许应要求同一字体家族的所有字体具有相同的行为(全部替换或全部回退)? 另见 @font-feature-values,用于基于字体家族控制行为。

4. 字体资源

4.1. @font-face 规则

@font-face 规则允许链接到需要时自动获取和激活的字体。 这使作者可以选择与页面设计目标更匹配的字体,而不是限制在给定平台上可用的一组字体中。 一组字体描述符定义了字体资源的位置,可以是本地的或外部的,并且定义了单个字体的样式特征。 可以使用多个 @font-face 规则来构建具有各种字形的字体家族。 使用 CSS 字体匹配规则,用户代理可以有选择地仅下载需要用于特定文本的字形。

其语法为:

@font-face {
  <declaration-list>
} 
测试

@font-face 规则接受此规范中定义的描述符。

每个 @font-face 规则为每个字体描述符指定一个值,隐式或显式。 在规则中未给出显式值的描述符将采用此规范中列出的初始值。 这些描述符仅适用于定义它们的 @font-face 规则上下文内,不适用于文档语言元素。 没有哪个元素适用这些描述符的概念,也没有值是否由子元素继承的概念。 当给定描述符在某个 @font-face 规则中多次出现时,只有最后一个描述符声明会被使用,之前的所有声明都会被忽略。

使用一个名为 Gentium 的可下载字体:
@font-face { 
font-family: Gentium; 
src: url(http://example.com/fonts/Gentium.woff); 
}

p { font-family: Gentium, serif; } 

用户代理将下载 Gentium 并在渲染段落元素时使用它。如果由于某种原因字体站点不可用,将使用默认的 serif 字体。

一组 @font-face 规则定义了一组字体,可以在包含这些规则的文档中使用。 当进行字体匹配时,使用这些规则定义的字体优先于系统上的其他可用字体。

下载的字体仅对引用它们的文档可用。激活这些字体的过程不应使它们对其他应用程序或未直接链接到相同字体的文档可用。 用户代理实现者可能认为在没有其他可用字体的情况下使用下载的字体来渲染其他文档中的字符是方便的,作为“已安装字体回退”程序的一部分。 然而,这会导致安全泄露,因为一个页面的内容可能会影响其他页面,攻击者可能会利用此作为攻击途径。 这些限制不影响缓存行为,字体的缓存方式与其他网络资源相同。

Tests

此 at 规则遵循 CSS 的前向兼容解析规则。 像声明块中的属性一样,用户代理不支持的描述符声明必须被忽略。@font-face 规则需要字体系列和 src 描述符; 如果缺少其中任何一个,@font-face 规则在执行字体匹配算法时不应被考虑。

在用户代理资源有限或实现了禁用可下载字体资源的能力的情况下,@font-face 规则应被简单忽略; 各个描述符的行为应如本规范所定义,不应被更改。

4.2. 字体家族:font-family 描述符

名称: font-family
适用于: @font-face
值: <family-name>
初始值: N/A

此描述符定义了将用于所有 CSS 字体家族名称匹配的字体家族名称。 它会覆盖基础字体数据中包含的字体家族名称。 如果字体家族名称与给定用户环境中可用的字体家族相同, 它会有效地隐藏基础字体,从而影响使用该样式表的文档。 这使网页作者可以自由选择字体家族名称,而无需担心与给定用户环境中存在的字体家族名称冲突。 同样,平台替代给定字体家族名称的情况不应被使用。

4.3. 字体引用:src 描述符

名称: src
适用于: @font-face
值: <font-src-list>
初始值: N/A

此描述符指定包含字体数据的资源。 它的值是以逗号分隔的优先列表,可以是外部引用或本地安装的字体字形名称。 当需要字体时,用户代理会迭代列出的引用集,使用它能够成功解析并激活的第一个引用。 解析此描述符比解析其他描述符更复杂;请参阅 § 4.3.1 解析 src 描述符 以获取解析规则。 激活字体涉及下载文件或从磁盘读取它,解析它,可能还有额外的用户代理依赖步骤。 包含无效数据的字体或未找到的本地字体字形会被忽略,用户代理会加载列表中的下一个字体。

4.3.1. 解析 src 描述符

要解析 <font-src-list> 这一产生式时,应按 CSS 语法解析一个逗号分隔列表, 其元素为多个 <font-src>

<font-src> = <url> [ format( <font-format> ) ]? [ tech( <font-tech># ) ]?
  | local( <family-name> )
<font-format>= [ <string> | collection | embedded-opentype | opentype
  | svg | truetype | woff | woff2 ]
<font-tech>= [ <font-features-tech> | <color-font-tech>
  | variations | palettes | incremental ]
<font-features-tech>= [ features-opentype | features-aat | features-graphite ]
<color-font-tech>= [ color-COLRv0 | color-COLRv1 | color-SVG | color-sbix | color-CBDT ]
Tests

虽然推荐使用关键字来标识字体格式, 但出于向后兼容性的原因,下列字符串形式也被接受, 并且与使用等效的现代语法具有相同效果。

字符串形式 等效语法
format("woff2") format(woff2)
format("woff") format(woff)
format("truetype") format(truetype)
format("opentype") format(opentype)
format("collection") format(collection)
format("woff2-variations") format(woff2) tech(variations)
format("woff-variations") format(woff) tech(variations)
format("truetype-variations") format(truetype) tech(variations)
format("opentype-variations") format(opentype) tech(variations)
Tests

Note: CSS 工作组预计不会在将来扩展这份格式字符串列表。

如果某个组件值被正确解析, 且其属于 UA 所支持的某种字体格式字体技术(font tech), 则将其加入到“受支持来源”的列表中。 如果解析组件值时产生解析错误, 或其格式或技术不受支持, 则不要将其加入“受支持来源”的列表中。

如果在该过程结束时不存在任何受支持的条目, 则 src 描述符的值即为解析错误。

这些解析规则允许在某些用户代理 不支持特定字体技术或字体格式时, 实现字体的优雅回退。

例如, 当不支持增量传输时, 会提供该字体的 woff2 压缩版本, 以获得最佳性能。 随后,对于 增量传输, 会提供原始未压缩的 OpenType 字体, 其中的各部分会按需加载。
@font-face {
  font-family: "MyIncrementallyLoadedWebFont";
  src: url("FallbackURLForBrowsersWhichDontSupportIncrementalLoading.woff2") format("woff2");
  src: url("MyIncrementallyLoadedWebFont.otf") format(opentype)  tech(incremental);
}

4.3.2. 加载 src 描述符中的单个项目

与 CSS 中的其他 URL 一样,该 URL 可以是相对路径,此时它将相对于包含 @font-face 规则的样式表的位置进行解析。对于 SVG 字体,该 URL 指向包含 SVG 字体定义的文档中的某个元素。如果省略元素引用,则默认引用第一个定义的字体。同样,能够包含多个字体的字体容器格式必须为给定的 @font-face 规则加载且仅加载一个字体。使用片段标识符来指示加载哪个字体;这些片段使用 [RFC8081] 中定义的字体的 PostScript 名称。

测试

兼容的用户代理在下面情况下不得使用该资源中的字面: 除非其 PostScript 名称与片段标识符完全匹配; 若给定的片段标识符 不可能是有效的 PostScript 名称, 则必须跳过下载该资源。

src: url(fonts/simple.woff);       /* 相对于样式表位置加载 simple.woff */
src: url(/fonts/simple.woff);      /* 从绝对路径加载 simple.woff */
src: url(fonts/coll.otc#foo);      /* 从集合 coll.otc 加载字体 foo */
src: url(fonts/coll.woff2#foo);    /* 从 woff2 集合 coll.woff2 加载字体 foo */
src: url(fonts.svg#simple);        /* 加载 ID 为 'simple' 的 SVG 字体 */

4.3.3. 选择 src 中的项目

外部引用由 URL 组成,后跟一个可选的提示,用于描述该 URL 引用的字体资源的格式。如果格式提示表明字体格式不受支持或未知,或用户代理不支持任何字体技术,则符合规范的用户代理必须跳过下载该字体资源。如果没有提供格式提示,用户代理应下载字体资源。

例如,以下示例展示了如何在可能的情况下加载 WOFF 2 字体,否则加载 WOFF 1,若都不支持则使用 OpenType 字体:
@font-face {
font-family: bodytext;
src: url(ideal-sans-serif.woff2) format("woff2"),
    url(ideal-sans-serif.woff) format("woff"),
  url(basic-sans-serif.ttf) format("opentype");
}
在此示例中,如果不支持 woff2,将跳过不受支持的虚构 "zebra" 格式,下载 opentype 字体:
src: url(ideal.woff2) format("woff2"),url(unsupported.zeb) format("zebra"),
url(basic.ttf) format("opentype");
此示例展示了如何加载集合中的单个实例,或者如果不支持集合,则下载单个字体:
@font-face {
  font-family: 源ノ角ゴシック Code JP;
  src: url(SourceHanCodeJP.otc#Regular) format("collection"),  
    url(SourceHanCodeJP-Regular.ttf) format("opentype");  
}
4.3.3.1. 本地字体回退

当作者希望优先使用 某个字体的本地可用副本, 且在不可用时再进行下载时, 可以使用 local()。 传递给 local() 的本地已安装 <family-name> 参数, 是一个与具体格式相关的字符串, 用于在更大的字体族中 唯一标识某个字体字面。 该名称可以选择性地用引号括起来。 如果不加引号, 则适用非引号字体族名称的处理约定; 换句话说, 该名称必须是由多个标识符 通过空白分隔而成的序列, 并通过将这些标识符 以单个空格连接在一起 转换为一个字符串; 因此, 像 CSS 全局关键字(CSS‑wide keywords)如 inherit, 以及 <generic-family> 关键字如 serif 都不允许出现在 local() 中。

/* Gentium 的常规字面 */
@font-face {
  font-family: MyGentium;
  src: local(Gentium),    /* 优先使用本地可用的 Gentium */
    url(Gentium.woff);  /* 否则,从网络下载 */
}
例如,下面这种对 local() 的使用就是错误的:
@font-face {
  font-family: foo;
  src: local(inherit);
}

对于 OpenType 和 TrueType 字体, 该字符串仅用于匹配本地可用字体的 PostScript 名称 或完整字体名称(full font name), 匹配哪一种名称会因平台 与字体而异, 因此作者应同时包含这两种名称, 以确保跨平台正确匹配。 不得使用针对给定字体名称的 平台替换名称。

/* Gentium 的粗体字面 */
@font-face {
  font-family: MyGentium;
  src: local(Gentium Bold),    /* 完整字体名称 */
    local(Gentium-Bold),    /* PostScript 名称 */
    url(GentiumBold.woff);  /* 否则,从网络下载 */
  font-weight: bold;
}

正如一条 @font-face 规则 用于指定一个字体家族中 某个单独字体的特征一样, 与 local() 搭配使用的唯一名称 也只指定单个字体, 而不是整个字体家族。 以 OpenType 字体数据来描述, PostScript 名称位于字体的 name 表中, 名称记录的 nameID = 6 (更多细节参见 [OPENTYPE])。 PostScript 名称是在 OSX 上 所有字体普遍使用的键, 也是 Windows 上 PostScript CFF 字体的键。 而完整字体名称(nameID = 4)则作为唯一键, 被用于 Windows 上 具有 TrueType 字形的字体。

对于具有多种本地化完整字体名称的 OpenType 字体, 必须使用美式英语版本 (Windows 的语言 ID = 0x409,Macintosh 的语言 ID = 0), 或在不存在美式英语完整字体名称时, 使用第一个本地化名称 (OpenType 规范建议 所有字体 至少应包含美式英语名称)。 对于还会匹配其他完整字体名称的用户代理, 例如在当前系统区域设置为荷兰语时 匹配荷兰语名称, 都被视为不符合规范。

Note: 这样做并不是为了偏好英语, 而是为了避免跨字体版本与操作系统本地化之间的 匹配不一致, 因为字体样式名称(例如 “Bold”) 往往会被本地化为多种语言, 而可用本地化的集合 会随着平台和字体版本而有很大差异。

对将“家族名称(nameID = 1)与 样式名称(nameID = 2)拼接”进行匹配的用户代理, 也视为不符合规范。

Note: 这同样可以用来引用 属于更大字体家族但 否则无法单独引用的字面。

使用本地字体,或引用另一文档中的 SVG 字体:
@font-face {
  font-family: Headline;
  src: local(Futura-Medium),
    url(images/fonts.svg#MyGeometricModern) format("svg");
}

为不同平台上的本地日文字体创建一个别名:

@font-face {
  font-family: jpgothic;
  src: local(HiraKakuPro-W3), local(Meiryo), local(IPAPGothic);
}

引用一个在更大字体家族中 无法通过常规方式匹配到的字体字面:

@font-face {
  font-family: Hoefler Text Ornaments;
  /* 其字体属性与 Hoefler Text Regular 相同 */
  src: local(HoeflerText-Ornaments);
}

由于本地化的完整名称永远不会匹配, 因此即使某个系统的区域参数被设置为芬兰语, 下面这些标题样式规则的文档 也始终会使用默认的 serif 字体进行渲染:

@font-face {
  font-family: SectionHeader;
  src: local("Arial Lihavoitu");  /* Arial Bold 的芬兰语完整名,应当匹配失败 */
  font-weight: bold;
}

h2 { font-family: SectionHeader, serif; }

在下面这个例子中,对于一个符合规范的用户代理来说, 永远不会加载字体 ‘gentium.eot’, 因为它包含在第一次对 src 描述符的定义中, 而该定义在同一条 @font-face 规则中 被第二次定义所覆盖:

@font-face {
  font-family: MainText;
  src: url(gentium.eot);                     /* 用于较老的用户代理 */
  src: local("Gentium"), url(gentium.woff);  /* 覆盖前面的 src 定义 */
}

4.4. 字体属性描述符:font-stylefont-weight,和 font-width 描述符

名称: font-style
用于: @font-face
取值: auto | normal | italic | left | right | oblique [ <angle [-90deg,90deg]>{1,2} ]?
初始值: auto
名称: font-weight
用于: @font-face
取值: auto | <font-weight-absolute>{1,2}
初始值: auto
名称: font-width
用于: @font-face
取值: auto | <'font-width'>{1,2}
初始值: auto
Tests

这些描述符定义了某个字体字面的特征, 并在样式与具体字面之间的匹配过程中被使用。 对于由多条 @font-face 规则定义的字体家族, 用户代理可以选择下载该家族中的所有字面, 也可以利用这些描述符, 仅选择性地下载与文档中实际使用样式相匹配的字体字面。 这些描述符的取值含义 与对应字体属性的含义相同, 只不过不允许使用相对关键字 bolderlighter。 如果省略这些描述符, 则假定为初始值。 如果指定的取值超出了同名属性 所接受取值的范围, 则该描述符被视为解析错误。

在这三个描述符中,允许使用区间来替代单一取值。 当给出单一取值时, 它的含义与起止点相同的区间一致。 用户代理必须对区间的起点与终点的计算值进行交换, 以禁止递减区间。 区间的两个端点都是包含性的。 这些区间会在下面的 字体匹配算法 中被使用。

Tests

这三个描述符的 auto 取值具有如下效果:

这些字体字面样式属性的取值 会替代底层字体数据所隐含的样式。 这使得作者可以灵活组合字面, 即便在原始字体数据的组织方式不同的情况下也是如此。 实现了合成粗体与合成倾斜的用户代理, 必须仅在字体描述符暗示需要合成时 才进行合成样式处理, 而不能依据字体数据本身隐含的样式属性。 但是,应用于通过 '@font-face' 定义的字体的变体取值, 将会同时被截断到这些描述符中指定的取值范围 (或者由变体参数的应用所暗示的范围, 比如通过调整 wght 轴 以满足请求的 font-weight), 以及字体文件自身所支持的取值范围之内。

Tests
本节定义的这些字体描述符 用于在由某个字体家族的 @font-face 规则所定义的字体集合中, 选择一个具体字体字面。

考虑一个仅包含单个常规字面的家族:

@font-face {
  font-family: BaskervilleSimple;
  src: url(baskerville-regular.woff2);
}

未加样式的文本会使用 在该 @font-face 规则中定义的常规字面来显示:

regular face display

然而,对于斜体文本, 由于没有单独定义斜体字面, 大多数用户代理会使用来自常规字面的 合成倾斜字形来显示:

synthetic italics display

现在考虑一个为其定义了真实斜体字面的家族:

@font-face {
  font-family: BaskervilleFull;
  src: url(baskerville-regular.woff2);
}

@font-face {
  font-family: BaskervilleFull;
  src: url(baskerville-italic.woff2);
  font-style: italic;
}

第二条 @font-face 规则 将字体资源 baskerville-italic.woff 定义为具有“正常字重、正常宽度、斜体样式”的字体。 在显示斜体文本时, 用户代理会使用这款字体, 因为它与斜体文本最为匹配。 因此,文本会使用由字体设计师设计的字形来显示, 而不是使用来自常规字面的合成倾斜字形:

real italics display

关于在字体家族中 选择特定字面的过程的更完整细节, 请参见 字体匹配 一节。

字体可以声明其所兼容的 font-weightfont-widthfont-style 的取值范围。
@font-face {
  font-family: Lastima;
  src: url(lastima-varfont.woff2);
  font-weight: 100 399;
}

上面的 @font-face 规则表明: 当 font-weight 处于 100 到 399 之间时, 应使用 lastima-varfont.woff。 视是否还存在其他指定 font-family: Lastima@font-face 规则而定, 对于超出 100–399 范围的 font-weight 取值, 也可能会使用 lastima-varfont.woff。 更多细节见 § 5 字体匹配算法

上文所示, 多条 @font-face 规则可以被合并为 一个家族, 跨越多个 font-weightfont-width 和/或 font-style 范围:

@font-face {
  font-family: Lastima;
  src: url(lastima-varfont-lightrange.woff2);
  font-weight: 100 399;
}
@font-face {
  font-family: Lastima;
  src: url(lastima-varfont-heavyrange.woff2);
  font-weight: 400 700;
}

上述 @font-face 规则表明: 当 font-weight 处于 100 到 399 之间时, 应使用 lastima-varfont-lightrange.woff; 而当 font-weight 处于 400 到 700 之间时, 应使用 lastima-varfont-heavyrange.woff

4.4.1. 字体宽度:font-stretch 旧名称别名

出于历史原因, 一个 font-stretch 描述符存在 它是一个 遗留名称别名 并以与 font-width 描述符 相同的方式运行。

测试

4.5. 字符范围: unicode-range 描述符

名称: unicode-range
用于: @font-face
取值: <unicode-range-token>#
初始值: U+0-10FFFF
Tests

该描述符定义了声明所针对的字体字面 可能支持的 Unicode 码位集合。 描述符的值是一个由逗号分隔的 Unicode 范围记号 (<unicode-range-token>)列表。 这些范围的并集定义出一组码位, 在用户代理决定是否为某段文本 下载某个字体资源时, 该集合会作为提示信息使用。

每个 <unicode-range-token> 值 是由前缀 "U+" 或 "u+" 与 下列三种形式之一的码位范围组合而成的记号。 不符合这几种形式之一的范围均为无效, 并会导致整个声明被忽略。

单个码位(例如 U+416)
一个 Unicode 码位,以一到六位十六进制数字表示
区间范围(例如 U+400-4ff)
由两个 Unicode 码位组成, 以连字符连接, 表示一个范围的起始与结束码位(包含端点)
通配范围(例如 U+4??)
由尾部的 '?' 字符所隐含的码位集合定义, 其中 '?' 表示任意十六进制数字

单个码位使用与 Unicode 字符码位 对应的十六进制值来书写。 Unicode 码位值必须位于 0 到 10FFFF(含)之间。 码位数字的大小写 按 ASCII 不区分大小写。 对于区间范围, 起始与结束码位必须都在上述范围之内, 且结束码位必须大于或等于起始码位。

使用 ‘?’ 指定的通配范围如果缺少 开头数字(例如 "U+???"),仍然是合法的, 等价于带有前导零数字的通配范围 (例如 "U+0???" = "U+0000-0FFF")。 超出 Unicode 码位范围的通配范围是无效的。 因此,尽管 UNICODE-RANGE 记号最多接受六个尾随 '?', 但在这里尾随 '?' 的最大数量为五。

在某个 unicode-range 描述符声明中, 逗号分隔的 Unicode 范围列表之内 允许出现重叠范围。 这些范围的并集定义了 可以使用对应字体的码位集合。 对于该集合之外的码位, 用户代理不得下载或使用该字体。 用户代理可以将范围列表规约为一个不同的列表, 只要其所表示的码位集合保持不变即可。

关联的字体可能并不包含 unicode-range 描述符所定义的完整码位集合的所有字形。 当使用该字体时, 有效字符映射 (effective character map)unicode-range 所定义的码位集合 与字体字符映射(character map) 的交集。 这使得作者可以通过较宽泛的范围 来定义支持范围, 而无需关心底层字体 实际支持的精确码位区间。

4.5.1. 使用字符范围定义复合字体

对于同一字体家族及样式描述符取值, 可以通过多条具有不同 Unicode 范围的 @font-face 规则, 构造出混合字体, 即:针对不同书写系统,从不同字体中混合使用字形。 这既可以用来组合各自仅包含单一书写系统字形的字体 (例如拉丁、希腊、西里尔), 也可以被作者用来将字体拆分为“常用字符字体” 与“不常用字符字体”。 由于用户代理只会拉取其所需的字体, 这有助于降低页面带宽。

如果一组 @font-face 规则 在具有相同家族及样式描述符取值的前提下 其 Unicode 范围彼此重叠, 则这些规则按其定义顺序的逆序排列; 也就是说,后定义的规则 在针对某个字符检查时会被优先检查。

一些针对特定语言或字符的示例范围:

unicode-range: U+A5;
单个码位:日元/人民币符号
unicode-range: U+0-7F;
基本 ASCII 字符的码位范围
unicode-range: U+590-5ff;
希伯来字符的码位范围
unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;
涵盖日文汉字、平假名、片假名字符, 以及日元/人民币符号的码位范围
BBC 提供多种语言的新闻服务, 其中许多语言在各个平台上的支持并不完善。 通过一条 @font-face 规则, BBC 可以为任意这些语言提供字体, 就像它已经通过手动字体下载所做的那样。
@font-face {
  font-family: BBCBengali;
  src: url(fonts/BBCBengali.woff) format("woff");
  unicode-range: U+00-FF, U+980-9FF;
}
技术文档通常需要大量符号。 STIX Fonts 项目旨在以标准化方式 提供用于广泛技术排版的字体。 下面的示例展示了一个字体的使用场景, 该字体为 Unicode 中许多 数学和技术符号范围提供了字形:
@font-face {
  font-family: STIXGeneral;
  src: local(STIXGeneral), url(/stixfonts/STIXGeneral.otf);
  unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
}
本示例展示了作者如何覆盖 日文字体中用于拉丁字符的字形, 改为使用另一字体中的字形。 第一条规则未指定范围,因此默认为整个范围。 第二条规则指定的范围与其重叠, 但因后定义而具有更高优先级。
@font-face {
  font-family: JapaneseWithGentium;
  src: local(MSMincho);
  /* 未指定范围,默认为整个范围 */
}

@font-face {
  font-family: JapaneseWithGentium;
  src: url(../fonts/Gentium.woff);
  unicode-range: U+0-2FF;
}
考虑这样一个家族: 为了优化带宽,将拉丁、日文及其他字符 分拆到不同的字体文件中:
/* 回退字体 - 大小:4.5MB */
@font-face {
  font-family: DroidSans;
  src: url(DroidSansFallback.woff);
  /* 未指定范围,默认为整个范围 */
}

/* 日文字形 - 大小:1.2MB */
@font-face {
  font-family: DroidSans;
  src: url(DroidSansJapanese.woff);
  unicode-range: U+3000-9FFF, U+ff??;
}

/* 拉丁、希腊、西里尔以及部分
  标点与符号 - 大小:190KB */
@font-face {
  font-family: DroidSans;
  src: url(DroidSans.woff);
  unicode-range: U+000-5FF, U+1e00-1fff, U+2000-2300;
}

对于简单的拉丁文本,只会下载拉丁字符对应的字体:

body { font-family: DroidSans; }

<p>This is that</p>

在这种情况下,用户代理首先检查 包含拉丁字符的字体(DroidSans.woff)的 unicode-range。 由于上述所有字符都落在 U+0-5FF 范围内, 用户代理会下载该字体并用其渲染文本。

再看一个使用箭头字符(⇨)的文本:

<p>This &#x21e8; that<p>

用户代理再次先检查 拉丁字符字体的 unicode-range。 由于 U+2000-2300 包含该箭头码位(U+21E8), 用户代理会下载该字体。 不过,对于这个字符来说, 拉丁字体内并无匹配字形, 因此用于字体匹配的有效 unicode-range 会将该码位排除在外。 接着,用户代理评估日文字体: 日文字体的 unicode-range(U+3000-9FFF 和 U+ff??) 并不包含 U+21E8, 因此用户代理不会下载该日文字体。 然后,轮到回退字体被考虑: 回退字体的 @font-face 规则未定义 unicode-range, 因此其取值默认为全部 Unicode 码位范围。 回退字体会被下载, 并用于渲染该箭头字符。

4.6. 字体特性与变体:font-feature-settingsfont-variation-settings 描述符

名称: font-feature-settings
用于: @font-face
取值: normal | <feature-tag-value>#
初始值: normal
Tests
名称: font-variation-settings
用于: @font-face
取值: normal | [ <string> <number>]#
初始值: normal
Tests

这些描述符定义了在由某条 @font-face 规则所定义的字体 被渲染时应用的初始设置。 它们不会影响字体选择。 取值与下文定义的对应 font-feature-settingsfont-variation-settings 属性完全相同, 只是省略了CSS 全局关键字。 当同时使用多条字体特性描述符、属性或变体, 并可选地与某个具名实例一起使用时, 它们对文本渲染的累积效果 在下文 § 7 字体特性与变体解析 中有详细说明。

这些描述符是在 @font-face 规则所表示的字体对象上 设置特性与变体取值, 而不是在整个元素上设置。 因此,在使用这些描述符时, 由于 § 5.3 字簇匹配, 同一元素中 只有部分字形可能会以该特性进行渲染。

4.7. 使用可变字体中的命名实例:font-named-instance 描述符

名称: font-named-instance
用于: @font-face
取值: auto | <string>
初始值: auto

如果 font-named-instance 描述符 被设置为除 auto 之外的值, 那么在 § 7 Font Feature and Variation Resolution 中相应阶段, 将会检查字体文件, 以在字体中找到第一个具名实例, 其本地化名称依据 § 5.1 Localized name matching 中给出的规则, 与给定的 <string> 相等。 如果不存在这样的具名实例, 则该描述符会被当作取值为 'font-named-instance/auto' 来处理。 否则,该具名实例的变体轴取值 将在 § 7 Font Feature and Variation Resolution 的该位置被应用。

例如,下面这个 @font-face 代码块 会应用名为 "Grotesque" 的实例, 但会将 "XHGT" 轴覆盖为取值 0.7。
@font-face {
  font-family: "AccuroVar";
  src: url("accurovar.otf") format("opentype");
  font-named-instance: "Grotesque";
  font-variation-settings: "XHGT" 0.7;
}

Note: 由于在 font-weightfont-widthfont-style 这些属性中提供的变体轴取值 会先于 font-named-instance 描述符中的取值被应用, 因此在需要使用具名实例时, 无需更改这些属性的取值。

4.8. 字体请求指南

4.8.1. 字体加载指南

@font-face 规则旨在支持字体资源的按需加载, 即仅在文档实际使用时才下载字体。 一个样式表可以包含一整套字体库的 @font-face 规则, 其中只会用到一小部分;用户代理 必须只下载在给定页面的可用样式规则中被引用到的那些字体。 若用户代理在不考虑这些字体是否真的在页面中被使用的情况下, 直接下载所有 @font-face 规则中定义的字体, 则被视为不符合规范。 在字符回退等情况下可能触发字体下载时, 若某个字体包含在某段文本运行的 font-family 计算值内, 用户代理可以选择下载该字体。

@font-face {
  font-family: GeometricModern;
  src: url(font.woff);
}

p {
  /* 对于包含 p 元素的页面会下载该字体 */
  font-family: GeometricModern, sans-serif;
}

h2 {
  /* 对于包含 h2 元素的页面可能会下载该字体,即使本地已存在 Futura */
  font-family: Futura, GeometricModern, sans-serif;
}

当文本内容在可下载字体尚不可用之前就被加载时, 用户代理必须根据该 @font-face 代码块中的 font-display 描述符 来渲染文本。 若字体下载失败,用户代理必须 以可见的方式显示文本。 建议作者在其字体列表中 使用在度量上与可下载字体高度接近的回退字体, 以尽可能避免大幅页面回流。

4.8.2. 字体获取要求

要在给定被选中的 <url> url 和某条 @font-face rule 的条件下 获取字体(fetch a font), 按如下方式抓取 url: 其中 ruleOrDeclaration 为 rule, destination 为 "font", CORS 模式为 "cors", 且 processResponse 为在给定 响应 res 以及 null、failure 或某个 字节流 stream 时执行的如下步骤:
  1. stream 为 null,则直接返回。

  2. 依据其类型, 从 stream 中加载字体。

Note: 这对作者的意义在于, 字体在跨源的情况下通常不会被加载, 除非作者明确采取步骤允许跨源加载。 站点可以通过 HTTP 头 Access-Control-Allow-Origin 显式允许跨站点加载字体数据。 对于其他方案(scheme), 除了 fetch 算法所允许的内容外, 未定义或要求任何额外的显式跨源加载机制。

Tests
对于下面的示例,假设文档位于 https://example.com/page.html, 且所有 URL 均指向用户代理支持的 有效字体资源。

使用下面这些 src 描述符取值定义的字体会被加载:

/* 同源(即域名、scheme、端口与文档一致) */
src: url(fonts/simple.woff);

/* 无重定向的数据 URL 被视作同源 */
src: url("data:application/font-woff;base64,...");

/* 跨源,不同域名 */
/* 响应头中设置了 Access-Control-Allow-Origin: '*' */
src: url(http://another.example.com/fonts/simple.woff);

使用下面这些 src 描述符取值定义的字体将加载失败:

/* 跨源,不同 scheme *//* 响应中没有 Access-Control-xxx 头 */
src: url(http://example.com/fonts/simple.woff);

/* 跨源,不同域名 */
/* 响应中没有 Access-Control-xxx 头 */
src: url(http://another.example.com/fonts/simple.woff);

4.9. 按字体字面控制显示:font-display 描述符

font-display 描述符用于 @font-face, 根据字体何时以及是否被下载并可用, 决定某个字体字面的显示方式。

Name: font-display
For: @font-face
Value: auto | block | swap | fallback | optional
Initial: auto
Tests

Note: 对于所有这些取值, 用户代理可以使用略有不同的时间长度, 或使用无法直接通过 font-display 语法表达的更复杂行为, 以便为用户提供更实用的体验。 他们也可以允许用户用更理想的方式 覆盖作者选择的行为; 例如强制所有字体的 阻塞期(block period)0s

auto
字体显示策略由用户代理自行决定。

Note: 许多浏览器的默认策略 类似于 block 所指定的行为。

block
为该字体字面提供一个较短的 阻塞期(block period) (大多数情况下建议为 3s), 以及一个无限的 替换期(swap period)

Note: 换句话说,如果字体尚未加载, 浏览器会先绘制“不可见”文本, 一旦字体加载完成即立刻替换为该字体字面。

仅当页面在使用某种特定字体渲染文本 才可用的情况下, 才应使用该取值。 并且只应在少量文本上使用。

例如,设计不佳的“图标字体”可能会把一个“⎙”(打印机)图标 关联到“P”这样的无关字符上, 如果文本改用回退字体显示, 页面上就会到处出现让人困惑的字母, 而不是预期的图标。 在这种情况下,短暂的空白位置 要优于使用回退字体。

(不过,回退字体最终仍会被使用, 因为到最后页面上到处是字符 总比链接之类的内容完全不出现要好。)

更好的解决方案见 可访问性注意事项 一节。

swap
为该字体字面提供一个极短的 阻塞期(block period) (大多数情况下建议为 100ms 或更短), 以及一个无限的 替换期(swap period)

Note: 换句话说,如果字体字面尚未加载, 浏览器会立刻用回退字体绘制文本, 而一旦字体加载完成就立刻替换为该字体字面。

仅当在某种特定字体下渲染文本对页面来说非常重要, 但在任何字体下渲染也能正确传达信息时, 才应使用该取值。 并且只应在少量文本上使用。

例如, 若某网站使用自定义字体渲染其 Logo, 为了品牌形象,正确渲染该 Logo 相当重要, 但即使用任意字体渲染 Logo, 也至少能在不致混淆的情况下传达含义。
fallback
为该字体字面提供一个极短的 阻塞期(block period) (大多数情况下建议为 100ms 或更短), 以及一个较短的 替换期(swap period) (大多数情况下建议为 3s)。

Note: 换句话说,如果字体尚未加载, 初始会用回退字体渲染该字面, 但一旦字体加载完成即进行替换。 然而,如果耗时过长, 则在该页面整个生命周期中 将持续使用回退字体。

该取值应被用于正文字体, 或其他使用所选字体有益且理想, 但用户在看到回退字体下的文本也可以接受的场景。 适合用于大段文本。

例如, 对于大段正文, 最重要的是尽快把文本渲染出来, 以便用户尽快开始阅读。 另外,一旦用户开始阅读, 文本不应突然因为新字体替换而“位移”, 否则会打断阅读, 让用户不得不再去找刚才读到的位置。
optional
若字体能够“立即”被加载完成 (即在文本的“首次绘制”时即可使用), 就使用该字体。

否则,字体会被当作 其 阻塞期替换期 均在加载完成前已到期来处理。 若因此而未使用该字体, 用户代理可以选择中止该字体下载, 或以极低优先级下载。 若用户代理认为这样更有利于用户, 它甚至可以直接不启动该字体下载, 而立即使用回退字体。

带有 optional 的字体 绝不能 在加载过程中 造成页面布局的“跳动”。 用户代理可以选择稍微推迟 使用 optional 字体的元素的绘制, 以便给字体从可能较慢的本地缓存加载的时间, 但一旦文本已经以回退字体绘制到屏幕上, 在该页面的其余生命周期内 就不得再用该 optional 字体重新渲染。

该取值应被用于正文, 或其他仅把所选字体作为装饰性“锦上添花”的文本。 只要“页面在首次访问时尽快可用” 比“用户等待更久以立刻看到完美排版”更重要时, 就应使用该取值。

例如,正文在浏览器默认字体中也能完全可读, 尽管某个可下载字体可能更美观, 且更契合站点的审美。 对于第一次访问站点的用户而言, 通常更关心页面是否能快速使用, 而不是是否一开始就完美呈现所有细节, optional 提供了一个很好的行为。 如果他们之后再次访问, 需要的字体可能已经下载完成, 在不拖慢首次或后续访问的前提下, 为他们提供“预期中的”体验。

对于网络极慢的用户来说, 他们可能永远也见不到“预期中的”体验, 但 optional 确保他们至少能真正 使用 该站点, 而不会因为页面加载过慢而放弃并转向别处。

为尽可能提高 optional 字体在渲染某段文本时 即时可用的概率, 建议用户代理采用一些启发式手段 来加快访问速度或判断何时值得推迟文本渲染, 例如检查字体是否已在 HTML 中预加载, 或在样式表中一旦看到该字体, 就立刻将其从较慢的缓存 移动到更快的内存缓存中 (还未确定它是否会在页面中被使用)。

然而,作者不能依赖这些启发式行为; 必须认识到, optional 取值 可能导致字体永远不会被使用。 如果需要稍微更高的“字体一定会被使用”保证, 作者应考虑改用 fallback 取值。

4.9.1. 通过 @font-feature-values 按字体家族控制显示

font-display 描述符用于 @font-feature-values, 通过为同一字体家族的 @font-face 规则设定“默认”的 font-display 值, 决定该字体家族整体的显示方式。 当某条 @font-face 规则中省略 font-display 时, 若已通过 @font-feature-values 为对应字体家族设置了 font-display 取值, 用户代理会使用该取值, 否则默认为 auto

该机制可用于为整个字体家族设定默认显示策略, 并使开发者能够为那些并不由自己直接控制的 @font-face 规则 设定显示策略。 例如,当字体由第三方字体厂商提供时, 开发者无法控制这些 @font-face 规则, 但仍然可以为该字体家族设定默认的 font-display 策略。 为整个字体家族设定默认策略的能力 对于避免“赎金字条效应” (即字面不统一)也很有用, 因为显示策略会应用于整个字体家族。

Name: font-display
For: @font-feature-values
Value: auto | block | swap | fallback | optional
Initial: auto

4.10. 默认字体语言重写:font-language-override 描述符

Name: font-language-override
For: @font-face
Value: normal | <string>
Initial: normal

该描述符定义了在由某条 @font-face 规则 所定义的字体被渲染时应用的初始设置。 它不会影响字体选择。 其取值与下文中 font-language-override 属性的定义完全相同, 只是省略了 inherit 取值。 当同时使用多条字体特性描述符、属性或变体时, 它们对文本渲染的累积效果 在下文 § 7 Font Feature and Variation Resolution 中有详细说明。

4.11. 默认字体度量重写: ascent-overridedescent-overrideline-gap-override 描述符

Name: ascent-override
For: @font-face
Value: normal | <percentage [0,∞]>
Initial: normal
Tests
Name: descent-override
For: @font-face
Value: normal | <percentage [0,∞]>
Initial: normal
Tests
Name: line-gap-override
For: @font-face
Value: normal | <percentage [0,∞]>
Initial: normal
Tests

ascent-overridedescent-overrideline-gap-override 这几个描述符, 分别定义了字体的 上行度量(ascent metric)下行度量(descent metric) 以及 行间距度量(line gap metric)

当描述符取值为 normal 时, 对应的度量值直接从字体文件中获取。

Note: 用户代理可能会从字体文件中的不同位置 读取这些度量值, 从而导致文本布局出现差异。

当描述符取值为百分比时, 对应度量值按给定百分比 乘以使用中的字体大小来计算。 负值在解析阶段即被视为无效。

同一百分比在不同元素上会根据各自的字体大小解析出不同的数值。
@font-face {
  font-family: overridden-font;
  ascent-override: 50%;
  ...
}

<span style="font-family: overridden-font; font-size: 20px;">
  Outer span content
  <span style="font-size: 150%;">Inner span content</span>
</span>

外层 span 使用的 ascent 值为 10px, 而内层 span 则为 15px。

我们可以重写本地回退字体的度量, 使其与主字体(某个 Web 字体)匹配。 这样在从回退字体切换到主字体时, 可以减少布局位移。
@font-face {
  font-family: cool-web-font;
  src: url("https://example.com/font.woff");
}

@font-face {
  font-family: fallback-to-local;
  src: local(Some Local Font);
  /* 重写度量值以匹配 cool-web-font */
  ascent-override: 125%;
  descent-override: 25%;
  line-gap-override: 0%;
}

<div style="font-family: cool-web-font, fallback-to-local">Title goes here</div>
<img src="https://example.com/largeimage" alt="A large image that you don’t want to shift">

当用户代理完成 Web 字体的加载并切换到使用该字体时, 该图像不会在垂直方向发生位移。

5. 字体匹配算法

下面的算法描述了字体如何与各个文本 run 关联。 对于该 run 中的每个字符, 会选择一个字体家族, 并为该字符选出一个包含相应字形的特定字体字面。

供字体匹配算法使用的 已安装字体集合 被刻意定义为未指定。

默认的已安装字体集合 会因 UA、平台和语言环境而异; 重要的是用户必须能够自定义 哪些已安装字体可用于渲染网页, 以及这些字体(如果有的话) 映射到哪些通用字体族。

UA 可以选择向 Web 暴露所有已安装字体, 无论这些字体是如何安装的; 这样做通常会在国际化方面取得更好的效果, 尤其是对于那些操作系统自带字体 并不支持其主要语言的用户。

UA 也可以选择 初始时不向 Web 暴露任何用户安装字体, 以帮助保护隐私; 因为用户所安装字体的集合 经常被用作跨站点跟踪用户的跟踪向量。 然后用户应能够按自身需求 将字体加入或移出该集合。

UA 还可以选择混合方式:其中一部分用户安装字体 会在初始时为国际化目的而被暴露, 而其他字体则不会。 同样,用户应该能够自定义这一初始集合。

期望 UA 在默认向 Web 暴露哪些字体这一点上 做出有根据的决策, 以在国际化与隐私之间取得平衡。 也期望 UA 提供一种便捷方式, 使用户能够按自身需求 添加或移除字体。

测试

5.1. 本地化名称匹配

某些字体文件格式允许字体样式携带特定字符串的多个本地化版本(例如,字体系列名称或命名实例)。用户代理必须能够识别并正确匹配所有这些名称,无论底层平台的本地化情况、使用的系统 API 或文档编码如何。

例如,对于下列字体,每个字体,作者都可以在 font-family 属性中使用拉丁名称或本地化名称,并且在所有系统上结果都是相同的:
本地化字体系列名称示例
本地化字体系列名称

用户代理必须不区分大小写地匹配这些名称,使用 Unicode 规范中概述的“默认无大小写匹配”算法 [UNICODE]。该算法详述于第 3.13 节“默认大小写算法”。具体而言,算法必须在不规范化相关字符串且不应用任何语言特定调整的情况下进行。该算法指定的大小写折叠方法使用 Unicode 字符数据库的 CaseFolding.txt 文件中状态字段为“C”或“F”的大小写映射。

注意: 对于作者来说,这意味着字体系列名称的匹配是大小写不敏感的,无论这些名称存在于平台字体中,还是样式表中的 @font-face 规则中。作者应确保名称的字符序列与实际的字体系列名称一致,尤其是在使用合并字符(如变音符号)时。例如,包含小写字母 a(U+0061)后跟合并圆环符号(U+030A)的系列名称不会匹配一个外观相同但使用预组合的小写字母 a-ring 字符(U+00E5)而非合并序列的名称。

注意: 实现者应注意验证给定的无大小写字符串比较实现是否使用了该精确算法,且不要假设给定平台的字符串匹配例程遵循此算法,因为许多这些例程具有特定区域的行为,或使用某种程度的字符串规范化。

5.2. 字体样式匹配

为给定文本中的字符选择字体的过程包括遍历 font-family 属性中命名的字体系列,基于其他字体属性选择合适的字体样式,然后确定是否存在该字符的字形。这是通过使用字体的 字符映射 来完成的,该数据将字符映射到该字符的默认字形。如果字体的 字符映射 中包含字符,并且(2)如果包含的脚本需要,则提供该字符的成形信息,则认为该字体 支持该字符。

某些旧版字体可能会在其 字符映射 中包含某些字符,但缺乏正确渲染包含该字符的文本所需的成形信息(例如 OpenType 布局表Graphite 表)。

由基础字符后跟合并字符序列组成的代码点序列稍有不同,详见下文中的 簇匹配 部分。

在下面的过程里, 对于给定的某个字体家族, 默认字体字面(default font face) 定义为:在所有字体样式相关属性都设为其初始值时, 会被选中的那一个字面。

  1. 对于某个给定元素, 使用其各个字体属性的计算值, 用户代理从 font-family 属性 指定的第一个字体家族名开始处理。

  2. 如果该家族名是一个通用(generic)家族关键字, 用户代理会查找要使用的具体字体家族名称。 用户代理可以基于包含该元素的语言, 或基于该字符的 Unicode 范围, 来选择要使用的通用字体家族。

  3. 对于其他家族名,用户代理会先在 通过 @font-face 规则定义的字体中 查找该家族名, 然后再在可用的已安装字体中查找 (这可以包括字体别名), 并按照上一节中 § 5.1 本地化名称匹配 的方式进行名称匹配。 如果某条 @font-face 规则中为某个字面定义的 字体资源不可用或包含无效字体数据, 那么该字面必须被视为在该家族中不存在。 如果通过 @font-face 规则 定义的某个家族中不存在任何字面, 则该家族必须被视为缺失; 在这种情况下不得匹配同名的平台字体。

  4. 如果找到了匹配的字体家族, 用户代理会收集该家族中的所有字面集合, 然后按照下面给出的顺序, 利用其他字体属性将该集合缩小到单个字面。 在这个集合中,可能存在一部分字体, 它们可以支持一段范围内的 font-widthfont-stylefont-weight 取值。 在这种情形下,算法会按“好像该字体支持的每个取值组合 都是在集合中一个独立字体”的方式来进行。 如果算法最终选中了这样的字体, 那么在进行任何布局或渲染之前, 必须先将选中的 font-widthfont-style 以及 font-weight 的具体取值 应用于该字体。 这些取值必须在 § 7 字体特性与变体解析 中详细描述的 “应用字体匹配变体(Apply font matching variations)” 步骤中被应用。 由多条 @font-face 规则定义、 但字体描述符取值相同而 unicode-range 取值不同的一组字面, 在该步骤中会被视为单个 复合字体字面(composite font face)

    Tests
    1. 首先尝试 font-width。 如果某字体本身并没有“宽度强度”的概念, 则其宽度取值会按照 属性定义中的表 映射为对应的取值。 如果在当前匹配集合中 存在宽度包含所需 font-width 取值的字面, 则会移除那些宽度不包含该取值的字面。 如果没有任何字面 包含所需宽度, 则按如下规则选择一个宽度取值:

      • 如果所需宽度值小于或等于 100%, 则先按从大到小的顺序检查 小于该宽度的宽度值, 然后再按从小到大的顺序检查 大于该宽度的宽度值, 直到找到匹配为止。

      • 否则,先按从小到大的顺序检查 大于该宽度的宽度值, 然后再按从大到小的顺序检查 小于该宽度的宽度值, 直到找到匹配为止。

      一旦通过这一过程确定了 与所需宽度最接近的宽度取值, 就会从匹配集合中 移除所有宽度不包含该取值的字面。

      可以把这一搜索算法看作一个“距离函数”: 在整个字体家族中, 会选中距离最小的宽度值所在的字体, 并移除所有不包含该宽度值的字体。

      考虑一个字体家族中存在三款字体, 名为 A、B 和 C, 每款字体都有一段它们各自支持的 font-width 范围。 若某元素使用 "font-width: 125%", 则该搜索算法可以被可视化为:

      algorithm

      如图所示,由于字体 B 在整个家族中 拥有最小的距离值, 因此算法会选中字体 B。 然而,如果字体 B 被从该家族中移除, 则字体 C 会成为距离最小的那款字体, 因此将被选中。

      上一个示例类似, 下面是元素使用 "font-width: 75%" 时, 概念上的距离图:

      distance graph

      如图所示,由于字体 B 在整个家族中 拥有最小的距离值, 因此算法会选中字体 B。 若 B 被移除,则 A 的距离最小, 将被选中。

    2. 接着尝试 font-style (参见 § 5.2 字体样式匹配)。 如果某字体本身并没有“斜体强度”或倾斜角度的概念, 则其样式会按照 font-style 属性定义中的说明 映射到对应的取值。

      如果 font-style 的取值为 italic

      1. 如果匹配集合中 存在样式取值中包含映射后 italic 的字面, 则移除所有样式取值中 不包含该映射后 italic 取值的字面。

      2. 否则,按从小到大顺序检查 比所需 italic 值大的 italic 取值, 直到到达 0 为止, 然后再按从大到小顺序检查 比所需值小的 italic 取值。 在该阶段中,只会检查正的 italic 取值。

      3. 若仍未找到匹配, 则按从小到大顺序检查 不小于 11deg 的 oblique 取值, 直到到达 0 为止, 然后再按从大到小顺序检查 小于 11deg 的 oblique 取值。 在该阶段中,只会检查正的 oblique 取值。

        使 oblique 优先于 normal 的阈值 应当低于平均角度

      4. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0 的 italic 取值, 直到找到匹配为止。

      5. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0deg 的 oblique 取值, 直到找到匹配为止。

        前面的示例类似, 下图是元素使用 "font-style: italic" 时 概念上的距离图:

        distance graph

        如图所示,由于字体 D 在整个家族中 拥有最小的 italic 取值, 因此算法会选中字体 D。 若 D 被移除,则 E 的距离最小,将被选中; 若 E 被移除,则 C 被选中; 若 C 再被移除, 字体 B 并不会立刻被选中, 而是会先考虑 oblique 取值, 也许会选中某个 oblique。 如果并未选中任何 oblique, 那么才会依次选中 B,然后 A。

      如果 font-style 的取值为 oblique, 且请求的角度不小于 11deg,

      1. 如果匹配集合中存在 oblique 取值中包含所请求 oblique 角度的字面, 则移除所有 oblique 取值中 不包含该角度的字面。

      2. 否则,按从小到大顺序检查 比所需 oblique 角度大的 oblique 取值, 直到 0 为止, 然后再按从大到小顺序检查 小于所需角度的 oblique 取值。 在该阶段中,只检查正的 oblique 取值。

      3. 对于具有 slnt 轴的可变字体, 可以通过将 slnt 轴取值 设为指定的 oblique 角度 来得到匹配。 否则,如果 font-synthesis-style 的取值为 auto, 则可以通过几何倾斜 (shearing)到指定 oblique 角度 来产生回退匹配。

      4. 若仍未找到匹配, 则按从小到大顺序检查 不小于 1 的 italic 取值, 直到到达 0 为止, 然后再按从大到小顺序检查 小于 1 的 italic 取值。 在该阶段中,只检查正的 italic 取值。

      5. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0deg 的 oblique 取值, 直到找到匹配为止。

      6. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0 的 italic 取值, 直到找到匹配为止。

        之前的示例类似, 下图是元素使用 "font-style: oblique 40deg" 时 的概念距离图:

        distance graph

        如图所示,由于字体 D 在整个家族中 拥有最小的 oblique 取值, 因此算法会选中字体 D。 若 D 被移除,则 E 的距离最小,将被选中; 若 E 被移除,则 C 被选中; 若 C 再被移除, 字体 B 并不会立刻被选中, 而是会先考虑 italic 取值, 也许会选中某个 italic。 如果并未选中任何 italic, 那么才会依次选中 B,然后 A。

      如果 font-style 的取值为 oblique, 且请求角度大于等于 0deg 且小于 11deg,

      1. 如果匹配集合中存在 oblique 取值中包含该 oblique 角度的字面, 则会移除所有 oblique 取值中 不包含该角度的字面。

      2. 否则,按从大到小顺序检查 小于所需 oblique 角度的 oblique 取值, 直到 0 为止, 然后再按从小到大的顺序检查 大于所需角度的 oblique 取值。 在该阶段中,只检查正的 oblique 取值。

      3. 对于具有 slnt 轴的可变字体, 可以通过将 slnt 轴取值 设为指定 oblique 角度来创建匹配。 否则,如果 font-synthesis-style 的取值为 auto, 则可以通过几何倾斜到指定角度 来产生回退匹配。

      4. 若仍未找到匹配, 则按从大到小顺序检查 小于 1 的 italic 取值, 直到 0 为止, 然后再按从小到大的顺序检查 大于 1 的 italic 取值。 在该阶段中,只检查正的 italic 取值。

      5. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0deg 的 oblique 取值, 直到找到匹配为止。

      6. 若仍未找到匹配, 则按从大到小顺序检查 小于或等于 0 的 italic 取值, 直到找到匹配为止。

      之前的示例类似, 下图是元素使用 "font-style: oblique 13deg" 时 的概念距离图:

      distance graph

      如图所示,由于字体 D 在整个家族中 拥有最小的 oblique 取值, 因此算法会选中字体 D。 若 D 被移除,则 C 的距离最小,将被选中; 若 C 被移除,则 E 被选中; 若 E 再被移除, 字体 B 并不会马上被选中, 而是会先考虑 italic 取值, 也许会选中某个 italic。 如果没有选中任何 italic, 那么才会依次选中 B,然后 A。

      如果 font-style 的取值为 oblique, 且请求角度小于 0deg 且大于 -11deg, 则按上文步骤执行, 只是全部使用相反符号和相反方向。 如果 font-style 的取值为 oblique, 且请求角度小于或等于 -11deg, 则按上文步骤执行, 同样全部使用相反符号和相反方向。

      如果 font-style 的取值为 normal

      1. 按从小到大顺序检查 不小于 0 的 oblique 取值。

      2. 若仍未找到匹配, 则按从小到大顺序检查 不小于 0 的 italic 取值。

      3. 若仍未找到匹配, 则按从大到小顺序检查 小于 0deg 的 oblique 取值, 直到找到匹配为止。

      4. 若仍未找到匹配, 则按从大到小顺序检查 小于 0 的 italic 取值, 直到找到匹配为止。

      前面的示例类似, 下图是元素使用 "font-style: normal" 时 的概念距离图:

      distance graph

      如图所示,由于字体 C 在整个家族中 拥有最小的 oblique 取值, 因此算法会选中字体 C。 若 C 被移除, 字体 B 并不会马上被选中, 而是会先考虑 italic 取值, 也许会选中某个 italic。 如果没有选中任何 italic, 那么才会依次选中 B,然后 A。

      如果在上述搜索过程中找到了 oblique 角度, 就会移除所有不包含该 oblique 角度的字面。 否则,如果在上述搜索中找到了 italic 取值, 就会移除所有不包含该 italic 取值的字面。

      用户代理并不强制要求 一定要区分 italic 与 oblique 字体。 在这种用户代理中, 上述 font-style 匹配步骤 会通过将 italic 取值和 oblique 角度 映射到一个公共量表来完成。 这种映射的具体方式未作规定, 然而,italic 取值 1 必须映射到 与 oblique 角度 11deg 相同的量表值。 在通过 @font-face 规则定义的字体家族中, italic 与 oblique 字面 必须根据 font-style 描述符的取值加以区分。

      对于完全不包含 italic 或 oblique 字面的家族, 如果 font-synthesis 属性的取值允许, 用户代理可以创建人工合成的 oblique 字面。

    3. 接着匹配 font-weight。 如果某字体本身没有“字重强度”的概念, 则其字重会按照 属性定义中的列表进行映射。 如果使用了 bolder/lighter 这类相对字重, 则会按照 font-weight 属性定义中的说明, 基于继承的字重计算出实际字重。 如果在完成上述步骤后, 匹配集合中存在字重取值中包含所需 font-weight 取值的字面, 则会移除所有字重取值中不包含该取值的字面。 若没有任何字面包含该字重, 则按如下规则选择一个字重:

      • 如果所需字重在 400 到 500(含)之间, 则按从小到大顺序检查 不小于目标字重的各字重, 直到检查到 500 为止; 然后按从大到小顺序检查 小于目标字重的各字重; 若仍无匹配,则继续检查大于 500 的字重, 直到找到匹配为止。

      • 如果所需字重小于 400, 则按从大到小顺序检查 小于或等于目标字重的各字重, 然后再按从小到大顺序检查 大于目标字重的各字重, 直到找到匹配为止。

      • 如果所需字重大于 500, 则按从小到大顺序检查 不小于目标字重的各字重, 然后再按从大到小顺序检查 小于目标字重的各字重, 直到找到匹配为止。

        Tests
      前面的示例类似, 下图是元素使用 "font-weight: 400" 时 的概念距离图:

      distance graph

      如图所示,由于字体 B 在整个家族中 拥有最小的距离, 因此算法会选中字体 B。 若 B 被移除,则 C 的距离最小,将被选中; 若 C 被移除,则 D 被选中, 接着是 A,最后是 E。

      前面的示例类似, 下图是元素使用 "font-weight: 450" 时 的概念距离图:

      distance graph

      如图所示,由于字体 C 在整个家族中 拥有最小的距离, 因此算法会选中字体 C。 若 C 被移除,则 D 的距离最小,将被选中; 若 D 也被移除,则依次选中 B、A,最后是 E。

      前面的示例类似, 下图是元素使用 "font-weight: 500" 时 的概念距离图:

      distance graph

      如图所示,由于字体 D 在整个家族中 拥有最小的距离, 因此算法会选中字体 D。 若 D 被移除,则 B 的距离最小,将被选中; 若 B 被移除,则 C 被选中, 然后是 B、A,最后是 E。

      前面的示例类似, 下图是元素使用 "font-weight: 300" 时 的概念距离图:

      distance graph

      如图所示,由于字体 B 在整个家族中 拥有最小的距离, 因此算法会选中字体 B。 若 B 被移除,则 A 的距离最小,将被选中; 若 A 被移除,则 C 被选中。

      一旦通过上述过程 确定了与所需字重最接近的字重取值, 就会从匹配集合中 移除所有不包含该字重取值的字面。

      Note:[CSS-FONTS-3] 相比, 本规范在 font-weight 属性的动画行为上存在细微差异。 之前,font-weight 的插值值会被四舍五入到 最接近的 100 的倍数, 然后再将该值用于字体匹配算法。 在本规范中,字体匹配算法可以接受任意取值, 因此不再发生这种舍入。 由于字体匹配算法本身是不连续的, 这会造成细微的行为变化。

    4. 最后匹配 font-size。 必须在 UA 依赖的允许误差范围内进行匹配。 (通常,对于可缩放字体, 其字号会被舍入到最接近的整像素; 而对于位图字体,容差可能高达 20%。) 后续诸如基于 em 单位的计算, 都是基于真正被使用的 font-size 取值, 而不是声明中指定的值。

    注意,在执行完以上步骤后, 匹配集合中可能仍然剩下多个字体。 在这种情况下,用户代理必须从该集合中 选择一个具体字体并继续后续步骤。 在不同用户代理和不同操作系统平台之间, 这个选择可以不同; 然而,在同一文档中的两个元素之间, 该选择不得不同。

  5. 如果匹配到的字面 是通过 @font-face 规则定义的, 用户代理必须按如下过程 选择一个具体字体:

    1. 如果字体资源尚未被加载, 且该字面 的 unicode-range 描述符指定的字符范围 包含当前要渲染的字符, 则加载该字体。

    2. 下载完成后, 如果该字体的 有效字符映射(effective character map) 支持当前字符, 就选中该字体。

    当匹配到的字面是某个 复合字体字面(composite face) 时, 用户代理必须按上述过程 依次用于该复合字面中的各个字面, 并按各个 复合字面 所在 @font-face 规则的定义顺序的逆序来处理。

    在下载进行期间, 用户代理必须在下列二选一: 要么一直等待字体下载完成, 要么先用替代的字体度量渲染一次, 待字体下载完成后再重新渲染一次。

  6. 如果不存在任何匹配的字面, 或者匹配到的字面不包含 要渲染字符的字形, 则选择下一个字体家族名, 并重复前面三步。 家族中的其他字面 不会被考虑。 惟一的例外是, 如果给定字形由 默认字面 支持, 且 font-synthesis 属性的取值允许对这些字面进行合成, 那么用户代理可以选择 对默认字面进行合成倾斜替代。 例如,如果 italic 字面中 没有阿拉伯文字形, 则可以使用 regular 字面的 合成斜体版本。

  7. 如果没有更多可评估的字体家族, 也没有找到任何匹配字面, 那么用户代理会执行 已安装字体回退(installed font fallback) 过程, 寻找对要渲染字符的最佳匹配。 该过程的结果在不同用户代理之间 可能会有所不同。

  8. 如果某个字符 无法通过任何字体显示, 用户代理应当通过某种方式 指示该字符无法被显示, 比如使用某个缺失字形的符号展示 (例如使用 Last Resort Font), 或使用默认字体中的 缺失字符字形来呈现。

只要实现的行为 与“好像完全按照上述算法执行”一致, 就允许对该过程进行优化。 匹配过程的顺序是被明确定义的, 以确保在可用字体集合与渲染技术完全一致的前提下, 不同用户代理之间的结果尽可能一致。

首个可用字体(first available font) 的定义如下: 它用于诸如 字体相对长度(如 ex) 以及 line-height 属性的定义中。 在给定 font-family 列表中的字体家族 (或在没有可用字体家族时, 使用用户代理的默认字体) 的前提下, 首个可用字体被定义为: 针对字符 U+0020(空格), 其 unicode-range 未排除该字符的第一个字体。

通过字体家族名称直接引用的已安装字体, 而不是通过 @font-face 规则引用的字体, 被视为具有覆盖整个 Unicode 码位空间的 unicode-range

Tests

Note: 该字体是否真的具有空格字符的字形 并不重要。

5.3. 簇匹配

当文本包含组合符号等字符时,理想情况下,基础字符和符号应使用相同的字体渲染,这可以确保符号的正确位置。因此,簇的字体匹配算法比单独匹配单个字符的常规情况更为专业。对于包含变体选择器的序列,它们指示要用于给定字符的精确字形,用户代理始终尝试 已安装字体回退 以找到合适的字形,然后再使用基础字符的默认字形。

包含组合符号或其他修饰符的代码点序列称为字形簇(参见 [CSS3TEXT][UAX29] 获取更完整的描述)。对于包含基础字符 b 和组合字符序列 c1, c2… 的簇,整个簇按以下步骤匹配:

  1. 对于字体列表中的每个系列,使用前一节中定义的样式选择规则选择一个字体样式。
    1. 如果序列 b + c1 + c2 … 中的所有字符都被该字体完全支持,则为该序列选择此字体。
    2. 如果多个代码点的序列在规范上等同于单个字符,并且字体 支持该字符,则为该序列选择此字体,并为整个簇使用与规范等效字符相关的字形。
  2. 如果在步骤 1 中没有在字体列表中找到字体:
    1. 如果 c1 是一个变体选择器,系统回退必须被使用以找到支持整个 b + c1 序列的字体。如果系统上没有字体 支持整个序列,则使用常规匹配单个字符的过程来匹配单个字符 b,并忽略变体选择器。注意:包含多个变体选择器的序列必须被视为编码错误,后续的选择器必须被忽略。[UNICODE]
    2. 否则,用户代理可以选择使用已安装字体回退匹配支持整个簇的字体。
  3. 如果在步骤 2 中没有找到字体,则使用步骤 1 的匹配序列来确定由字体列表中的字体完全 支持 的最长序列,并尝试使用单个字符的匹配规则分别匹配其余的组合字符。

5.4. 字符处理问题

CSS 字体匹配始终针对包含 Unicode 字符的文本运行进行 [UNICODE],因此使用传统编码的文档在匹配字体之前被假定已进行转码。对于同时包含传统编码和 Unicode 字符映射的字体,传统编码的字符映射内容不得对字体匹配过程的结果产生影响。

字体匹配过程不假定文本运行处于标准化或非标准化形式(详情请参见 [CHARMOD-NORM])。字体可能只支持预组合形式,而不支持由基础字符加组合符号构成的分解序列。作者在选择字体时应始终根据其内容进行调整,包括该内容是否包含标准化或非标准化的字符流。

如果给定字符是私人使用区 Unicode 代码点,用户代理必须只匹配 font-family 列表中非通用系列名称的字体。 如果 font-family 列表中命名的系列没有包含该代码点的字形,用户代理必须显示某种形式的缺失字形符号,而不是尝试为该代码点使用 已安装字体回退。在匹配替换字符 U+FFFD 时,用户代理可以跳过字体匹配过程并直接显示某种形式的缺失字形符号,而不需要显示通过字体匹配过程选择的字体中的字形。

通常,给定系列的字体将具有相同或类似的 字符映射。这里概述的过程旨在处理甚至包含面部特征高度不同的 字符映射 的字体系列。然而,作者应注意,使用此类系列可能会导致意外结果。

Tests

6. 字体功能属性

现代字体技术支持多种高级排版和特定语言的字体功能。利用这些功能,单个字体可以提供广泛的字形,包括连字、上下文和样式替代、表格和旧式数字、小型大写字母、自动分数、花饰和特定语言的替代字符。为了让作者能够控制这些字体功能,font-variant 属性得到了扩展。它现在作为一组属性的简写,用于控制样式字体功能。

6.1. 字形选择和定位

本节为非规范性内容

用于显示拉丁文本的简单字体使用非常基本的处理模型。字体包含一个 字符映射,将每个字符映射到该字符的字形。后续字符的字形只需一个接一个地放置在文本运行中。现代字体格式(如 OpenType 和 AAT(Apple 高级排版))使用更丰富的处理模型。给定字符的字形不仅可以根据字符本身的代码点来选择和定位,还可以根据相邻字符以及文本启用的语言、脚本和功能来选择。字体功能可能是某些脚本所必需的,或推荐默认启用的,或者可能是作者控制下使用的样式功能。字体选择和定位发生在文本处理操作的总体顺序中的位置(例如文本转换、文本方向和文本对齐)在 CSS 文本 3 § A 文本处理操作顺序 中有所描述。

有关 OpenType 字体字形处理的详细描述,请参见 [WINDOWS-GLYPH-PROC]

样式字体功能可以分为两大类:一类影响字形形状与周围上下文的和谐性,如字距调整和连字功能;另一类则影响形状选择,如小型大写字母、下标/上标和替代功能。

下面列出的 font-variant 子属性用于控制这些样式字体功能。它们不控制用于显示某些脚本的必需功能,例如用于显示阿拉伯文或印度语文本的 OpenType 功能。它们影响字形选择和定位,但不影响字体选择(除非为了兼容 CSS 2.1 而需要)。

为了确保跨用户代理的一致行为,单独属性的等效 OpenType 属性设置是规范性的。当使用其他字体格式时,应该将这些设置作为指导,以将 CSS 字体功能属性值映射到特定的字体功能。

6.2. 特定语言显示

OpenType 还支持特定语言的字形选择和定位,以便在语言规定特定显示行为的情况下正确显示文本。许多语言共用一种书写系统,但某些字母的形状在不同语言之间可能有所不同。例如,某些西里尔字母在俄语文本中与在保加利亚语中的形状不同。在拉丁文本中,通常将“fi”显式渲染为没有“i”上的点的连字。然而,在如土耳其语等同时使用带点和无点“i”的语言中,不使用该连字或使用包含“i”上的点的专用版本很重要。

测试

下面的示例展示了基于西班牙语、意大利语和法语正字法中的风格传统的特定语言变化:

特定语言形式,西班牙语
特定语言形式,意大利语
特定语言形式,法语

如果根据文档语言规则 能够确定该元素的内容语言, 用户代理必须从内容语言推断出 OpenType 语言系统, 并在使用 OpenType 字体选择和排布字形时采用该语言系统。 如果明确指定了某种书写系统, 则该书写系统必须优先于由内容语言所隐含的常用书写系统。

对于 OpenType 字体,在某些情况下可能需要显式声明要使用的 OpenType 语言, 例如:在以某种语言显示文本时,却采用另一种语言的排印习惯; 或者字体并未显式支持某种语言, 但支持与其具有相同排印习惯的另一种语言。 为此可以使用 font-language-override 属性。

6.3. 字距调整:font-kerning 属性

名称: font-kerning
取值: auto | normal | none
初始值: auto
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定值
规范顺序: 按语法
动画类型: 离散
Tests

字距调整(kerning)是对字形间距 的上下文调整。 本属性用于控制“度量字距调整”, 即利用字体中包含的 调整数据来进行的字距调整。

auto
指定是否应用字距调整 由用户代理自行决定
normal
指定应用字距调整
none
指定不应用字距调整

对于不包含字距调整数据的字体, 本属性不会产生可见效果。 在使用 OpenType 字体渲染时, [OPENTYPE] 规范建议默认启用字距调整。 当启用字距调整时, 会启用相应的 OpenType 字距特性 (对于水平方向的排版模式(typographic modes) 以及垂直排版模式中的 横向排版(sideways typesetting), 启用 kern 特性; 对于直立排版(upright typesetting)垂直排版模式, 启用 vkrn 特性)。 用户代理还必须支持仅通过 字体表 kern 中的数据 来进行字距调整的字体, 其细节见 OpenType 规范。 如果定义了 letter-spacing 属性, 则字距调整被视为默认间距的一部分, 字符间距的额外调整 必须在字距调整应用之后进行。

当设为 auto 时, 用户代理可以基于多种因素 来决定是否应用字距调整: 文本大小、书写系统, 或其他影响文本处理速度的因素。 希望得到正确字距调整的作者 应使用 normal 来显式开启字距调整。 同样地,在性能 比精确外观更重要的场景中, 一些作者也可能选择关闭字距调整。 不过,在设计良好的现代实现中, 启用字距调整通常 不会对文本渲染速度 产生较大影响。

6.4. 连字:font-variant-ligatures 属性

名称: font-variant-ligatures
取值: normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ]
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定值
规范顺序: 按语法
动画类型: 离散
Tests

连字和上下文字形 是将多个字形组合起来, 以产生更为协调统一字形的一种方式。

<common-lig-values>        = [ common-ligatures | no-common-ligatures ]
<discretionary-lig-values> = [ discretionary-ligatures | no-discretionary-ligatures ]
<historical-lig-values>    = [ historical-ligatures | no-historical-ligatures ]
<contextual-alt-values>    = [ contextual | no-contextual ]

各个取值的含义如下:

normal
取值 normal 表示启用常见的默认特性, 其详细说明见下一节。 对于 OpenType 字体, 默认开启常用连字和上下文字形, 而不启用可选连字和历史连字。
none
表示显式禁用本属性所涵盖的 各种类型的连字与上下文字形。 在不需要连字的场景下, 这样可能会提升文本渲染速度。
common-ligatures
启用常用连字的显示 (OpenType 特性:liga, clig)。 对于 OpenType 字体, 常用连字默认启用。
common ligature example
no-common-ligatures
禁用常用连字的显示 (OpenType 特性:liga, clig)。
discretionary-ligatures
启用可选连字的显示 (OpenType 特性:dlig)。 哪些连字被视为可选或装饰性, 由字体设计师决定, 因此作者需要参考 具体字体的文档, 以了解哪些连字被视为可选连字。
discretionary ligature example
no-discretionary-ligatures
禁用可选连字的显示 (OpenType 特性:dlig)。
historical-ligatures
启用历史连字的显示 (OpenType 特性:hlig)。
historical ligature example
no-historical-ligatures
禁用历史连字的显示 (OpenType 特性:hlig)。
contextual
启用上下文替代字形的显示 (OpenType 特性:calt)。 虽然严格来说它并非连字特性, 但与连字类似, 该特性通常用于让字形形状 与周围上下文更加协调。 对于 OpenType 字体, 此特性默认启用。
contextual alternate example
no-contextual
禁用上下文替代字形的显示 (OpenType 特性:calt)。

必需连字, 即在正确渲染复杂书写系统时 所必需的连字, 不受上述设置影响, 包括 none 在内 (OpenType 特性:rlig)。

6.5. 下标和上标形式:font-variant-position 属性

名称: font-variant-position
取值: normal | sub | super
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests

该属性用于启用排印学上的 下标和上标字形。 这些是替代字形, 与默认字形设计在同一个 em-box 中, 旨在与默认字形一样 排版在同一基线上, 不需要重新调整字号 或重新定位基线。 它们被明确设计为 在不影响行高的前提下, 与周围文本保持风格一致, 并具有更好的可读性。

comparison between real subscript glyphs and synthesized ones

真实下标字形(上)与典型合成下标(下)对比

各个取值的含义如下:

normal
不启用下面列出的任何特性。
sub
启用下标变体的显示 (OpenType 特性:subs)。
super
启用上标变体的显示 (OpenType 特性:sups)。

由于下标和上标具有语义性质, 当某个连续文本 run 的取值为 subsuper 时, 如果该 run 中并非所有字符 都有可用的变体字形, 就应为该 run 中的所有字符 合成模拟字形: 使用在未启用该特性时 所会使用的字形的缩小形式。 这是按 run 为单位执行的, 以避免真实变体字形 与合成字形混用后 无法正确对齐。 对于缺少下标或上标字形的 OpenType 字体, 用户代理必须合成 合适的下标和上标字形。

alternate superscripts vs. glyphs synthesized using superscript metrics

上标替代字形(左)、合成上标字形(中) 以及两者混用的错误示例(右)

在某些场景中, 只有包含上标或下标字形的文本 run 才会应用文字装饰, 此时可以使用合成字形, 以避免装饰位置出现问题。

过去, 用户代理常通过 font-size 和 vertical-align 为 HTML 的 subsup 元素 模拟下标和上标效果。 为了在向后兼容的前提下 定义下标与上标, 建议作者使用条件规则 [CSS3-CONDITIONAL], 这样旧版用户代理 仍然会通过旧机制 渲染上下标。

由于 font-size: smaller 常用于这些元素, 实际应用到上下标文本上的 缩放因子会随字号变化而变化。 对于较大的文本, 字号通常会缩小为原来的三分之二; 而对于较小的字号, 缩小比例则可能小得多。 这让即使在较小字号中 使用的下标和上标 仍然保持可读。 用户代理在决定如何合成 下标和上标字形时, 应当考虑这一点。

OpenType 字体格式 在 OS/2 表 中定义了上下标度量 [OPENTYPE], 但这些度量在实际中并不总是准确, 因此在合成下标和上标字形时 不能完全依赖这些度量。

需要注意的是, 字体通常只为 自身支持字符集中的一小部分 提供下标和上标字形。 例如, 虽然拉丁数字的 下标和上标字形 经常会提供, 但标点与字母字符的 下标和上标则不那么常见。 本属性定义的 合成回退规则 试图保证总能显示出上下标, 但如果所用字体 并未为上下标中的所有字符 提供合适的替代字形, 实际呈现的效果 可能与作者的预期不完全一致。

此属性不是累积的。 在已经是下标或上标的元素内部再使用该属性, 不会叠加出“下标的下标”或“上标的上标”。 若文本 run 中包含的图像 所在 run 的属性值为 subsuper, 该图像的绘制与 取值为 normal 时 并无区别。

由于这些限制, 不推荐在用户代理样式表中 使用 font-variant-position。 作者应在仅包含 字体所支持的 小范围字符的上下标情形中 使用该属性。

变体字形 使用与默认字形相同的基线。 在基线方向不会发生位移, 因此使用变体字形 不会改变内联盒的高度, 也不会改变行盒的高度。 这使得上标与下标变体 非常适合那些 要求行距保持恒定的场景, 例如多栏布局。

一个典型的用户代理对 sub 元素的默认样式:

sub {  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}

使用 font-variant-position 以一种在旧版用户代理中 仍然能显示下标的方式 来指定排印学上的下标:

@supports ( font-variant-position: sub ) {  sub {
    vertical-align: baseline;
    font-size: 100%;
    line-height: inherit;
    font-variant-position: sub;
  }
}

支持 font-variant-position 属性的用户代理 会选择下标变体字形, 并在不调整基线与字号的情况下渲染。 旧版用户代理则会忽略 font-variant-position 的定义, 使用其标准的下标默认样式。

6.6. 大写方式: font-variant-caps 属性

名称: font-variant-caps
取值: normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests

该属性允许选择用于小型或细号大写字母 以及标题字形的替代字形。 这些字形经过专门设计, 以便与周围的普通字形良好融合, 并保持字重与可读性, 而不像简单缩放文字那样 为此目的而牺牲视觉效果。

各个取值的含义如下:

normal
不启用下面列出的任何特性。
small-caps
启用小型大写字母的显示 (OpenType 特性:smcp)。 小型大写字形通常采用大写字母的字形形式, 但缩小到与小写字母相近的尺寸。
small-caps example
all-small-caps
为大写和小写字母 都启用小型大写字形 (OpenType 特性:c2sc, smcp)。
petite-caps
启用细号大写字形 (OpenType 特性:pcap)。
all-petite-caps
为大写和小写字母 都启用细号大写字形 (OpenType 特性:c2pc, pcap)。
unicase
启用一种混合形式: 对大写字母使用小型大写字形, 对小写字母使用正常小写字形 (OpenType 特性:unic)。
titling-caps
启用标题大写字形 (OpenType 特性:titl)。 大写字母字形往往是为与小写字母搭配而设计的。 当在全大写标题序列中使用时, 这些大写字形可能显得过于粗重。 标题大写字形就是为这种场景 特别设计的。

这些字形的可用性 取决于对应的特性 是否在字体的特性列表中定义。 用户代理可以按“脚本类型”(script)为粒度 决定是否启用这些特性, 但明确不应以单个字符为粒度来决定。

有些字体可能只支持该属性下 描述特性中的一部分, 甚至完全不支持。 为了与 CSS 2.1 向后兼容, 如果声明了 small-capsall-small-caps, 但给定字体并不提供小型大写字形, 用户代理应当模拟小型大写字体, 例如使用普通字体, 并用缩放过的大写字母字形 替换小写字母字形 (在 all-small-caps 情况下, 同时替换大写和小写字母的字形)。

synthetic vs. real small-caps

合成小型大写 vs. 真实小型大写

font-feature-settings 属性 也会影响是否使用 模拟小型大写字体的决策 (与 CSS Fonts 3 不同)。

#example1 { font-variant-caps: small-caps; }#example2 { font-variant-caps: small-caps; font-feature-settings: 'smcp' 0; }

对于不支持小型大写的字体, #example1 与 #example2 都应以合成小型大写渲染。 但对于支持小型大写的字体, #example1 应以原生小型大写渲染, 而 #example2 则不应使用任何小型大写 (无论原生还是合成)。

为了与周围文本保持一致, 当这些特性被启用时, 字体可能会为无大小写区分的字符 提供替代字形; 但当用户代理在模拟小型大写时, 不得尝试为被视为“无大小写”的码位 模拟这些替代字形。

caseless characters with small-caps, all-small-caps enabled

启用 small-caps / all-small-caps 时的无大小写字符

如果在不支持相应特性的字体上 指定了 petite-capsall-petite-caps, 则该属性的行为分别等同于 指定 small-capsall-small-caps。 如果在不支持该特性的字体上 指定了 unicase, 则该属性的行为 等同于仅对“小写化的大写字母” 应用 small-caps。 如果在不支持该特性的字体上 指定了 titling-caps, 则该属性不会产生可见效果。 当使用合成小型大写字形时, 对于没有大/小写区分的文字系统, small-capsall-small-capspetite-capsall-petite-caps 以及 unicase 都不会产生可见效果。

当使用大小写转换 来模拟小型大写时, 所采用的大小写转换 必须与 text-transform 属性 所使用的转换保持一致。

在万不得已的情况下, 可以用普通字体中 未缩放的大写字母字形 来替换小型大写字体中的字形, 使文本以全大写形式出现。

using all-small-caps in acronym-laden text

在大量缩写的文本中使用小型大写来提升可读性

将引用文本设置为斜体,并在首行使用小型大写:

blockquote            { font-style: italic; }blockquote:first-line { font-variant: small-caps; }

<blockquote>I’ll be honor-bound to slap them like a haddock.</blockquote>

6.7. 数字格式化: font-variant-numeric 属性

名称: font-variant-numeric
取值: normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ]
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定值
规范顺序: 按语法
动画类型: 离散
Tests

指定对数字形式的控制。 下面的示例展示了 如何组合使用其中一些取值, 在字体支持相关特性的前提下, 影响表格数据的渲染方式。 在普通段落文本中使用比例数字, 而在表格中则使用等宽数字, 以便数字列能正确对齐:

combining number styles

数字样式的使用

可选组合:

<numeric-figure-values>   = [ lining-nums | oldstyle-nums ]
<numeric-spacing-values>  = [ proportional-nums | tabular-nums ]
<numeric-fraction-values> = [ diagonal-fractions | stacked-fractions ]

各个取值的含义如下:

normal
不启用下面列出的任何特性。
lining-nums
启用等高(lining)数字的显示 (OpenType 特性:lnum)。
oldstyle-nums
启用旧式(old-style)数字的显示 (OpenType 特性:onum)。
proportional-nums
启用比例宽度数字的显示 (OpenType 特性:pnum)。
tabular-nums
启用等宽(表格)数字的显示 (OpenType 特性:tnum)。
diagonal-fractions
启用等高斜线分数的显示 (OpenType 特性:frac)。
diagonal fraction example
stacked-fractions
启用等高叠排分数的显示 (OpenType 特性:afrc)。
stacked fraction example
ordinal
启用用于序数的字母形式 (OpenType 特性:ordn)。
ordinals example
slashed-zero
启用带斜线的零的显示 (OpenType 特性:zero)。
slashed zero example

ordinal 的情形中, 尽管序数字形 通常与上标形式相同, 它们的标记方式却不同。

对于上标, 变体属性只应用于 包含上标的子元素:

sup { font-variant-position: super; }
x<sup>2</sup>

对于序数, 变体属性应用于 整个序数数字, 而不是仅用于词尾(或整个段落):

.ordinal { font-variant-numeric: ordinal; }
<span class="ordinal">17th</span>

在这种情况下, 只有 “th” 会以序数字形呈现, 数字本身保持不变。 根据不同语言所采用的排印传统, 序数字形可能与上标形式不同。 例如在意大利语中, 序数字形有时会在设计中加入下划线。

一个简单的牛排腌料配方, 使用自动分数和旧式数字进行渲染:

.amount { font-variant-numeric: oldstyle-nums diagonal-fractions; }
<h4>Steak marinade:</h4>
<ul>
  <li><span class="amount">2</span> tbsp olive oil</li>
  <li><span class="amount">1</span> tbsp lemon juice</li>
  <li><span class="amount">1</span> tbsp soy sauce</li>
  <li><span class="amount">1 1/2</span> tbsp dry minced onion</li>
  <li><span class="amount">2 1/2</span> tsp italian seasoning</li>
  <li>Salt &amp; pepper</li>
</ul>

<p>Mix the meat with the marinade
and let it sit covered in the refrigerator
for a few hours or overnight.</p>

注意,分数字体特性 只应用于数值本身, 而不是整个段落。 字体通常会基于斜杠('/')字符 使用上下文规则实现这一特性。 因此,它并不适合作为 段落级样式来使用。

6.8. 变体和饰线: font-variant-alternates 属性

名称: font-variant-alternates
取值: normal | [ stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name>#) || character-variant(<feature-value-name>#) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) ]
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests
<feature-index> = <integer [0,]>
<feature-value-name> = <ident>

对于任意给定字符, 字体除了默认字形之外, 还可以提供多种替代字形。 本属性用来控制 这些替代字形的选择。

对于下文列出的许多属性取值, 都可能存在多个不同的替代字形。 可用替代字形的数量 以及它们所代表的含义 都是与具体字体相关的, 因此在下面的取值定义中 都标记为 字体特定(font specific)。 由于这些替代字形的性质 与具体字体相关, 会通过 @font-feature-values 规则 为某个特定字体家族或家族集合 定义取值: 将字体特定的数值 <feature-index> 与自定义 <feature-value-name> 关联起来, 然后在本属性中 通过这些名字来选择特定替代字形:

@font-feature-values Noble Script { @swash { swishy: 1; flowing: 2; } }

p {
  font-family: Noble Script;
  font-variant-alternates: swash(flowing); /* 使用第 2 号花体替代字形 */
}

当某个 <feature-value-name> 尚未为某个家族或某类特性定义时, 其计算值必须与已定义该名称时相同。 但是,在选择字形时, 包含这些未定义 <feature-value-name> 标识符的属性值 必须被忽略。

/* 下面两条样式规则在效果上是等价的 */

p { font-variant-alternates: swash(unknown-value); } /* 未定义的取值,忽略 */
p { font-variant-alternates: normal; }

这使得可以为某组字体家族 定义并使用这些取值, 而在发生回退时将其忽略, 因为此时字体家族名称已经不同。 如果给定取值 超出某字体支持的范围, 则该取值会被忽略。 这些取值绝不会应用于 通用字体家族(generic families)。

各个取值的含义如下:

normal
不启用下面列出的任何特性。
historical-forms
启用历史字形形式的显示(OpenType 特性:hist)。
historical form example
stylistic(<feature-value-name>)
启用风格化替代字形 (字体特定,OpenType 特性:salt <feature-index>)。
stylistic alternate example
styleset(<feature-value-name>#)
启用样式集显示 (字体特定,OpenType 特性:ss<feature-index>; 当前 OpenType 定义了 ss01ss20)。
styleset example
character-variant(<feature-value-name>#)
启用特定字符变体的显示 (字体特定,OpenType 特性:cv<feature-index>; 当前 OpenType 定义了 cv01cv99)。
swash(<feature-value-name>)
启用花体(swash)字形显示 (字体特定,OpenType 特性:swsh <feature-index>, cswh <feature-index>)。
swash example
ornaments(<feature-value-name>)
若字体中提供了装饰字形, 则用装饰字形替换默认字形 (字体特定,OpenType 特性:ornm <feature-index>)。 某些字体可能为大量字符提供装饰字形作为替代; 然而,将任意字符(如字母数字)显示为装饰字形 会扭曲数据的语义,是一种不佳实践。 鼓励字体设计者将所有装饰字形 (显式编码在 Unicode Dingbats 等块中的除外) 编码为项目符号字符(U+2022)的替代字形, 这样作者即可使用 ornaments() 来选择所需字形。
ornaments example
annotation(<feature-value-name>)
启用替代注解形式的显示 (字体特定,OpenType 特性:nalt <feature-index>)。
alternate annotation form example

6.9. 定义字体特定的替代字形: @font-feature-values 规则

上文列出的 font-variant-alternates 的若干可能取值 被标记为 font specific; 某个字体特性不仅可以只定义一个字形, 还可以定义多个可选字形变体, 并为每个变体关联一个数字索引, 从而允许你选择要启用哪一个。

这些数字索引对每个字面来说都是特立独行的; 在某个字面上,swsh 1 特性可能会开启大写字母 Q 的花体版本, 而在另一个字面中, 它则可能开启 & 的花体版本。 因此,在 font-feature-settings 中指定索引时, 要求作者精确知道某元素实际会使用哪一种字体; 如果判断错误(比如因为字体回退而选择了不同字体), 最终可能会开启一个与预期完全不同、甚至并不想要的特性! 这也意味着作者在为使用不同字体的元素开启类似特性时并不轻松: 他们必须分别为每个元素单独设置不同的 font-feature-settings 取值, 以便对每种字体都使用正确的数字索引来开启期望的特性。

为解决这个问题, @font-feature-values 规则允许作者 为每个字面,将某个易读的人类友好名称 绑定到特定特性索引上。 通过这些友好名称, 作者可以方便地为不同字体启用相同的特性 (只要为所有这些字体都定义了相同的名称), 并且可以确信自己不会误开启无关特性 (因为对某字体未定义这些名称时, 它们根本不会起作用)。

使用一个通用命名的取值, 可以让作者通过单条样式规则 覆盖一组底层选择器各不相同的字体。 在下面的示例中, 如果找到了任意一种字体, 就会使用带圆圈数字字形:

@font-feature-values Otaru Kisa {
  @annotation { circled: 1; black-boxed: 3; }
}
@font-feature-values Taisho Gothic {
  @annotation { boxed: 1; circled: 4; }
}

h3.title {
  /* 两种字体都定义了 circled 形式 */
  font-family: Otaru Kisa, Taisho Gothic;
  font-variant: annotation(circled);
}

如果尝试不借助 @font-feature-values, 而是直接为任一字体显式开启 “circled” 形式, 则要求作者确定无疑知道实际使用的是哪一种字体; 如果他们预期使用 “Otaru Kisa” 并写了 font-feature-settings: "nalt" 1;, 那么在 Otaru Kisa 中会开启 “circled” 字符, 但如果系统回退到了 Taisho Gothic, 这段设置会开启的是boxed 字符, 因为 Taisho Gothic 将 nalt 1 关联的是 boxed 形式!

6.9.1. 基础语法

@font-feature-values 规则的前导部分(prelude) 由一组字体家族名称组成, 后跟一个包含多个 特性值块(feature value block) 的代码块, 特性值块是一类特殊的子 at-rule。 每个 特性值块 都包含若干声明, 将作者自定义的、易读的人类可读名称 (例如 "flowing") 映射到对应特性的特性索引。

每一个 字体特性值 的含义都与 font-variant-alternates 属性中 对应取值的含义相同。

@font-feature-values = @font-feature-values <family-name># { <declaration-rule-list> }

<font-feature-value-type> = <@stylistic> | <@historical-forms> | <@styleset> | <@character-variant>
  | <@swash> | <@ornaments> | <@annotation>

@stylistic = @stylistic { <declaration-list> }
@historical-forms = @historical-forms { <declaration-list> }
@styleset = @styleset { <declaration-list> }
@character-variant = @character-variant { <declaration-list> }
@swash = @swash { <declaration-list> }
@ornaments = @ornaments { <declaration-list> }
@annotation = @annotation { <declaration-list> }
Tests

@font-feature-values 的前导部分 是一个由逗号分隔的字体家族名称列表, 这些名称需符合 <family-name> 的定义, 与 font-family 属性中相同。 这意味着这里只允许使用具名字体家族; 若在字体家族列表中包含通用字体或系统字体, 则该规则属于语法错误。 但是,如果用户代理将某个通用字体 定义为具体的具名字体(例如 Helvetica), 则会使用与该字体家族名称关联的设置。 如果在 <family-name> 列表中出现语法错误, 整条 @font-feature-values 规则 都视为无效并必须被忽略。

@font-feature-values 代码块的内容 接受 <declaration-rule-list>, 其中的条目可以是:

或者

多次指定相同的 <font-feature-value-type> 是合法的; 它们的内容会级联在一起。 每个 特性值块 接受一组 声明, 即 字体特性值声明(font feature value declaration), 其中声明名可以是任意 CSS 标识符, 声明值必须是一个或多个 非负 <integer> 组成的列表。

特性值块 接受任意声明名; 这些名称必须是标识符, 并且根据标准 CSS 语法规则, 是区分大小写 (因此 foo: 1;FOO: 2 会定义两个不同的特性)。 每个声明的取值必须符合语法 <integer [0,∞]>+, 否则该声明视为无效并必须被忽略。

Note: 每个特性名 只在单个 特性值块 内是唯一的。 在不同的 特性值块 之间, 或跨越不同 @font-feature-values 规则中 同一种类型的 特性值块 时, 名称可以重复使用而不会冲突。

对于 @font-feature-values 前导中的 每个 <family-name>, 每条 字体特性值声明 都定义了一个 (家族名、特性块名称、声明名)三元组(tuple) 与该声明取值中 一组或多组整数之间的映射关系。 如果文档中出现相同三元组多次 (例如在同一个块中), 则以后定义的覆盖之前的。

例如,下面这些都定义了 完全相同的一组字体特性值:
/* 默认写法 */
@font-feature-values foo {
  @swash { pretty: 1; cool: 2; }
}

/* 重复的声明名 */
@font-feature-values foo {
  @swash { pretty: 0; pretty: 1; cool: 2; }
}

/* 多个相同类型的块 */
@font-feature-values foo {
  @swash { pretty: 1; }
  @swash { cool: 2; }
}

/* 针对同一字体家族的多条规则 */
@font-feature-values foo {
  @swash { pretty: 1; }
}
@font-feature-values foo {
  @swash { cool: 2; }
}

若某条 字体特性值声明 内部存在语法错误, 则该声明无效并被忽略, 但不会导致其所在的 字体特性值块 失效。 若在 @font-feature-values 块内出现未知 at-rule (没有使用允许列表中的 at-keyword 之一), 则该 at-rule 无效并被忽略, 但不会使外层的 @font-feature-values 规则失效。

在语法错误处理规则下等价的几条规则:
@font-feature-values Bongo {
  @swash { ornate: 1; }
  annotation { boxed: 4; } /* 应该写成 @annotation! */
  @swash { double-loops: 1; flowing: -1; } /* 负值 */
  @ornaments ; /* 不完整定义 */
  @styleset { double-W: 14; sharp-terminals: 16 1 } /* 缺少 ; */
  redrum  /* 随手误输的内容 */
}

上面的示例等价于:

@font-feature-values Bongo {
  @swash { ornate: 1; }
  @swash { double-loops: 1; }
  @styleset { double-W: 14; sharp-terminals: 16 1; }
}

如果针对某个字体家族 定义了多条 @font-feature-values 规则, 则最终得到的取值定义 是这些规则内所有定义的并集。 这样可以为某个字体家族 在站点级别定义一组命名取值, 再在每个页面上 按需做特定补充。

站点级与页面级特性值同时使用:

site.css:

@font-feature-values Mercury Serif {
  @styleset {
    stacked-g: 3; /* g、a 的“双层”变体 */
    stacked-a: 4;
  }
}

page.css:

@font-feature-values Mercury Serif {
  @styleset {
  geometric-m: 7; /* m 的替代形 */
  }
}

body {
  font-family: Mercury Serif, serif;

  /* 同时启用 stacked g 和替代 m */
  font-variant-alternates: styleset(stacked-g, geometric-m);
}

6.9.2. 多值特征值定义

大多数组件为 字体特定font-variant-alternates 功能型取值 只接受一个值(例如 swash()), 用于开启对应特性。

@font-feature-values Jupiter Serif {  @swash {
    swishy: 5;     /* implies ss05 = 1 */
    swirly: 2;     /* implies ss02 = 1 */
  }
}

character-variant() 属性值和 @character-variant 描述符 允许使用两个值, 即通过第一个值指定要启用的特性, 再通过第二个值为该特性设置具体取值。

@font-feature-values MM Greek {  @character-variant { alpha-2: 1 2; }   /* implies cv01 = 2 */
  @character-variant { beta-3: 2 3; }    /* implies cv02 = 3 */
}

对于 styleset() 属性值和 @styleset 规则, 多个取值表示要开启的样式集。 1 到 99 之间的取值会依次开启 OpenType 特性 ss01ss99。 然而,OpenType 标准目前只正式定义了 ss01ss20。 对于 OpenType 字体,超过 99 或等于 0 的取值在解析时不会产生语法错误, 但也不会开启任何 OpenType 特性。

@font-feature-values Mars Serif {  @styleset {
    alt-g: 1;        /* implies ss01 = 1 */
    curly-quotes: 3; /* implies ss03 = 1 */
    code: 4 5;       /* implies ss04 = 1, ss05 = 1 */
  }

  @styleset {
    dumb: 125;        /* >99, ignored */
  }

  @swash {
    swishy: 3 5;     /* more than 1 value for swash, syntax error */
  }
}

p.codeblock {
  /* implies ss03 = 1, ss04 = 1, ss05 = 1 */
  font-variant-alternates: styleset(curly-quotes, code);
}

对于 <@character-variant>, 单个 1 到 99 之间的取值表示 开启 OpenType 特性 cv01cv99 中的某一个。 对于 OpenType 字体,超过 99 或等于 0 的取值会被忽略, 解析时不会产生语法错误, 但也不会开启任何 OpenType 特性。 当列出两个取值时, 第一个取值用于指明使用哪一个特性, 第二个取值作为传入该特性的具体值。 如果为某个名称指定了超过两个取值, 则会产生语法错误, 整条特性值定义会被忽略。

@font-feature-values MM Greek {  @character-variant { alpha-2: 1 2; }   /* implies cv01 = 2 */
  @character-variant { beta-3: 2 3; }    /* implies cv02 = 3 */
  @character-variant { epsilon: 5 3 6; } /* more than 2 values, syntax error, definition ignored */
  @character-variant { gamma: 12; }      /* implies cv12 = 1 */
  @character-variant { zeta:   20 3; }   /* implies cv20 = 3 */
  @character-variant { zeta-2: 20 2; }   /* implies cv20 = 2 */
  @character-variant { silly: 105; }     /* >99, ignored */
  @character-variant { dumb: 323 3; }    /* >99, ignored */
}

#title {
  /* 使用第三种 beta 变体、第一种 gamma 变体 */
  font-variant-alternates: character-variant(beta-3, gamma);
}

p {
  /* zeta-2 在 zeta 之后,意味着 cv20 = 2  */
  font-variant-alternates: character-variant(zeta, zeta-2);
}

.special {
  /* zeta 在 zeta-2 之后,意味着 cv20 = 3  */
  font-variant-alternates: character-variant(zeta-2, zeta);
}
Matching text on Byzantine seals using character variants

使用字符变体显示拜占庭印章上的文字

在上图中,红色文字使用的字体包含一组字符变体, 这些变体模仿了公元 8 世纪拜占庭印章上的字形形式。 再往下两行是同一段文本, 使用不含变体的字体显示。 注意印章上 U 与 N 所使用的两种不同变体。

@font-feature-values Athena Ruby {  @character-variant {
    leo-B: 2 1;
    leo-M: 13 3;
    leo-alt-N: 14 1;
    leo-N: 14 2;
    leo-T: 20 1;
    leo-U: 21 2;
    leo-alt-U: 21 4;
  }
}

p {
  font-variant: discretionary-ligatures
  character-variant(leo-B, leo-M, leo-N, leo-T, leo-U);
}

span.alt-N {
  font-variant-alternates: character-variant(leo-alt-N);
}

span.alt-U {
  font-variant-alternates: character-variant(leo-alt-U);
}

<p>ENO....UP͞RSTU<span class="alt-U">U</span>͞<span class="alt-U">U</span>ΚΑΙTỤẠG̣IUPNS</p>

<p>LEON|ΚΑΙCONSTA|NTI<span class="alt-N">N</span>OS..|STOIBAṢ.|LIṢROM|AIO<span class="alt-N">N</span></p>

6.10. 东亚文本渲染:font-variant-east-asian 属性

名称: font-variant-east-asian
取值: normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests

允许控制东亚文本中的字形替换与字形尺寸。

<east-asian-variant-values> = [ jis78 | jis83 | jis90 | jis04 | simplified | traditional ]
<east-asian-width-values>   = [ full-width | proportional-width ]

各个取值的含义如下:

normal
不启用下面列出的任何特性。
jis78
启用 JIS78 形式的渲染 (OpenType 特性:jp78)。
JIS78 form example
jis83
启用 JIS83 形式的渲染 (OpenType 特性:jp83)。
jis90
启用 JIS90 形式的渲染 (OpenType 特性:jp90)。
jis04
启用 JIS2004 形式的渲染 (OpenType 特性:jp04)。

各种 JIS 变体反映了 不同日本国家标准中 定义的字形形式。 字体通常会包含 最新国家标准定义的字形, 但在某些情况下 仍有必要使用较旧的变体, 比如为了与既有标牌保持一致。

simplified
启用简体字形的渲染 (OpenType 特性:smpl)。
traditional
启用繁体(传统)字形的渲染 (OpenType 特性:trad)。

simplifiedtraditional 取值 用于控制那些在时间推移中 已被简化、 但在某些语境下 仍然使用旧有传统字形的字符的字形形式。 具体涉及哪些字符、采用哪些字形形式, 会在一定程度上视 字体的设计语境而定。

traditional form example
full-width
启用全角变体的渲染 (OpenType 特性:fwid)。
proportional-width
启用比例间距变体的渲染 (OpenType 特性:pwid)。
proportionally spaced Japanese example
ruby
启用注音(ruby)变体字形的显示 (OpenType 特性:ruby)。 由于注音文字通常比正文更小, 字体设计者可以专门为注音 设计更易读的字形, 而不是简单缩放默认字形。 该特性只影响字形选择, 并不会触发任何字号缩放 或其他影响行布局的变化。

下图中红色注音文字 上部使用默认字形, 下部使用注音变体字形。 注意笔画粗细的细微差别。

ruby variant example

6.11. 字体渲染的整体简写:font-variant 属性

名称: font-variant
取值: normal | none | [ [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ] || [ small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps ] || [ stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name>#) || character-variant(<feature-value-name>#) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) ] || [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ] || [ <east-asian-variant-values> || <east-asian-width-values> || ruby ] || [ sub | super ] || [ text | emoji | unicode ] ]
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests

font-variant 属性 是所有 font-variant 子属性的缩写形式:

取值 normal 会把 font-variant 的所有子属性 重置为它们的初始值。 取值 none 会将 font-variant-ligatures 设为 “font-variant-ligatures/none”, 并把所有其他字体特性相关属性 重置为它们的初始值。 与其他缩写属性类似, 使用 font-variant 时, 未显式指定的 font-variant 子属性 都会被重置为各自的初始值。

它不会重置下列属性的取值: font-language-overridefont-feature-settingsfont-variation-settings

6.12. 低级字体特性设置控制:font-feature-settings 属性

名称: font-feature-settings
取值: normal | <feature-tag-value>#
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 按指定
规范顺序: 按语法
动画类型: 离散
Tests

该属性为 OpenType 字体特性 提供底层控制。 它旨在为那些并不常用、 但在某些特定场景下又确实需要的 字体特性提供访问方式。

作者不应使用 font-feature-settings 来设置下表中的任何字体特性。 相反,请使用对应的更高层替代属性,因为:
  1. 高层属性可以分别参与层叠。你可以只设置其中一个, 而不必重写整个 font-feature-settings 列表
  2. 某些高层属性在字体不支持对应特性时, 仍可以通过合成方式提供类似效果。
如果你想设置这个字体特性 那么请使用这个(而不是)font-feature-settings 说明
字距调整 Kerning(kern)或垂直字距调整 Vertical Kerning(vkrnfont-kerning: normal font-kerning 属性会根据 writing-mode 来设置 kernvkrn 特性。
标准连字 Standard Ligatures(liga) 或上下文连字 Contextual Ligatures(cligfont-variant-ligatures: common-ligatures
可选连字 Discretionary Ligatures(dligfont-variant-ligatures: discretionary-ligatures
历史连字 Historical Ligatures(hligfont-variant-ligatures: historical-ligatures
上下文替代 Contextual Alternates(caltfont-variant-ligatures: contextual
下标 Subscript(subsfont-variant-position: sub
上标 Superscript(supsfont-variant-position: super
小型大写 Small Capitals(smcpfont-variant-caps: small-caps
从大写生成的小型大写 Small Capitals From Capitals(c2scfont-variant-caps: all-small-caps
细号大写 Petite Capitals(pcapfont-variant-caps: petite-caps
从大写生成的细号大写 Petite Capitals From Capitals(c2pcfont-variant-caps: all-petite-caps
单一大小写 Unicase(unicfont-variant-caps: unicase
标题字 Titling(titlfont-variant-caps: titling-caps
等高数字 Lining Figures(lnumfont-variant-numeric: lining-nums
旧式数字 Oldstyle Figures(onumfont-variant-numeric: oldstyle-nums
比例数字 Proportional Figures(pnumfont-variant-numeric: proportional-nums
等宽数字 Tabular Figures(tnumfont-variant-numeric: tabular-nums
分数 Fractions(fracfont-variant-numeric: diagonal-fractions
备用分数 Alternative Fractions(afrcfont-variant-numeric: stacked-fractions
序数 Ordinals(ordnfont-variant-numeric: ordinal
带斜线的零 Slashed Zero(zerofont-variant-numeric: slashed-zero
历史字形 Historical Forms(histfont-variant-alternates: historical-forms
风格化替代 Stylistic Alternates(saltfont-variant-alternates: stylistic() 通过编写 @font-feature-values 规则 来定义使用哪一个替代字形
字符变体 1 – 字符变体 99 Character Variant 1 - Character Variant 99 (cv01 - cv99font-variant-alternates: character-variant() 通过编写 @font-feature-values 规则 来定义使用哪一种字符变体
花体 Swash(swsh) 或上下文花体 Contextual Swash(cswhfont-variant-alternates: swash() 通过编写 @font-feature-values 规则 来定义使用哪一种花体字形
装饰字形 Ornaments(ornmfont-variant-alternates: ornaments() 通过编写 @font-feature-values 规则 来定义使用哪一种装饰字形
替代注解形式 Alternate Annotation Forms(naltfont-variant-alternates: annotation() 通过编写 @font-feature-values 规则 来定义使用哪一种注解形式
JIS78 形式(jp78font-variant-east-asian: jis78
JIS83 形式(jp83font-variant-east-asian: jis83
JIS90 形式(jp90font-variant-east-asian: jis90
JIS2004 形式(jp04font-variant-east-asian: jis04
简体字形 Simplified Forms(smplfont-variant-east-asian: simplified
传统字形 Traditional Forms(tradfont-variant-east-asian: traditional
全宽 Full Widths(fwidfont-variant-east-asian: full-width
比例宽度 Proportional Widths(pwidfont-variant-east-asian: proportional-width
注音字形 Ruby Notation Forms(rubyfont-variant-east-asian: ruby

例如,目前并没有用于控制 科学下标(在化学式中使用的小号数字)的 font-variant 取值。 使用科学下标可以提升可读性, 因此必须通过 font-feature-settings 来启用:

.chem {
  font-feature-settings: 'sinf'
}
scientific inferior numbers in a chemical formula
科学下标可以提升化学式的可读性

整个属性值会一次性设置。 与各个 font-variant 属性不同, 没有办法在继承值的基础上 单独添加或移除某个特性。

取值 normal 表示由于该属性 不会发生任何字形选择或定位上的变化。

特性标签取值的语法如下:

<feature-tag-value> = <opentype-tag> [ <integer [0,]> | on | off ]?
<opentype-tag> = <string>

<opentype-tag> 是区分大小写的 OpenType 特性标签。 按 OpenType 规范 [OPENTYPE] 的要求, 特性标签由四个 ASCII 字符组成。 如果标签字符串长度不是四个字符, 或包含不在 U+20–7E 码位范围内的字符, 则视为无效。 特性标签只需要与字体中定义的某个特性标签匹配即可, 因此不限于显式注册的 OpenType 特性。 定义自定义特性标签的字体 应当遵循 OpenType 规范 中的标签命名规则 [OPENTYPE-FEATURES]

字体中不存在的特性标签会被忽略; 用户代理不得尝试 基于这些特性标签 合成回退行为。 唯一的例外是: 对于通过 kern 表 提供字距数据、 但在 GPOS 表中 不支持 kern 特性的字体, 用户代理可以以合成方式 支持 kern 特性。

一般来说,作者应当使用 font-kerning 属性 来显式启用或禁用字距调整, 因为该属性总能作用于 具有任一类型字距数据的字体。

如果存在取值, 则该取值表示用于字形选择的索引。 <integer> 值必须大于或等于 0。 值为 0 表示禁用该特性。 对于布尔特性, 值为 1 表示启用该特性。 对于非布尔特性, 值为 1 或更大时, 既表示启用该特性, 也表示具体的特性选择索引。 取值 on 等同于 1, off 等同于 0。 如果省略取值,则默认视为 1。

font-feature-settings 的计算值是一个映射, 因此在指定值中出现的重复项 不得被保留下来。 如果同一特性标签出现多次, 则最后一次出现所对应的取值 会覆盖该特性之前的所有取值。

计算值中包含去重后的特性标签, 并按照码元(code unit)升序排序。

font-feature-settings: "sinf" 1;       /* sinf=1 启用 Scientific Inferiors */
font-feature-settings: "sinf" on;      /* sinf=1 启用 Scientific Inferiors */
font-feature-settings: 'sinf';         /* sinf=1 启用 Scientific Inferiors */
font-feature-settings: "sinf" off;     /* sinf=0 禁用 Scientific Inferiors */
font-feature-settings: "sinf", 'twid'; /* sinf=1, twid=1 启用 Scientific Inferiors 和 Third Widths */
font-feature-settings: "sinf" "twid";  /* 无效,必须是用逗号分隔的列表 */
font-feature-settings: "silly" off;    /* 无效,标签过长 */
font-feature-settings: "PKRN";         /* PKRN=1 启用自定义特性 */
font-feature-settings: sinf;           /* 无效,标签必须是字符串 */

当指定的取值 大于字体所支持的范围时, 行为是明确未定义的。 对于布尔特性,一般来说这类取值会启用该特性。 对于非布尔特性, 超出范围的取值通常等同于 0。 然而,在这两种情况下, 具体行为仍取决于字体的设计方式 (特别是该特性采用了哪一种查找类型 来进行定义)。

实现可以选择忽略 对 OpenType 规范声明为 “始终必需”的特性的关闭操作, 例如必需连字 “rlig”。

Tests

虽然该属性是专门为 OpenType 特性标签定义的, 但未来也可能会为其他 支持字体特性的现代字体格式 增加特性标签。 在可能的情况下, 其他字体格式中定义的特性 应尽量遵循 已注册的 OpenType 标签的模式。

下面的日文文本会使用半角片假名进行渲染:

body { font-feature-settings: "hwid"; /* Half-width OpenType feature */ }

<p>毎日カレー食べてるのに、飽きない</p>

6.13. 字体语言覆盖:font-language-override 属性

名称: font-language-override
取值: normal | <string>
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的字符串或关键字 none
规范顺序: 按语法
动画类型: 离散
Tests

通常情况下,作者可以通过设置元素的内容语言 来控制是否使用特定语言的字形替换与定位, 正如上文所述

<!-- 使用适用于 S’gaw Karen 的特性渲染文本 -->
<p lang="ksw">...</p>

在某些情况下,作者可能需要指定 与内容语言不同的语言系统, 例如需要模仿另一种语言的排版传统时。 font-language-override 属性允许作者 显式指定字体的语言系统, 覆盖由内容语言隐含得到的语言系统。

各取值含义如下:

normal
指定在使用 OpenType 字体渲染时, 由元素的内容语言 来推断 OpenType 语言系统
<string>
单个四字符、 区分大小写的 OpenType 语言系统标签, 用来指定要使用的 OpenType 语言系统, 以替代由元素语言隐含得到的语言系统。 如果字符串长度小于四个字符, 会在末尾以空格(U+0020)填充, 直至长度为 4,然后再进行匹配。

未知的 OpenType 语言系统标签会被静默忽略, 不会影响字形的选择与定位。

7. 字体特性和变化解析

如前一节所述, 可以通过多种方式启用字体特性与变体, 例如在样式规则中使用 font-variantfont-feature-settingsfont-variation-settings, 或在 @font-face 规则内部使用。 这些设置合并后的解析顺序如下所定义。 通过 CSS 属性定义的特性 会叠加在排版引擎的默认特性之上。

7.1. 默认特性

对于 OpenType 字体, 用户代理必须启用 OpenType 规范中 针对给定书写系统(script)和书写模式(writing mode) 所定义的默认特性。 必需连字、常用连字和上下文字形 必须默认启用 (OpenType 特性:rlig, liga, clig, calt), 同时还包括本地化字形 (OpenType 特性:locl) 以及用于正确显示组合字符与附加记号的特性 (OpenType 特性:ccmp, mark, mkmk)。 即使当 font-variantfont-feature-settings 属性的值为 normal 时, 这些特性也必须始终保持启用。 只有在作者显式覆盖时, 单个特性才会被禁用, 例如将 font-variant-ligatures 设置为 'font-variant-ligatures/no-common-ligatures' 时。

Tests

在处理诸如 阿拉伯文蒙古文天城文 等复杂书写系统时, 需要额外的特性。 对于竖排文本行中的直排文本, 必须启用竖排替代字形 (OpenType 特性:vert)。

7.2. 特性和变化的优先级

通用和 字体特定 字体 特性属性设置会按下面的顺序解析,按优先级由低到高排列。此排序用于构造影响给定 文本运行的一组合并字体特性列表。

  1. 应用默认启用的字体特性, 包括针对特定 script 所必需的特性。 这些特性的说明见 § 7.1 Default features

  2. 应用由 font-weightfont-widthfont-style 属性启用的字体变体。

    font-style 启用的取值 会受到字体选择的影响, 因为该属性可能会选择斜体或倾斜体字体。 实际应用的取值 是由字体匹配算法 所确定的最接近匹配值。 用户代理在此步骤中 至多只能应用一个由 font-style 属性启用的取值; “ital” 与 “slnt” 不得同时被设置。

    如果所选字体是在某个 @font-face 规则中定义的, 则本步骤中应用的取值 应先被截断到该规则中 font-weightfont-widthfont-style 描述符所允许的取值范围内。

    随后,本步骤中的取值 还应再(可能再次)截断到 字体实际所支持的取值范围内。

  3. 应用由继承得到的 lang/xml:lang 值 所指定的语言信息。

  4. 如果字体是通过某个 @font-face 规则定义的, 则应用该 @font-face 规则中 font-language-override 描述符 所隐含的字体语言覆盖。

  5. 如果字体是通过某个 @font-face 规则定义的, 该 @font-face 规则中 至少包含一个有效的 font-named-instance 描述符, 且其值不为 'font-named-instance/none', 并且已加载的字体资源中 根据 § 5.1 Localized name matching 规则 存在具有该名称的命名实例, 则应用该命名实例所代表的 所有变体取值。 这些取值会被截断到字体所支持的取值范围内。

  6. 如果字体是通过某个 @font-face 规则定义的, 则应用该 @font-face 规则中 font-variation-settings 描述符 所隐含的字体变体设置。

  7. 如果字体是通过某个 @font-face 规则定义的, 则应用该 @font-face 规则中 font-feature-settings 描述符 所隐含的字体特性。

  8. 应用 font-language-override 属性取值 所隐含的字体语言覆盖。

  9. 应用 font-optical-sizing 属性取值 所隐含的字体变体。

  10. 应用 font-variant 属性、 相关的 font-variant 子属性 以及任何其他使用 OpenType 特性的 CSS 属性 (例如 font-kerning 属性) 所隐含的字体特性。

  11. 应用由 font-variantfont-feature-settings 之外的属性 决定的特性设置。 例如,将 letter-spacing 属性 设为非默认值时, 会禁用可选连字。

  12. 应用 font-variation-settings 属性取值 所隐含的字体变体。 这些取值应被截断到 字体所支持的取值范围内。

  13. 应用 font-feature-settings 属性取值 所隐含的字体特性。

Tests

这种顺序使作者可以先在 @font-face 规则中 为字体建立一套通用默认设置, 再通过属性设置 对特定元素进行覆盖。 通用属性设置会覆盖 @font-face 规则中的设置, 而底层字体特性设置 又会覆盖 font-variant 属性的设置。

当合并后的字体特性设置列表中 针对同一特性包含多个取值时, 采用最后一个取值。 如果字体本身不支持 某个底层字体特性, 文本就按未启用该特性来渲染; 不会触发字体回退, 也不会尝试合成该特性, 除非针对某些特定属性 已有明确规定。

7.3. 特性优先级示例

使用以下样式,当数字在段落中使用时将以比例形式显示,但在价格表中则显示为表格式:
body {
  font-variant-numeric: proportional-nums;
}

table.prices td {
  font-variant-numeric: tabular-nums;
}
@font-face 规则也可以通过使用 local()src 描述符中访问本地可用字体特性,定义如下 @font-face
@font-face {
  font-family: BodyText;
  src: local("HiraMaruPro-W4");
  font-variant: proportional-width;
  font-feature-settings: "ital"; /* CJK 文本中的拉丁斜体特性 */
}

body { font-family: BodyText, serif; }

如果可用,将使用日语字体 "Hiragino Maru Gothic"。当进行文本渲染时,日语假名将按比例间隔,拉丁文本将显示为斜体。使用回退的衬线字体渲染的文本将使用默认的渲染属性。

在下面的示例中,任选连字仅对可下载的字体启用,但在 class 为 "special" 的 span 中禁用:
@font-face {
  font-family: main;
  src: url(fonts/ffmeta.woff) format("woff");
  font-variant: discretionary-ligatures;
}

body         { font-family: main, Helvetica; }
span.special { font-variant-ligatures: no-discretionary-ligatures; }

假设使用 font-feature-settings 规则启用任选连字:

body         { font-family: main, Helvetica; }
span         { font-feature-settings: "dlig"; }
span.special { font-variant-ligatures: no-discretionary-ligatures; }

在这种情况下,任选连字将会在 class 为 "special" 的 span 中呈现。这是因为 font-feature-settingsfont-variant-ligatures 属性均适用于这些 span。尽管 font-variant-ligaturesno-discretionary-ligatures 设置有效地禁用了 OpenType "dlig" 特性,但由于 font-feature-settings 在之后解析,"dlig" 值重新启用了任选连字。

8. 字体变化属性

注意:本节中使用的技术称为“字体变化”。其中一种字体的实例称为“可变字体”。

8.1. 光学尺寸控制:font-optical-sizing 属性

名称: font-optical-sizing
值: auto | none
初始值: auto
应用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的关键字
规范顺序: 按照语法
动画类型: 离散
测试

在排版上,不同大小的文本在视觉上通常会受益于略有不同的表现形式。例如,为了提高小尺寸文本的可读性,笔画通常更粗,衬线更大。大尺寸文本通常具有更精致的形状,笔画的粗细对比更加明显。

auto
用户代理可以根据字体大小和屏幕的像素密度来调整字形的形状。对于使用字体变化的 OpenType 和 TrueType 字体,通常使用“opsz”字体变化来实现此目的。
none
用户代理不得为光学尺寸调整字形的形状。
不同光学尺寸下的文本,标准化为相似的物理尺寸
Century Expanded 在模拟金属形式中的每种尺寸。不同的光学尺寸,标准化为相同的物理尺寸,以保持风格特征并提高可读性。

font-size 必须在为 "opsz" 轴选择变化值时考虑,但也可以考虑其他信号。

注意:用户代理应为 "opsz" 轴提供一个接近 font-size 使用值的值。然而,用户代理可能希望考虑其他因素,例如屏幕的像素密度,或者文本在查看者视网膜中的视角。不过,实验表明,忽略这些其他次要因素,仅使用 font-size 可能是用户代理选择此值的最佳方式。

像素密度以及文本的视觉大小可能会影响为 font-optical-sizing 选择的变化值。当响应用户操作或样式变化时,像素密度或文本的视觉大小发生变化,用户代理不得为此变化选择新值,除非该变化会引发布局变更。用户代理可以自行决定哪些变化会引发布局变更。

注意:某些用户操作,如缩放,可能不被视为布局变更,如果它们不导致文本重新排版。然而,其他用户操作,如为辅助功能目的增加文本大小,可能会被视为布局变更,因为它们会导致文本重新排版。同样,transform 属性通常不被视为引发布局变更,因为变换通常不会导致文本重新排版。每个用户代理可以自行决定每个操作是否导致布局变化。

用户代理不得在字体未直接执行时合成光学尺寸调整。

用户代理不得选择字体未支持的 "opsz" 轴值。可以通过将选择的值限制在字体支持的范围内来实现此目的。

font-optical-sizingfont-size-adjust 相关联。应用光学尺寸调整时,用户代理必须根据调整后的字体大小应用适当的光学尺寸值,前提是遵守上述限制。

8.2. 低级字体变化设置控制:font-variation-settings 属性

名称: font-variation-settings
取值: normal | [ <opentype-tag> <number> ]#
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 关键字 normal 或一个列表,其中每一项是“字符串 + 数值”配对
规范顺序: 按语法
动画类型: 见后文说明
Tests

该属性为 OpenType 或 TrueType 字体变体 提供底层控制。 它的目标是为那些 并不广泛使用、 但在特定用例中又确实需要的 字体变体提供访问途径。

作者不应使用 font-variation-settings 来设置下表中的任一变体轴。 相反,请使用更高层的替代属性,因为:
  1. 高层属性可以分别参与层叠。 你可以只设置其中一个, 而不必一次性重写整个 font-variation-settings 列表
  2. 对不支持某些字体变体的字体, 有些高层属性仍可以通过合成方式提供效果。
如果你想设置这个变体轴 那么请使用这个(而不是)font-variation-settings 说明
字重(wghtfont-weight font-weight 属性 会在存在该轴时设置 wght 轴。
宽度(wdthfont-width font-width 属性 会在存在该轴时设置 wdth 轴。
倾斜(slnt)或斜体(italfont-style font-style 属性 会视其取值来设置 slntital 轴。
光学尺寸(opszfont-optical-sizing font-optical-sizing 属性 会在存在该轴时设置 opsz 轴。

使用字体变体设置 并不会影响回退字体的选择; 而对同一变体轴 使用字体属性(如 font-weight 等) 则会对字体选择产生影响。

在可能的情况下, 作者一般应优先使用 其他与字体变体相关的属性 (例如 font-optical-sizing), 仅在一些特殊情形下才使用本属性, 即当它是访问某个 很少使用但又必须使用的 字体变体的唯一途径时。

例如, 推荐使用 font-weight: 700, 而不是 font-variation-settings: "wght" 700。

取值 normal 表示由于该属性 不会发生任何字形形状、匹配或定位的变化。

<opentype-tag> 是区分大小写的 OpenType 或 TrueType 变体轴名称。 按 OpenType / TrueType 规范, 轴名称由四个 ASCII 字符组成。 长于或短于四个字符的轴名称字符串, 或包含 U+20–7E 之外字符的名称, 都是无效的。 轴名称只需与字体中定义的某个轴标签匹配即可, 因此并不限于 显式注册的 OpenType / TrueType 变体轴。 定义自定义轴名称的字体 应遵循 OpenType 规范中的 命名规则

如果字体不支持某个轴, 对该轴的取值设置会被忽略, 因而不会产生任何效果; 用户代理不得基于这些轴标签 尝试合成回退行为。 同一条 CSS font-variation-settings 声明中的 其他轴取值则不受影响。

如果字体支持某个变体轴, 但所设取值超出了 该字体预定义的范围, 则会被截断到 离它最近的、字体所支持的值。

取值允许为小数或负数。

Note: 获得倾斜字形时, 更推荐使用 font-style 属性。 然而,如果通过 font-variation-settings 直接使用 slnt 轴, 需要记住该轴是以 “正角度表示逆时针倾斜”来定义的, 与 CSS 的方向相反。

如果同一轴名称出现多次, 则最后一次出现所对应的取值 会覆盖该轴之前的所有取值。 这种去重行为可以通过 访问该属性的计算值观察到。

计算值中包含 去重后的轴名称, 并按照 码元(code unit) 升序排序。

尽管该属性是专门为 OpenType / TrueType 变体定义的, 但未来也可能为其他 支持字体变体的现代字体格式 增加变体轴。 在可能的情况下, 其他字体格式中定义的变体 应尽量遵循 已注册变体轴的模式。

可以通过如下机制 对 font-variation-settings 进行动画。 若两条 font-feature-settings 声明 是“相似”的,则它们可以互相之间进行插值动画。 这里“相似”是指两条声明中出现了相同集合的属性 (顺序不限)。 由于后出现的重复属性 会覆盖先前的同名属性, 即便两条声明中的属性数量不同, 只要最终集合一致, 也可以视为“相似”。 如果两条声明“相似”, 则会在动画过程中 对声明中对应的取值成对插值。 否则,就无法进行动画; 在这种情况下, 动画过程中的某个未指定时间点, “from” 端的取值会被切换成 “to” 端的取值。

9. 彩色字体支持

彩色字体不仅允许字体文件描述 用于勾勒字形边缘的轮廓, 还允许描述字形内部所呈现的颜色。

an example multicolored font
Multicolore,作者:Ivan Filipov
an example multicolored font
Magical Unicorn Neue Pro,作者:Arthur Reinders Folmer
an example multicolored font
Reem Kufi Ink,作者:Khaled Hosny 和 Santiago Orozco

对于某些用途,例如 emoji, 将颜色固定在字体中是合适的。 但在其他场景下,则需要能够从样式表中 控制所使用的颜色。

Tests

CSS 提供了两种方式来实现这一点。 font-palette 属性允许从字体中 所包含的多个不同调色板中 选择其一。 @font-palette-values 规则则允许 覆盖调色板中的一个或多个颜色, 甚至允许创建 一整套完全不同的调色板。

9.1. 控制彩色字体调色板:font-palette 属性

许多彩色字体文件格式允许将字形内部的颜色参数化。 在这些字体中,描述每个字形的几何形状时, 会通过索引来引用颜色。 这些索引会在当前激活的调色板中解析, 解析所用的查找表存储在字体内部。 不过,许多字体包含多个调色板, 每个调色板都包含一组互补的颜色, 由字体设计者挑选, 以提供令人愉悦的视觉效果。

此外,一些彩色字体文件格式 既提供常规的、无颜色的字形轮廓, 也提供彩色版本。

名称: font-palette
取值: normal | light | dark | <palette-identifier> | <palette-mix()>
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的关键字、标识符或 <palette-mix()> 函数。 若得到的调色板等价, <palette-mix()> 必须被简化为单个关键字或标识符。
规范顺序: 按语法
动画类型: 按计算值
Tests

随着如下所定义的 palette-mix() 函数:

<palette-mix()> = palette-mix(<color-interpolation-method> , [ [normal | light | dark | <palette-identifier> | <palette-mix()> ] && <percentage [0,100]>? ]#{2})
normal
如果 color-scheme 属性被设置为 非 normal' 的值, 用户代理应根据情况选择第一个 light 或 dark 调色板。 否则,用户代理使用默认调色板 或默认字形着色来显示彩色字体。

当彩色字体格式需要使用前景色时, 用户代理应考虑 color 属性的计算值。

COLR [OPENTYPE] 表中, 颜色索引 0xFFFF 应按 color 属性进行渲染。
对于 COLR/CPAL [OPENTYPE] 字体, font-palette: normal 通常意味着使用字体中索引为 0 的调色板来渲染。
light
一些彩色字体格式包含元数据, 标记某些调色板适用于浅色(接近白色)背景。 此关键字会使用户代理 使用字体文件中第一个以这种方式标记的可用调色板。 如果字体文件格式不支持此类元数据, 或字体中没有调色板以这种方式标记, 则该值的行为与 normal 相同。
dark
一些彩色字体格式包含元数据, 标记某些调色板适用于深色(接近黑色)背景。 此关键字会使用户代理 使用字体文件中第一个以这种方式标记的可用调色板。 如果字体文件格式不支持此类元数据, 或字体中没有调色板以这种方式标记, 则该值的行为与 normal 相同。
<palette-identifier>
该值用于标识要使用的、由 CSS 定义的调色板。 用户可以使用 @font-palette-values 规则来定义调色板。 如果不存在适用的 @font-palette-values 规则, 则该值的行为与 normal 相同。

<palette-identifier> 会被解析为 <dashed-ident>

Note: 这种由 CSS 定义的调色板 既可能是对字体中已存在调色板的引用, 也可能是对字体中已存在调色板的修改, 也可能是一个全新的调色板。

<palette-mix()>
该值定义了两个调色板取值之间插值的位置。 两个调色板取值可以由 <palette-identifier> 标识, 也可以由调色板关键字 normallightdark 标识, 或由另一个 <palette-mix()> 值标识。

字体的字形必须使用一个通过创建的调色板来渲染: 对于每个调色板颜色索引, 在作为参数指定的第一个与第二个调色板的对应颜色索引之间进行插值; 如有需要,应递归解析 <palette-mix()> 函数。

对每个调色板颜色, 插值遵循 <color-mix()> 函数的规则。

百分比会根据 CSS Color 5 § 3.2 百分比归一化(Percentage Normalization) 进行归一化。

Tests

Note: 名称 'font-palette/light' 与 'font-palette/dark' 描述的是 该调色板可用于的背景, 而不是调色板本身的颜色。

当深色模式生效时,使用深色模式调色板
@media (prefers-color-scheme: dark) {    .banner {font-palette: dark;
  }
}
在调色板之间做动画。
@font-palette-values --pink {
  font-family: Nabla;
  base-palette: 1;
}

@font-palette-values --yellow {
  font-family: Nabla;
  base-palette: 7;
}

@keyframes animate-palette {
  from {
    font-palette: --yellow;
  }
  to {
    font-palette: --pink;
  }
}

p {
  font-family: Nabla;
  animation: animate-palette 1.4s infinite alternate linear;
}
The word Animate animated between a pink and a yellow palette.
Nabla Color by typearture.com —— 在字体中的调色板 1 与 7 之间做动画。
Tests

添加更多示例与图片。

9.2. 用户定义的字体颜色调色板:@font-palette-values 规则

@font-palette-values 规则用于定义一个颜色调色板, 并将该调色板与某个特定字体关联起来。 这使得 Web 作者可以为彩色字体 任意选择样式表中的 <color>, 而不再局限于字体文件内部 预先存在的调色板。

Note: OpenType 的 CPAL 表仅支持 sRGB 颜色。 <color>@font-palette-values 中则可以是任意 CSS 颜色。 目前某些实现使用的底层 API 仍然受限于 sRGB, 因而可能会将指定颜色映射到 sRGB。 这被视为一种暂时性的限制。 作者不应依赖这种映射到 sRGB 的行为。

此外,该规则与特定字体的关联 使得同一个调色板名称 可以在不同字体中产生不同的效果, 这就允许在一个元素中使用多字体时 (例如字体回退), 在多种字体之间使用相似的颜色。

Note: Web 作者可能希望为单个字体 创建多个调色板, 以便为其 Web 内容制作多套主题。 Web 作者也可能希望 为多种字体创建相互匹配的调色板, 以便在一组不同字体之间 实现统一的设计风格。

@font-palette-values 规则表示 字体中使用的一组颜色调色板。 一个调色板由一个有序的颜色集合构成。 使用 @font-palette-values, Web 作者既可以引用字体内部已有的调色板, 也可以创建由作者自定义颜色填充的调色板。 此外,它还允许用作者描述的颜色 覆盖字体调色板中的一组颜色。

调色板始终是完整的, 这意味着不可能描述 一个缺少某些颜色的调色板。 如果某些颜色原本会缺失, 则从字体内由 base-palette 描述符 所指明的调色板中补足。

数学函数(Math functions), 如 calc(), 以及 var()env(), 都可以合法地出现在 @font-palette-values 规则中的描述符取值里。 它们会在根元素的上下文中进行求值。 相对单位也同样在根元素上下文中求值。

@font-palette-values 规则 由 @font-palette-values at-keyword 加上一组描述符声明块组成。 它具有如下语法:

@font-palette-values <dashed-ident> {
  <declaration-list>
}
Tests

@font-palette-values 规则 接受本规范中定义的各个描述符。

如果用相同名称 定义了多条 @font-palette-values 规则, 则文档顺序中最后一条生效, 其余规则全部被忽略。

修改 Bixa Color 的调色板。
@font-palette-values --Cooler {
  font-family: Bixa;
  base-palette: 1;
  override-colors:
    1 #7EB7E4;
}
overriding a color
Bixa Color,来自 Novo Typo。上图使用字体内原有颜色; 下图将橙色改成了蓝色。
修改 Handover Sans 的调色板
@font-palette-values --Augusta {
  font-family: Handover Sans;
  base-palette: 3;
  override-colors:
    1 rgb(43, 12, 9),
    3 var(--highlight);
}

这些描述符仅在其所定义的 @font-palette-values 规则的上下文中生效, 不会作用于文档语言元素。 当某个描述符 在同一条 @font-palette-values 规则中出现多次时, 只有最后一个声明会被使用, 该描述符的所有先前声明都会被忽略。

每一条这样的调色板 都会应用到共享同一字体家族名的 每个 @font-face 上。

我希望为两个彩色字体 使用偏绿色的调色板。 第一个字体 Bixxxa 已经自带 一个可用的绿色调色板, 但对 Bungeehee 来说, 我需要覆写其中一个颜色 才能获得我的绿色调色板。
@font-face {
  font-family: Bixxxa;
  src: url('./bixxxa.woff') format('woff');
}

@font-face {
  font-family: Bungeehee;
  src: url('./bungeehee.woff') format('woff');
}

@font-palette-values --ToxicGreen {
  font-family: Bixxxa;
  base-palette: 3; /* 这是 Bixxxa 的绿色调色板 */
}


@font-palette-values --ToxicGreen {
  font-family: Bungeehee;
  base-palette: 7; /* 这是 Bungeehee 的绿色调色板…… */
  override-colors: 2 lime; /* ……只是其中这个颜色是粉色,我把它改成 lime */
}

h1 {
  font-family: Bixxxa;
  font-palette: --ToxicGreen;
}

h2 {
  font-family: Bungeehee;
  font-palette: --ToxicGreen;
}

示例作者:Roel Nieskens

Note: 当一个家族名 被多个物理字体共享时 (例如通过 unicode-range 创建复合字体时), 如果这些字体拥有不同的调色板, 那么使用 @font-palette-values 指定部分调色板时, 结果往往不会是作者预期的。 在这种情况下, 最好提供一份完整的调色板定义。

在上面的示例中, 由于已经为两个不同的字体家族 设置了名称兼容的调色板, 于是就可以进一步写出:
h3 {
  font-family: Bixxxa, Bungeehee;
  font-palette: --ToxicGreen;
}

即便两个字体的内部调色板编号不同, 上述写法也能在每个字体中 正确应用所需的调色板。

某组 @font-palette-values 规则 决定了哪些作者自定义调色板 可以在包含这些规则的文档中使用。

作者自定义的字体颜色调色板 只能在引用它的文档中可用。 若在引用它的文档之外 使用作者自定义调色板, 会构成安全漏洞, 因为一个页面的内容 将能够影响其他页面, 攻击者可以将其作为攻击向量。

该 at-rule 遵循 CSS 的前向兼容解析规则。 与声明块中的属性类似, 对于用户代理不支持的描述符声明, 必须直接忽略。 @font-palette-values 规则要求必须包含 font-family 描述符; 若缺少该描述符, 则这一整条 @font-palette-values 规则无效, 必须被完全忽略。

在用户代理平台资源有限、 未实现彩色字体支持、 或实现了关闭彩色字体能力的情况下, 必须直接忽略 @font-palette-values 规则; 本规范中对各个描述符 的行为定义不应因此被改变。

9.2.1. 字体族:font-family 描述符

名称: font-family
用于: @font-palette-values
值: <family-name>#
初始值: N/A

该描述符定义了此调色板适用的字体家族, 使用与 § 5 字体匹配算法 相同的字体家族列表。 此调色板只会应用到具有这些家族名称的字体。 该描述符的取值意味着只允许具名字体家族, 若在字体家族列表中包含通用字体则属于语法错误。 如果在字体家族列表中出现语法错误, 必须忽略该描述符 (仍会出现在 CSS OM 中,但不会匹配任何字体家族)。

9.2.2. 指定基础调色板:base-palette 描述符

名称: base-palette
用于: @font-palette-values
值: light | dark | <integer [0,∞]>
初始值: N/A
light
某些彩色字体格式包含元数据, 将某些调色板标记为适用于浅色(接近白色)背景。 此关键字标识字体文件中 第一个以这种方式标记的可用调色板。 如果字体文件格式不支持此类元数据, 或字体中没有调色板以这种方式标记, 则该值的行为等同于 0。
dark
某些彩色字体格式包含元数据, 将某些调色板标记为适用于深色(接近黑色)背景。 此关键字标识字体文件中 第一个以这种方式标记的可用调色板。 如果字体文件格式不支持此类元数据, 或字体中没有调色板以这种方式标记, 则该值的行为等同于 0。
<integer [0,∞]>
标识字体中的一个(从 0 开始计数的)数值调色板索引。
修改 Banner Flag 的颜色调色板
@font-palette-values --Festival {
  font-family: Banner Flag;
  base-palette: 1;
  override-colors:
    0 rgb(123, 64, 27),
    1 darkblue,
    2 var(--highlight);
}

该描述符指定了字体中的一个调色板, 外层 @font-palette-values 规则 以其作为初始值。 如果 @font-palette-values 规则中 不存在 override-colors 键, 则该 @font-palette-values 规则 表示字体中索引与此描述符取值相同的调色板。 如果 override-colors 键 存在于 @font-palette-values 规则中, 则该描述符取值中的每一项 都会覆写此 @font-palette-values 块 所表示颜色调色板中的单个颜色。

为 Handover Sans 的第 3 个颜色调色板命名
@font-palette-values --Augusta {
  font-family: Handover Sans;
  base-palette: 3;
}

如果该描述符未出现在 @font-palette-values 中, 或字体在 base-palette 的取值所指示索引处 并不包含调色板, 则行为等同于指定了 0。 若字体不包含任何颜色调色板, 则由此 @font-palette-values 规则 所表示的初始颜色调色板 中不包含任何颜色。 可以通过在 @font-palette-values 规则中 使用 override-colors 描述符 来覆写调色板中的颜色。

9.2.3. 覆盖调色板中的颜色:override-colors 描述符

名称: override-colors
用于: @font-palette-values
值: [ <integer [0,∞]> <color> ]#
初始值: N/A

该描述符会对由此 @font-palette-values 规则 所表示的初始颜色调色板进行颜色覆写。

override-colors 描述符 接受一个由调色板索引项与颜色组成的 逗号分隔列表。 该列表中的每一项 都是一个二元组, 包含一个调色板条目 以及用于替换它的颜色。

每个指定的 <color> 必须是 绝对颜色(absolute color), 否则该描述符无效。

对于此描述符取值中的每个键/值对, 初始调色板中(即由 base-palette 描述符 所确定的调色板) 具有相同键的颜色 会被此描述符中指定的颜色覆写。 若某个键超出了初始调色板索引范围, 则忽略该键, 但这不会使描述符整体无效。

override-colors 描述符中的调色板索引项, 是从 0 开始计数的调色板索引条目。

整数值使用零起始索引。

如果多个不同的键/值对 的键标识了同一个颜色索引 (无论是通过名称还是整数), 那么在渲染时会采用最后一个键; 但在序列化时, 这两个键/值对都会保留。

Note: 这意味着, 在两个不同元素上 为 font-palette 使用相同的取值时, 实际使用的调色板可能不同, 因为 @font-palette-values 规则内部 变量的取值 可能在这两个元素各自的上下文中 有不同的应用结果。

从 CSS 提供的颜色 (无论是作为覆写, 还是作为新条目) 都可以使用任何受支持的颜色空间。

修改 Blaka Ink 的颜色调色板
@font-palette-values --Festival {
  font-family: Blaka Ink;
  base-palette: 0;
  override-colors:
    0 oklch(0.63 0.12 105.7),
    1 color(display-p3 0.23 0.22 0.04),
    2 color(prophoto-rgb 0.37 0.27 0.09);
}

Note: CPAL 表 0 与 1 版本中指定的颜色 都是 sRGB 颜色。

9.3. 选择文本呈现样式:font-variant-emoji 属性

名称: font-variant-emoji
取值: normal | text | emoji | unicode
初始值: normal
适用于: 所有元素和文本
是否继承:
百分比: 不适用
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散
Tests

该属性允许 Web 作者选择 对某些 emoji 码位 使用表情呈现(emoji presentation) 还是文本呈现(text presentation)。 传统上,这两种呈现风格 是通过在特定码位后附加 Variation Selector 15 (U+FE0E) 或 Variation Selector 16 (U+FE0F) 来选择的。 而 font-variant-emoji 则允许 Web 作者 设置一种默认呈现风格, 以替代变体选择符。

只有被 Unicode 列出 为会构成 Unicode emoji 呈现序列的码位 会受到该属性影响。 在本 CSS 规范中, 这些字符被称为 Emoji 呈现参与码位(Emoji Presentation Participating Code Points)。 该属性对其他任何字符 都没有影响。

预期该属性会影响字体回退; 不过,字体回退与 font-variant-emoji 的具体交互方式 并未作出明确规定。 然而,变体选择符必须 包含在前一个簇内, 如上文 cluster matching 一节所定义。 这一行为的直接结果是: 变体选择符不得使用 与前一个字符不同的字体来渲染。 它因此使字体回退的行为 如同相关变体选择符 已被使用(与各取值描述相同); 然后再执行字体回退, 包括簇级回退规则, 且回退过程必须将 这些“附加”的变体选择符的 呈现偏好考虑在内。

即便使用了 font-variant-emoji, 元素内容中 若显式存在 Variation Selector 15 (U+FE0E) 或 Variation Selector 16 (U+FE0F), 也会覆盖 font-variant-emoji 中指定的渲染方式。 因此,font-variant-emoji 设置的是一个默认呈现方式, 文本内容可以通过显式变体选择符 选择不使用该默认。

Note: 不同平台之间 在如何处理 emoji 呈现序列方面 有不同的惯例。 跨平台的 UA 可能会选择 遵循各个平台各自的惯例, 也可能会在所有平台上 采用统一的处理方式。 当被要求进行 emoji 风格渲染时, UA 可能会忽略 不包含彩色表(color tables)的字体。 另一个 UA 则可能更愿意 使用与任意簇相同的 机械式簇级回退算法。

除 FE0E VARIATION SELECTOR-15 与 U+FE0F VARIATION SELECTOR-16 外的 其他变体选择符 不得对字体选择产生任何影响。 如果出现了此类变体选择符, 但之前选定的字体并不支持它, 则应忽略该变体选择符。

当 UA 决定 是否对某个字符 使用 emoji 呈现或文本呈现时, 不应考虑 BCP47 中 通过 -u- 扩展到语言标签上的内容 (即 lang 或 xml:lang 接受的那部分)。

normal
用户代理可以自行选择 将某个 Emoji 呈现参与码位 以 emoji 风格 或文本风格绘制。 用户代理通常会在做出这一决定时 遵循平台的惯例。
text
各个码位的渲染方式 如同在每个 Emoji 呈现参与码位 后面都附加了 U+FE0E VARIATION SELECTOR-15 一样。
emoji
各个码位的渲染方式 如同在每个 Emoji 呈现参与码位 后面都附加了 U+FE0F VARIATION SELECTOR-16 一样。
unicode
各个码位会依据 [UTS51] 中的规定, 按 emoji-default、text-default 或 text-only 的方式呈现, 具体取决于每个 Emoji 呈现参与码位 的 Emoji 与 Emoji_Presentation 属性值。 若存在 FE0E VARIATION SELECTOR-15 或 U+FE0F VARIATION SELECTOR-16, 则会覆盖单个 Emoji 呈现参与码位 的默认呈现方式。
若要显示 U+1F6CB COUCH AND LAMP 的 emoji 形式, 可令 CustomEmoji.ttf 遵循用户代理对该字符 emoji 形式支持的判断, 然后使用如下代码:
@font-face {
  font-family: "Custom Emoji";
  src: url("CustomEmoji.ttf") format("truetype");
}
...
<div style="font-family: 'Custom Emoji'; font-variant-emoji: emoji;">&#x1F6CB;</div>

10. 字体分类

一个给定的字体可能属于以下一个或多个类别:

10.1. 已安装字体

字体可以全局安装在设备上。这类字体通常在任何应用程序中都可以访问,即使是没有 CSS 概念的应用程序。支持字体对象的文件存在于用户的设备上,而不是作为远程资源。

已安装字体不能是 Web 字体,Web 字体也不能是已安装字体。

10.2. Web 字体

字体可能由远程资源支持,必须使用用户代理的资源获取机制进行请求。Web 字体由以下两种机制之一表示:

Web 字体不能在与 @font-face 规则关联的文档或拥有 FontFaceSet 的文档之外的任何其他文档中访问。 设备上的其他应用程序不能访问 Web 字体。

已安装字体不能是 Web 字体,Web 字体也不能是已安装字体。

Web 字体会遮盖已安装字体,因此如果已安装字体的系列名称与 Web 字体相同,则无法访问已安装字体。

10.3. 预安装字体和用户安装字体

用户可以选择在其设备上安装字体。 用户安装字体是通过用户的明确操作安装的,例如点击"安装"按钮或将文件复制到设备的特定目录中。 这些字体是用户安装字体,也是已安装字体。 Web 内容作者不应依赖用户安装字体,因为无法保证任何用户都会执行安装特定字体的操作。

请参阅 字体匹配算法,了解用户安装字体如何与字体匹配算法交互。

任何非用户安装的已安装字体都是预安装字体。很可能特定操作系统版本的所有用户都安装了相同的预安装字体集。因此,针对这些操作系统的 Web 内容作者可能希望在 font-family 属性中使用这些字体系列名称。

10.4. 系统字体

系统字体是由 system-ui 通用字体家族名 使用的字体。它是预装字体(Preinstalled Font)的一个示例。

如果系统提供,额外的字体样式也可以作为 ui-sans-serif, ui-serif, ui-monospace, 和 ui-rounded 提供;这些在系统提供时也属于预装字体。

测试

11. 字体技术与格式

11.1. 字体技术

The features-opentype, features-aat and features-graphite 技术指的是对字体特性的支持, 这些特性常见于 [OPENTYPE] 中,通过 GSUBGPOS 表来实现,也可以在 [AAT-FEATURES] 中使用 morxkerx 表来实现,或在 [GRAPHITE] 中使用 SilfGlat Gloc Feat Sill 表实现,如 Graphite Table Format 所记载。关于与这些机制交互的属性,请参阅 § 6 Font Feature Properties 一节。

The variations 技术指的是对字体变体(font variations)的支持, 这些通常在 [OPENTYPE] 中通过 avarcvarfvargvarHVARMVARSTATVVAR 表实现,也可以在 [AAT-FEATURES] 中通过 avarcvarfvargvar 表实现。关于与这些机制交互的属性,请参阅 § 2 Basic Font Properties 以及 § 8 Font Variation Properties 一节。

The color-colrv0, color-colrv1, color-svg, color-sbix and color-cbdt 技术指的是各种彩色字体文件技术。 每一种都对应字体中的一个表 (COLRSVGsbixCBDT) 在 [OPENTYPE][AAT-FEATURES] 字体中, 必须支持这些表才能满足相应的要求。

The palettes 技术指的是对字体调色板(font palettes)的支持, 通常在 [OPENTYPE][AAT-FEATURES] 中通过 CPAL 表实现。关于与这些机制交互的属性,请参阅 § 9 Color Font Support 一节。

The incremental 技术指的是客户端对增量字体传输的支持 ,参见 [IFT]

有关这些技术的背景,请参阅 [PFE-report]

Web 作者可以在 tech() 函数中指定所需的支持, 将其置于 @font-facesrc 描述符内, 以表明渲染该字体所必需的功能。 当所请求的支持不存在时,该机制可用于优雅地回退到辅助字体。

这个 @font-face 块展示了如何在用户代理支持 彩色字体时, 如果不支持,则回退到非彩色字体。
@font-face {
  font-family: "Trickster";
  src: url("trickster-COLRv1.otf") format(opentype) tech(color-COLRv1),
  url("trickster-outline.otf") format(opentype);
}

11.2. 字体格式

本规范定义的格式字符串如下。 <font-format> 值是以下格式的同义词。

字符串 字体格式 常见扩展名 常见媒体类型
"collection" OpenType 集合 .otc,.ttc font/collection
"embedded-opentype" 嵌入式 OpenType .eot application/vnd.ms-fontobject
"opentype" OpenType .ttf, .otf font/otf, font/ttf
"svg" SVG 字体(已弃用) .svg, .svgz image/svg+xml
"truetype" TrueType .ttf font/ttf
"woff" WOFF 1.0(Web Open Font Format) .woff font/woff
"woff2" WOFF 2.0(Web Open Font Format) .woff2 font/woff2
测试

鉴于 TrueType 与 OpenType 在常见用法上的重叠,格式提示 "truetype" 与 "opentype" 必须视为同义; 提示 "opentype" 并不意味着该字体包含 Postscript CFF 风格的字形数据, 也不意味着它包含 OpenType 布局信息(有关更多背景,请参见 附录 A)。

12. 对象模型

这些 @font-face@font-feature-values 规则的内容 可以通过下面对 CSS 对象模型的扩展来访问。

测试

12.1. CSSFontFaceRule 接口

CSSFontFaceRule 接口表示一条 <@font-face> 规则。

[Exposed=Window]
interface CSSFontFaceDescriptors : CSSStyleDeclaration {
  attribute [LegacyNullToEmptyString] CSSOMString src;
  attribute [LegacyNullToEmptyString] CSSOMString fontFamily;
  attribute [LegacyNullToEmptyString] CSSOMString font-family;
  attribute [LegacyNullToEmptyString] CSSOMString fontStyle;
  attribute [LegacyNullToEmptyString] CSSOMString font-style;
  attribute [LegacyNullToEmptyString] CSSOMString fontWeight;
  attribute [LegacyNullToEmptyString] CSSOMString font-weight;
  attribute [LegacyNullToEmptyString] CSSOMString fontStretch;
  attribute [LegacyNullToEmptyString] CSSOMString font-stretch;
  attribute [LegacyNullToEmptyString] CSSOMString fontWidth;
  attribute [LegacyNullToEmptyString] CSSOMString font-width;
  attribute [LegacyNullToEmptyString] CSSOMString unicodeRange;
  attribute [LegacyNullToEmptyString] CSSOMString unicode-range;
  attribute [LegacyNullToEmptyString] CSSOMString fontFeatureSettings;
  attribute [LegacyNullToEmptyString] CSSOMString font-feature-settings;
  attribute [LegacyNullToEmptyString] CSSOMString fontVariationSettings;
  attribute [LegacyNullToEmptyString] CSSOMString font-variation-settings;
  attribute [LegacyNullToEmptyString] CSSOMString fontNamedInstance;
  attribute [LegacyNullToEmptyString] CSSOMString font-named-instance;
  attribute [LegacyNullToEmptyString] CSSOMString fontDisplay;
  attribute [LegacyNullToEmptyString] CSSOMString font-display;
  attribute [LegacyNullToEmptyString] CSSOMString fontLanguageOverride;
  attribute [LegacyNullToEmptyString] CSSOMString font-language-override;
  attribute [LegacyNullToEmptyString] CSSOMString ascentOverride;
  attribute [LegacyNullToEmptyString] CSSOMString ascent-override;
  attribute [LegacyNullToEmptyString] CSSOMString descentOverride;
  attribute [LegacyNullToEmptyString] CSSOMString descent-override;
  attribute [LegacyNullToEmptyString] CSSOMString lineGapOverride;
  attribute [LegacyNullToEmptyString] CSSOMString line-gap-override;
};

[Exposed=Window]
interface CSSFontFaceRule : CSSRule {
  [SameObject, PutForwards=cssText] readonly attribute CSSFontFaceDescriptors style;
};

12.2. CSSFontFeatureValuesRule 接口

CSSRule 接口扩展如下:

partial interface CSSRule {  const unsigned short FONT_FEATURE_VALUES_RULE = 14;
};

CSSFontFeatureValuesRule 接口表示一条 @font-feature-values 规则。

[Exposed=Window]
interface CSSFontFeatureValuesRule : CSSRule {
  attribute CSSOMString fontFamily;
  readonly attribute CSSFontFeatureValuesMap annotation;
  readonly attribute CSSFontFeatureValuesMap ornaments;
  readonly attribute CSSFontFeatureValuesMap stylistic;
  readonly attribute CSSFontFeatureValuesMap swash;
  readonly attribute CSSFontFeatureValuesMap characterVariant;
  readonly attribute CSSFontFeatureValuesMap styleset;
  readonly attribute CSSFontFeatureValuesMap historicalForms;
};

[Exposed=Window]
interface CSSFontFeatureValuesMap {
  maplike<CSSOMString, sequence<unsigned long>>;
  undefined set(CSSOMString featureValueName,
    (unsigned long or sequence<unsigned long>) values);
};
fontFamily 类型为 CSSOMString
为指定的一组特性值定义的一个或多个字体家族的列表。
值映射,类型为 CSSFontFeatureValuesMap,只读
将特性值名称与对应特性值关联起来的映射,适用于给定的 font-variant-alternates 值类型

每个 CSSFontFeatureValuesRule 的值映射属性都反映了通过相应的 feature value block 定义的值。因此,annotation 属性包含 @annotation feature value block 中的值,ornaments 属性包含 @ornaments feature value block 中的值,依此类推。

CSSFontFeatureValuesMap 接口使用 默认的 map 类方法,但 set 方法具有不同的行为。它接受一个无符号整数序列,并将其与给定的 featureValueName 关联。该方法的行为与默认的 map 类方法相同,唯一的区别是单个无符号 long 值会被视为包含单个值的序列。如果传入的值数量不合法,该方法会抛出异常。如果关联的 feature value block 只允许有限数量的值,当传入给 set 的序列包含超过该限制的值时,set 方法会抛出 InvalidAccessError 异常。有关某类 feature value block 允许的最大值数量的详细信息,请参见 multi-valued feature value definitions 的描述。get 方法始终返回一个值序列,即使该序列仅包含一个值。

12.3. CSSFontPaletteValuesRule 接口

[Exposed=Window]interface CSSFontPaletteValuesRule : CSSRule {
  readonly attribute CSSOMString name;
  readonly attribute CSSOMString fontFamily;
  readonly attribute CSSOMString basePalette;
  readonly attribute CSSOMString overrideColors;
};

fontFamilybasePalette 接口根据相应的 CSS 属性语法进行解析。

13. 序列化

13.1. 序列化与字体相关的属性

除非个别属性特别注明,本模块定义的属性遵循 CSSOM § 6.7.2 CSS 值的序列化 的原则。

测试

13.2. 序列化与字体相关的 at-rules

除非个别描述符特别注明,本模块中 at-rules 的描述符遵循 CSSOM § 6.7.2 CSS 值的序列化 的原则。

特别是,遵循简洁表示原则:对于接受一系列值的描述符,如果起始值和结束值相同(范围为零),则该描述符序列化为单个值,而不是范围。

测试
例如,规则:
@font-face { 
  font-family: "foo"; 
  font-weight: 200 200; 
} 

将会序列化为:

@font-face { 
  font-family: "foo"; 
  font-weight: 200; 
} 

此外,遵循仅保留最后定义的值的原则,以及简洁表示的原则,重复指定的元组和多个块将被序列化为仅包含最后定义值的单个块。

例如,声明:
/* 重复的声明名称,以及相同类型的多个块 */ 
@font-feature-values foo { 
  @swash { pretty: 0; cool: 2; } 
  @swash { pretty: 1; } 
} 

将会序列化为:

/* 规范序列化 */ 
@font-feature-values foo {
    @swash { cool: 2; pretty: 1; } 
}
测试

附录A:将平台字体属性映射到 CSS 属性

本附录作为对某些在其他章节中描述的问题和 情形的背景说明而收录。它应仅被视为 参考性资料。

CSS 中的字体属性被设计为与所用的底层字体格式相互独立; 它们既可用于指定位图字体、 Type1 字体、 SVG 字体, 也可用于常见的 TrueType 与 OpenType 字体。 但是 TrueType 与 OpenType 格式的某些方面 常常会令作者困惑, 并在不同平台上给实现者带来挑战。

TrueType 最初由 Apple 开发, [TRUETYPE] 被设计为一种既适用于屏幕又适用于印刷的轮廓字体格式。 Microsoft 后来与 Apple 一同参与了 TrueType 格式的开发, 此后两大平台均支持 TrueType 字体。 TrueType 格式的字体数据由一组以常见四字符标签命名的表组成, 每个表包含某一类型的特定数据。 例如, 包含版权与许可信息的命名信息 存储在 name 表中。 字符映射cmap)表 包含从字符编码到字形的映射。 Apple 随后为支持增强排版功能而增加了附加表; 这些现在称为 Apple Advanced Typography,或 AAT,字体。 Microsoft 与 Adobe 开发了一套用于高级排版的独立表集, 并将其格式称为 OpenType [OPENTYPE]。 OpenType 规范在 ISO 中被标准化为 Open Font Format [OPEN-FONT-FORMAT]

在许多情况下,Microsoft Windows 或 Linux 下使用的字体数据 与 Apple 的 Mac OS X 下使用的数据略有不同, 因为 TrueType 格式允许在不同平台间存在显式差异。 这包括字体度量(metrics)、 名称以及 字符映射 数据。

具体而言, 字体家族名称数据在各平台上的处理方式不同。 对于 TrueType 与 OpenType 字体, 这些名称存储在 name 表中, 位于 name ID 为 1 的 name 记录里。 可以为不同的区域设置存储多个名称, 但 Microsoft 建议字体 至少包含一个美式英语版本的名称。 在 Windows 上, 为了向后兼容,Microsoft 决定将该家族名限制为最多四个字形; 对于更大的分组,可以使用 “首选家族”(name ID 16)或 “WWS 家族”(name ID 21)。 其他平台(例如 OSX)则没有此限制, 因此家族名用于定义所有可能的分组。

其他 name 表数据提供用于在家族内唯一标识某一特定字形的名称。 完整字体名称(name ID 4)和 Postscript 名称(name ID 6) 唯一地描述某一单独字形。 例如, Gill Sans 家族的粗体字形 的 fullname 是 "Gill Sans Bold", 而 Postscript 名称是 "GillSans-Bold"。 给定字形可以有多个本地化的 fullname 版本, 但 Postscript 名称始终是由有限集合的 ASCII 字符构成的唯一名称。

在各个平台上, 用于搜索字体的名称各不相同。 例如, 在 Windows 的 GDI CreateIndirectFont API 中, 可使用家族名或 fullname 来查找字形, 而在 Mac OS X 中则使用 CTFontCreateWithName API 调用 通过 fullname 和 Postscript 名称来查找某一字形。 在 Linux 下, fontconfig API 允许使用上述任一名称来搜索字体。 在平台 API 自动替换其他字体选择的情形下, 可能需要验证返回的字体是否与给定名称匹配。

某一字形的字重可以通过 OS/2 表的 usWeightClass 字段确定, 或从样式名称(name ID 2)中推断。 同样,宽度可通过 OS/2 表的 usWidthClass 确定, 或从样式名称推断。 出于与 Windows GDI API 在权重 200 或更低时合成加粗的历史原因, 字体设计师有时会调整 OS/2 表中的值以避免这些权重。

渲染使用上下文成形(contextual shaping)的复杂书写系统, 例如泰语(Thai)、 阿拉伯语(Arabic) 和天城文(Devanagari), 需要仅在 OpenType 或 AAT 字体中存在的特性。 目前, 在 Windows 与 Linux 上对复杂书写系统的渲染 通过 OpenType 字体特性来支持, 而在 Mac OS X 上则同时使用 OpenType 与 AAT 字体特性。

14. 安全性考虑

请参阅下方自我评审问卷中的 91617 项目。

15. 隐私性考虑

根据自我评审问卷:安全与隐私,并结合 第 10 节 字体分类

15.1. 该功能可能会向网站或其他方暴露哪些信息,以及该暴露的目的是什么?

该规范允许使用 Web 字体,这些字体按需请求,但未安装。如果文档或样式表与 Web 字体的来源不同,此网络请求会暴露 Referer 头中的信息,这些信息可能会被字体提供者获取。

除了 Web 字体之外,该规范还继续允许使用自 CSS1 引入的安装字体(包括预安装字体和用户安装字体)。

虽然 Web 字体具有跨平台一致性的优势,但安装字体具有零下载时间的优势。

在某些情况下,尤其是对于支持较差或少数语言,安装字体允许显示信息,这在没有自由许可的 Web 字体支持该语言的情况下无法显示,或者由于延迟或下载时间过长,使用变得不可行,尤其是对于字符库较大的语言,或在较慢或计量连接上。

注意:字体匹配算法中可用的安装字体集合明确未定义。可用的字体集合 已被追踪者用来对用户进行指纹识别,进而降低他们的隐私性。然而,一些安装字体,甚至是用户安装字体,是为了使语言可读而必须的。用户代理可以选择为了语言支持和设计完整性原因使所有安装字体可用,或者为了隐私原因使部分字体不可用。此外,用户代理可能具有额外的功能来微调这种平衡,例如提供接口提示用户明确选择是否使某些请求的字体可用或不可用(可能是按站点设置)。即使在相同操作系统上运行的不同用户代理,也可能在此处平衡不同。

对于执行本地资源渲染的用户代理(例如 HTML 和 CSS 转换为 PDF 的渲染器,或基于 Web 的文字处理器),访问所有安装字体(包括预安装字体和用户安装字体)是提供预期功能的必要条件。

攻击者可以通过查询安装字体获取指纹信息。与旧技术(尤其是 Adobe Flash,它提供了安装字体的完整列表并将此信息发送到 HTTP 头中)相比,此类探测必须逐一进行字体检查,提供字体族名称,然后检查(通过脚本,或使用 unicode-range 有选择地下载 Web 字体,具体取决于用户是否具有支持某个字符的某个字体),字体是否加载。这需要时间,检查几百个以上的字体会引入页面渲染中的明显延迟。

对于特别隐私敏感的环境,选项包括永不下载任何 Web 字体(这会有一些字符可能被错误渲染,甚至无法渲染的风险),或者总是下载所有 Web 字体,无论是否需要(忽略 unicode-range,且可能每次查看页面时都会下载大量未使用的字体)。

15.2. 该规范是否只暴露了实现该功能所需的最少信息?

目前的共识是用户代理必须暴露预安装字体以确保功能的正常运行,但对于是否暴露用户安装字体尚无定论。该规范允许用户代理在字体匹配算法中忽略用户安装字体。一些现有的用户代理已经这样做了。

根据用户类型,最少暴露的信息量有所不同,这目前正在讨论中。这里有一个用户安装字体用户分类,该分类已经被略微扩展

暴露更多信息可能会带来更多指纹识别的风险;而减少信息暴露则降低了指纹识别风险,但同时也减少了功能性,某些情况下可能会对少数语言用户的网络体验造成严重影响。

目前正在讨论是否可能实现一种用户配置选项,允许用户选择是否暴露部分或全部用户安装字体,或者按来源选择性暴露。

此外,也在讨论一种隐私预算的可能性,即惩罚或禁用恶意网页对大量字体的测试,但允许对少量字体测试的无害网页继续运行。

一些用户代理在其隐私浏览、无痕模式或抵制指纹识别模式下,会暴露比正常模式更少的预安装字体集合。

15.3. 该规范如何处理个人信息或可识别个人身份的信息或由此衍生的信息?

该规范不暴露个人信息。

某些情况下,可能会暴露可识别个人身份的信息。例如,对于日本的用户,列举条件启用的日文字体可能不会构成重要的指纹识别向量,但对于在欧洲有日文输入法的用户而言,则可能构成。

15.4. 该规范如何处理敏感信息?

在某些情况下,通过安装字体进行指纹识别可能会暴露敏感信息。例如,受迫害的少数群体可能会通过暴露他们使用的特定语言字体而泄露敏感信息;这可能是通过向第三方服务请求 Web 字体或暴露与该语言相关的预安装字体或用户安装字体实现的。

15.5. 该规范是否引入了跨浏览会话持续存在的来源新状态?

没有。

具体来说,Web 字体必须无法被关联 @font-face 规则的文档之外的任何其他文档访问。同样,字体调色板值仅能供引用它们的文档使用,否则可能会导致安全泄露。

15.6. 该规范向来源暴露了哪些来自底层平台的信息,如配置数据?

system-ui关键字暴露了操作系统的默认系统 UI 字体,这可能会被指纹识别机制利用。

15.7. 该规范是否允许来源访问用户设备上的传感器?

没有。

15.8. 该规范暴露了哪些数据给来源?请说明哪些数据与其他功能暴露的数据相同,无论是在相同还是不同的上下文中。

对于通过样式表加载的第三方 Web 字体,样式表来源可能会通过 Referer 头暴露给第三方。此外,仔细配对 unicode-range 和不同的 src URL,允许第三方看到页面上使用了哪些字符,这对大字符库语言(如 CJK)构成了隐私风险。

对于预加载到 HTML 的第三方 Web 字体,文档来源也可能会被类似地暴露。

15.9. 该规范是否启用了新的脚本执行/加载机制?

没有。

具体来说,对于包含在 OpenType 彩色字体中的 SVG,用于字形定义的 SVG 不应包含 script 元素,且任何出现的 script 元素都不会执行。

15.10. 该规范是否允许来源访问其他设备?

没有。

15.11. 该规范是否允许来源在一定程度上控制用户代理的原生 UI?

攻击者可能会通过确定操作系统并使用与该操作系统相符的本地字体来伪装原生 UI 功能。

15.12. 该规范可能会创建或暴露哪些临时标识符给网络?

无。

15.13. 该规范如何区分第一方和第三方上下文中的行为?

对于字体加载,用户代理必须使用 @font-face 规则内定义的 URL,遵循[HTML]规范定义的 CORS 可用的抓取方法。

15.14. 该规范在用户代理的隐私浏览或“无痕模式”下如何工作?

该规范未做区分。

一些用户代理在这些模式下可能会暴露更少的安装字体。

15.15. 该规范是否包含“安全性考虑”和“隐私性考虑”部分?

是的。

15.16. 该规范是否允许降低默认的安全特性?

没有。

15.17. 该问卷还应当询问什么问题?

它应该询问是否存在恶意负载可能导致应用崩溃,甚至整个操作系统崩溃,或者导致远程代码执行的可能性。

某些情况下,这种可能性确实存在,尤其是针对某些平台,当安装和渲染精心构造的字体时,这一漏洞已被实际利用。

在实际中,运行于具有此类漏洞操作系统上的用户代理会使用字体消毒器检测这些恶意字体并阻止其被使用。

16. 无障碍考虑

使用字体来提供文本的视觉渲染通常不会影响无障碍性。例如,使用屏幕阅读器将文本转换为语音的人不会下载字体,因此不会受到这些字体内容的影响。

然而,这假设字体字形传达的语义与字符传达的语义是一致的。

历史上,这种情况并不总是如此。例如,在早期的 Web 中,常常使用字体(例如“Symbol”字体,尽管其他字体也被使用)使拉丁字母具有希腊字形;虽然这种做法在视觉上有效,但它对屏幕阅读器不起作用,且由于这种映射是特定于字体的,文本也难以搜索或索引。随着 Unicode 的兴起,现在的标准做法是使用希腊字符表示希腊文本,并将字体中的希腊字形映射到希腊字符。

遗憾的是,这种做法仍然存在于设计不良的图标字体中。例如,这种字体可能将“打印机”图标放在拉丁字母“P”上。这种做法会在文本中散布无意义的字母,影响文本搜索和索引,并且如果图标字体未加载,渲染将难以理解,还会妨碍屏幕阅读器的使用。设计良好的字体应将此类图标分配给具有语义意义的字符。例如,可以将打印机图标分配给字符串“printer”或 Unicode 字符 🖨 U+1F5A8(PRINTER)。

17. 致谢

CSS 工作组感谢以下人员:

Peter Constable 对多语言问题的修正。

Nick Sherman 准备了光学尺寸示例图像。

Richard Ishida 准备了乌尔都语样本。

Munira Tursunova 和 Dominik Röttsches 开发了动画字体调色板功能。

John Hudson 详细解释了 OpenType 语言标签的细微差别,并提供了用于显示拜占庭印章文本的字符变体示例。

Elika Etemad 提供了“@font-feature-values”规则的一些初始设计理念。

特别感谢 Tab Atkins Jr. 提供了字体渲染控制部分的文本,以及font-display描述符部分的文本。特别感谢 Ilya Grigorik 和 David Kuettel 帮助开发了这些部分。

18. 变更

18.1. 2024 年 2 月 1 日工作草案 的更改

18.2. 2021年12月21日工作草案的变更

18.3. 2021年7月29日工作草案的变更

18.4. 2020年11月17日工作草案的变更

18.5. 2019年11月13日工作草案的变更

18.6. 2018年9月20日工作草案的变更

18.7. 2018年4月10日工作草案的变更

18.8. CSS Fonts 3 推荐规范与2018年9月20日的变更

本节总结了 CSS Fonts 4 与 CSS Fonts 3 的变更。

一致性

文档惯例

一致性要求通过描述性断言和 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"> 与其他规范文本区分开,如下所示:用户代理(UAs)必须提供可访问的替代方案。

测试

与本规范内容相关的测试可能会记录在像这样的“测试”块中。任何此类块都是非规范性的。


一致性类别

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

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

样式表符合本规范的要求,如果其使用本模块定义的语法的所有语句根据通用 CSS 语法和本模块定义的每个功能的单独语法都是有效的。

渲染器符合本规范的要求,如果它除了按适当的规范定义解释样式表外,还正确解析本规范定义的所有功能,并相应地渲染文档。然而,由于设备限制,UA 无法正确渲染文档并不使其不符合规范。(例如,UA 不需要在单色显示器上渲染颜色。)

创作工具符合本规范的要求,如果它编写的样式表根据通用 CSS 语法和本模块中每个功能的单独语法是语法正确的,并且满足本模块中描述的样式表的所有其他一致性要求。

部分实现

为了使作者能够利用向前兼容的解析规则来分配回退值,CSS 渲染器必须将任何它们没有可用支持级别的 at-rules、属性、属性值、关键字和其他语法结构视为无效(并适当地忽略)。特别是,用户代理不得选择性地忽略不支持的组件值并在单个多值属性声明中接受支持的值:如果任何值被视为无效(因为不支持的值必须是无效的),CSS 要求整个声明被忽略。

不稳定和专有功能的实现

为了避免与未来稳定的 CSS 功能发生冲突,CSS 工作组建议遵循最佳实践来实现不稳定的功能和专有扩展

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现就有可能进行,实现者应发布任何 CR 级别功能的非前缀实现,只要他们能够证明根据规范正确实现了这些功能。

为了建立和维护跨实现的 CSS 互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布任何 CSS 功能的非前缀实现之前,向 W3C 提交实现报告(如果有必要,还需提交用于该实现报告的测试用例)。提交给 W3C 的测试用例将由 CSS 工作组进行审查和修正。

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

索引

本规范定义的术语

引用中定义的术语

参考文献

规范性参考文献

[AAT-FEATURES]
Apple Advanced Typography 字体特性注册表. URL: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 级联与继承 第5级. 13 January 2022. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS 颜色模块 第4级. 27 February 2026. CRD. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; Una Kravets; Lea Verou. CSS 颜色模块 第5级. 27 February 2026. WD. URL: https://www.w3.org/TR/css-color-5/
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al. CSS 颜色调整模块 第1级. 16 December 2025. CR. URL: https://www.w3.org/TR/css-color-adjust-1/
[CSS-ENV-1]
CSS 环境变量模块 第1级. 23 September 2025. FPWD. URL: https://www.w3.org/TR/css-env-1/
[CSS-INLINE-3]
Elika Etemad. CSS 行内布局模块 第3级. 18 December 2024. WD. URL: https://www.w3.org/TR/css-inline-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS 语法模块 第3级. 24 December 2021. CRD. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-TEXT-4]
Elika Etemad; et al. CSS 文本模块 第4级. 29 May 2024. WD. URL: https://www.w3.org/TR/css-text-4/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块 第3级. 22 March 2024. CRD. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块 第4级. 12 March 2024. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VARIABLES-1]
Tab Atkins Jr.. 级联变量的 CSS 自定义属性 模块 第1级. 16 June 2022. CR. URL: https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS 书写模式 第4级. 30 July 2019. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS2]
Bert Bos; et al. 层叠样式表 第2版 修订版1(CSS 2.1)规范. 7 June 2011. REC. URL: https://www.w3.org/TR/CSS2/
[CSS3TEXT]
Elika Etemad; Koji Ishii; Florian Rivoal. CSS 文本模块 第3级. 30 September 2024. CRD. URL: https://www.w3.org/TR/css-text-3/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型(CSSOM). 26 August 2021. WD. URL: https://www.w3.org/TR/cssom-1/
[FETCH]
Anne van Kesteren. Fetch 标准. Living Standard. URL: https://fetch.spec.whatwg.org/
[GRAPHITE]
Graphite 技术概览. 2012. URL: https://graphite.sil.org/graphite_techAbout.html
[HTML]
Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[I18N-GLOSSARY]
Richard Ishida; Addison Phillips. 国际化术语表. 17 October 2024. NOTE. URL: https://www.w3.org/TR/i18n-glossary/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. Living Standard. URL: https://infra.spec.whatwg.org/
[OPENTYPE]
OpenType 规范. URL: http://www.microsoft.com/typography/otspec/default.htm
[OPENTYPE-FEATURES]
OpenType 特性注册表. URL: http://www.microsoft.com/typography/otspec/featurelist.htm
[RFC2119]
S. Bradner. RFC 中用于表示要求级别的关键词. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC8081]
C. Lilley. “font” 顶级媒体类型. February 2017. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8081
[UNICODE]
Unicode 标准. URL: https://www.unicode.org/versions/latest/
[UTS51]
Mark Davis; Ned Holbrook. Unicode Emoji. 4 September 2025. Unicode Technical Standard #51. URL: https://www.unicode.org/reports/tr51/tr51-29.html
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/

参考性参考文献

[CHARMOD-NORM]
Addison Phillips; et al. 万维网字符模型:字符串匹配. 11 August 2021. NOTE. URL: https://www.w3.org/TR/charmod-norm/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS 显示模块 第4级. 6 November 2025. WD. URL: https://www.w3.org/TR/css-display-4/
[CSS-FONT-LOADING-3]
Tab Atkins Jr.. CSS 字体加载模块 第3级. 6 April 2023. WD. URL: https://www.w3.org/TR/css-font-loading-3/
[CSS-FONTS-3]
John Daggett; Myles Maxfield; Chris Lilley. CSS 字体模块 第3级. 20 September 2018. REC. URL: https://www.w3.org/TR/css-fonts-3/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS 溢出模块 第3级. 7 October 2025. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS 变换模块 第1级. 14 February 2019. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSS3-CONDITIONAL]
Chris Lilley; David Baron; Elika Etemad. CSS 条件规则模块 第3级. 15 August 2024. CRD. URL: https://www.w3.org/TR/css-conditional-3/
[IFT]
Chris Lilley; Garret Rieger; Skef Iterum. 增量字体传输. 18 November 2025. CRD. URL: https://www.w3.org/TR/IFT/
[OPEN-FONT-FORMAT]
信息技术 — 音视频对象的编码 — 第22部分:开放字体格式. January 2019. Published. URL: https://www.iso.org/standard/74461.html
[PFE-report]
Chris Lilley. 渐进字体增强:评估报告. 15 October 2020. Note. URL: https://www.w3.org/TR/PFE-evaluation/
[TRUETYPE]
TrueType™ 参考手册. URL: https://developer.apple.com/fonts/TrueType-Reference-Manual/
[UAX29]
Josh Hadley. Unicode 文本分割. 17 August 2025. Unicode Standard Annex #29. URL: https://www.unicode.org/reports/tr29/tr29-47.html
[WINDOWS-GLYPH-PROC]
John Hudson. Windows 字形处理. URL: http://www.microsoft.com/typography/developers/opentype/default.htm

属性索引

名称 取值 初始值 适用于 是否继承 百分比 动­画类型 规范顺序 计算值 媒体
font [ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-width-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'># ] | <system-family-name> 参见各单独属性 所有元素和文本 参见各单独属性 参见各单独属性 按语法 参见各单独属性
font-family [ <family-name> | <generic-family> ]# 由用户代理决定 所有元素和文本 不适用 离散 按语法 列表,每项为字符串和/或 <generic-family> 关键字
font-feature-settings normal | <feature-tag-value># normal 所有元素和文本 不适用 离散 按语法 按指定
font-kerning auto | normal | none auto 所有元素和文本 不适用 离散 按语法 按指定
font-language-override normal | <string> normal 所有元素和文本 N/A 离散 按语法 指定的字符串或关键字 none
font-optical-sizing auto | none auto 所有元素和文本 不适用 离散 按语法 指定的关键字
font-palette normal | light | dark | <palette-identifier> | <palette-mix()> normal 所有元素和文本 N/a 按计算值 按语法 指定的关键字、标识符或 <palette-mix()> 函数。 <palette-mix()> 若结果调色板等价,必须简化为单个关键字或标识符。
font-size <absolute-size> | <relative-size> | <length-percentage [0,∞]> | math medium 所有元素和文本 参照父元素的字体大小 按计算值类型 按语法 一个绝对长度
font-size-adjust none | <number [0,∞]> none 所有元素和文本 N/A 按计算值类型 按语法 一个数值或关键字 none
font-style normal | italic | left | right | oblique <angle [-90deg,90deg]>? normal 所有元素和文本 不适用 按计算值类型;normal 的动画行为为 oblique 0deg 按语法 指定的关键字,如指定角度则附带度数
font-synthesis none | [ weight || style || small-caps || position] weight style small-caps position 所有元素和文本 N/A 离散 按语法 指定的关键字
font-synthesis-position auto | none auto 所有元素和文本 N/A 离散 按语法 指定的关键字
font-synthesis-small-caps auto | none auto 所有元素和文本 N/A 离散 按语法 指定的关键字
font-synthesis-style auto | none | oblique-only auto 所有元素和文本 N/A 离散 按语法 指定的关键字 视觉
font-synthesis-weight auto | none auto 所有元素和文本 N/A 离散 按语法 指定的关键字 视觉
font-variant normal | none | [ [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ] || [ small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps ] || [ stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name>#) || character-variant(<feature-value-name>#) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) ] || [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ] || [ <east-asian-variant-values> || <east-asian-width-values> || ruby ] || [ sub | super ] || [ text | emoji | unicode ] ] normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-alternates normal | [ stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name>#) || character-variant(<feature-value-name>#) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) ] normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-caps normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-east-asian normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ] normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-emoji normal | text | emoji | unicode normal 所有元素和文本 N/a 离散 按语法 指定的关键字
font-variant-ligatures normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ] normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-numeric normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ] normal 所有元素和文本 不适用 离散 按语法 按指定
font-variant-position normal | sub | super normal 所有元素和文本 不适用 离散 按语法 按指定
font-variation-settings normal | [ <opentype-tag> <number> ]# normal 所有元素和文本 不适用 见正文 按语法 关键字 normal 或 列表,每项为字符串与数字配对
font-weight <font-weight-absolute> | bolder | lighter normal 所有元素和文本 不适用 按计算值类型 按语法 一个数值,见下文
font-width normal | <percentage [0,∞]> | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded normal 所有元素和文本 未解析 按计算值类型 按语法 一个百分比,见下文

@font-face 描述符

名称 取值 初始值
ascent-override normal | <percentage [0,∞]> normal
descent-override normal | <percentage [0,∞]> normal
font-display auto | block | swap | fallback | optional auto
font-family <family-name> N/A
font-feature-settings normal | <feature-tag-value># normal
font-language-override normal | <string> normal
font-named-instance auto | <string> auto
font-style auto | normal | italic | left | right | oblique [ <angle [-90deg,90deg]>{1,2} ]? auto
font-variation-settings normal | [ <string> <number>]# normal
font-weight auto | <font-weight-absolute>{1,2} auto
font-width auto | <'font-width'>{1,2} auto
line-gap-override normal | <percentage [0,∞]> normal
src <font-src-list> N/A
unicode-range <unicode-range-token># U+0-10FFFF

@font-feature-values 描述符

名称 初始值
font-display auto | block | swap | fallback | optional auto

@font-palette-values 描述符

名称 初始值
base-palette light | dark | <integer [0,∞]> 不适用
font-family <family-name># 不适用
override-colors [ <integer [0,∞]> <color> ]# 不适用

IDL 索引

[Exposed=Window]
interface CSSFontFaceDescriptors : CSSStyleDeclaration {
  attribute [LegacyNullToEmptyString] CSSOMString src;
  attribute [LegacyNullToEmptyString] CSSOMString fontFamily;
  attribute [LegacyNullToEmptyString] CSSOMString font-family;
  attribute [LegacyNullToEmptyString] CSSOMString fontStyle;
  attribute [LegacyNullToEmptyString] CSSOMString font-style;
  attribute [LegacyNullToEmptyString] CSSOMString fontWeight;
  attribute [LegacyNullToEmptyString] CSSOMString font-weight;
  attribute [LegacyNullToEmptyString] CSSOMString fontStretch;
  attribute [LegacyNullToEmptyString] CSSOMString font-stretch;
  attribute [LegacyNullToEmptyString] CSSOMString fontWidth;
  attribute [LegacyNullToEmptyString] CSSOMString font-width;
  attribute [LegacyNullToEmptyString] CSSOMString unicodeRange;
  attribute [LegacyNullToEmptyString] CSSOMString unicode-range;
  attribute [LegacyNullToEmptyString] CSSOMString fontFeatureSettings;
  attribute [LegacyNullToEmptyString] CSSOMString font-feature-settings;
  attribute [LegacyNullToEmptyString] CSSOMString fontVariationSettings;
  attribute [LegacyNullToEmptyString] CSSOMString font-variation-settings;
  attribute [LegacyNullToEmptyString] CSSOMString fontNamedInstance;
  attribute [LegacyNullToEmptyString] CSSOMString font-named-instance;
  attribute [LegacyNullToEmptyString] CSSOMString fontDisplay;
  attribute [LegacyNullToEmptyString] CSSOMString font-display;
  attribute [LegacyNullToEmptyString] CSSOMString fontLanguageOverride;
  attribute [LegacyNullToEmptyString] CSSOMString font-language-override;
  attribute [LegacyNullToEmptyString] CSSOMString ascentOverride;
  attribute [LegacyNullToEmptyString] CSSOMString ascent-override;
  attribute [LegacyNullToEmptyString] CSSOMString descentOverride;
  attribute [LegacyNullToEmptyString] CSSOMString descent-override;
  attribute [LegacyNullToEmptyString] CSSOMString lineGapOverride;
  attribute [LegacyNullToEmptyString] CSSOMString line-gap-override;
};

[Exposed=Window]
interface CSSFontFaceRule : CSSRule {
  [SameObject, PutForwards=cssText] readonly attribute CSSFontFaceDescriptors style;
};

partial interface CSSRule {  const unsigned short FONT_FEATURE_VALUES_RULE = 14;
};
[Exposed=Window]
interface CSSFontFeatureValuesRule : CSSRule {
  attribute CSSOMString fontFamily;
  readonly attribute CSSFontFeatureValuesMap annotation;
  readonly attribute CSSFontFeatureValuesMap ornaments;
  readonly attribute CSSFontFeatureValuesMap stylistic;
  readonly attribute CSSFontFeatureValuesMap swash;
  readonly attribute CSSFontFeatureValuesMap characterVariant;
  readonly attribute CSSFontFeatureValuesMap styleset;
  readonly attribute CSSFontFeatureValuesMap historicalForms;
};

[Exposed=Window]
interface CSSFontFeatureValuesMap {
  maplike<CSSOMString, sequence<unsigned long>>;
  undefined set(CSSOMString featureValueName,
    (unsigned long or sequence<unsigned long>) values);
};

[Exposed=Window]interface CSSFontPaletteValuesRule : CSSRule {
  readonly attribute CSSOMString name;
  readonly attribute CSSOMString fontFamily;
  readonly attribute CSSOMString basePalette;
  readonly attribute CSSOMString overrideColors;
};

问题索引

正斜体和负斜体在垂直书写模式下应朝哪个方向倾斜?我们如何在另一维度实现倾斜 (垂直书写模式需要)?
fallbackoptional 可能会导致同一个字体家族中的一些字形被使用, 而另一些则需要回退,这会导致字体看起来像“赎金条”。或许要求同一个家族的所有字体表现一致(要么都替换,要么都回退)? 另请参阅 @font-feature-values 控制字体家族的行为。
stream 中根据字体类型加载字体。
选择倾向于使用斜体而非普通字体的阈值 应低于平均角度
添加更多示例和图片。