CSS 字体模块第 4 级

W3C 工作草案,

更多关于此文档的详细信息
此版本:
https://www.w3.org/TR/2026/WD-css-fonts-4-20260913/
最新发布版本:
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 属性定义惯例 (见 [CSS2]), 并使用 值定义语法 (来自 [CSS-VALUES-3])。 未在本规范中定义的值类型,可在 CSS Values & Units [CSS-VALUES-3] 中找到。 与其他 CSS 模块的组合,可能扩展这些值类型的定义。

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

1.2. 与字体相对单位的交互

本规范中定义的以下属性是影响字体的属性

注: 一些能够影响文本大小的属性 并不是影响字体的属性, 因为它们是通过字体塑形来实现这种影响的, 而字体相对长度明确不会将其考虑在内。

2. 基本字体属性

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

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

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

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

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

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

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

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

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

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

<generic-font-family>
每个 <generic-font-family> 关键字表示一种通用字体选项, 并作为某个指定字体通用类别下的一个或多个本地已安装字体的潜在别名。 <generic-font-family> 可作为 作者更具体字体选择不可用时的降级方案。

通用字体族有三种类型:

  1. 作用于所有 Unicode 字符、且总会匹配本地已安装字体的通用项。 例如 monospace

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

  3. 特定于某类书写系统,仅作用于部分 Unicode 字符,且在部分系统上可能无法匹配本地字体的通用项。 例如 generic(fangsong)

建议作者在字体列表结尾加上一个通用字体,以增强健壮性;如有可能,也建议优先用更具体的通用字体家族,从而即使未命中某个具体字体,仍能维持想要的字体风格。

注意 <generic-font-family> 关键字不能加引号(否则会被当作 <font-family-name> 处理)。

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

<system-font-family-name>
本地已安装的系统字体,其使用受到一定限制。 特别地,它不能用于 font-family 属性, 但可用于 font 简写属性。

以下是系统字体取值:

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

2.1.1. <font-family-name> 的语法

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

除通用字体族或系统字体族外, 字体家族名称必须要么以 <string> 形式加引号给出, 要么以一个或多个 <custom-ident> 不加引号的序列给出。

注: 这意味着在不加引号的字体家族名中,大多数标点符号和以数字开头的字符必须转义。

举例来说,下面这些声明是无效的:
font-family: Red/Black, sans-serif;
font-family: "Lucida" Grande, sans-serif;
font-family: Ahem!, sans-serif;
font-family: test@foo, sans-serif;
font-family: #POUND, sans-serif;
font-family: Hawaii 5-0, sans-serif;

任何有可能被误解为 font-family 值定义中的预定义关键字, 或 CSS 全局关键字 的标识符,都是不允许的。

注: 这意味着如果确实有字体名 与 <generic-font-family> 名称、 系统字体名,或 CSS 全局关键字 相同,则必须加引号。

举例来说,下面这些特殊的字体家族名因加了引号,是合法的:
font-family: "sans-serif", sans-serif;
font-family: "default", sans-serif;
font-family: "initial", sans-serif;
font-family: "inherit", sans-serif;

如果 <font-family-name> 给出的是标识符序列, 其计算值为: 先将该序列所有标识符用单空格连接,转换为字符串后作为名称。

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

给字体家族加引号可以避免转义错误。
body { font-family: "New Century Schoolbook", serif }
<body style="font-family: '21st Century', fantasy">

font-family 关键字值 (如 CSS 全局关键字 inherit,或 <generic-font-family> 关键字如 serif)同名的字体 名称,必须加引号以防混淆。 用户代理不得将这些关键字视为匹配 <font-family-name> 类型。

2.1.2. <generic-font-family> 的语法

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

为减少语法冲突,较新的通用字体族使用函数式语法进行标识。

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

本例第一个选项是特定命名的仿宋体(Fang Song)风格字体,家族名因含有空格需加引号。 第二项是新近添加的脚本专用通用字体(unicode 范围特定), 其在某些系统上可能无法匹配实际已安装字体,但若存在,则能满足所需风格。 第三项为通用字体,保证所有系统都有匹配。

2.1.3. <system-font-family-name> 的语法

<system-font-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

注:通用字体族旨在在许多平台上广泛实现, 不同于任意的 <font-family-name>,后者通常是特定平台的名称。 预期它们会在不同平台上映射到不同的字体。若作者希望其文本在许多平台上遵循某种特定设计, 且并不特别在意这些平台上最终选择了哪一种具体字体, 则可以指定这些通用字体族名称。

用户代理应为通用字体族提供合理的默认选择, 在底层技术允许的限制内, 尽可能体现各个字体族的特征。 鼓励用户代理允许用户为通用字体族选择替代字面。

serif
衬线字体代表 具有收笔笔画的字形, 末端呈外扩或渐细, 或具有真正的衬线式收尾(包括 slab serif)。 衬线字体通常为比例间距。 与 sans-serif 通用字体族中的字体相比, 它们的粗细笔画变化往往更大。

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

CSS 使用术语 “serif” 指代任意书写系统的某类字体, 尽管对特定书写系统而言,其他名称可能更为熟悉, 例如 Mincho(日文)、 Sung 或 Song(中文)、 Batang(韩文)。 对于阿拉伯文,Naskh 风格对应于 serif

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

注:对该字体字面的字符覆盖范围不作保证。 因此,serif 所映射到的字体 最终可能不会用于所有内容。

sample serif fonts
衬线字体示例
sans-serif
无衬线字体中的字形, 按 CSS 中该术语的用法, 通常对比度较低 (垂直与水平笔干的粗细接近相同), 且笔画末端较为朴素 (没有外扩、横画收笔或其他装饰)。 无衬线字体通常为比例间距。 与 serif 家族中的字体相比, 它们的粗细笔画变化往往较小。 CSS 使用术语 “sans-serif” 指代任意书写系统的某类字体, 尽管对特定书写系统而言,其他名称可能更为熟悉, 例如 Gothic(日文)、 Hei(中文)、 或 Gulim(韩文)。

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

注:对该字体字面的字符覆盖范围不作保证。 因此,sans-serif 所映射到的字体最终可能不会用于所有内容。

sample sans-serif fonts
无衬线字体示例
cursive
草写字体中的字形通常采用手写体风格, 效果看起来更像手写的钢笔字或毛笔字,而不是印刷体字形。 CSS 使用术语 “cursive” 指代任意书写系统的某类字体, 尽管在字体名称中也常用 Chancery、Brush、Swing 和 Script 等其他名称。
sample cursive fonts
草写字体示例
fantasy
Fantasy 字体主要是装饰性或表现性字体, 其中包含对字符的装饰性或表现性呈现。 这不包括不表示实际字符的 Pi 字体或图画字体。
sample fantasy fonts
Fantasy 字体示例
monospace
等宽字体的唯一标准是所有字形具有相同的固定宽度。 这常用于渲染计算机代码示例。

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

注:对该字体字面的字符覆盖范围不作保证。 因此,monospace 所映射到的字体最终可能不会用于所有内容。

sample monospace fonts
等宽字体示例
system-ui
该通用字体族使文本使用默认的用户界面字体进行渲染 (与所有 § 2.1.5 通用字体族 一样,它也可能是复合字体), 字体来自 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” 的结果。

注: system-ui 高度依赖平台环境,因为多种因素可能 影响默认用户界面字体,并且其文本渲染支持程度可能各不相同。 这可能导致所显示的字体对于某些最终用户而言并不理想 (例如,简体中文用户在较旧版本的 Windows 上可能会看到等宽衬线字体; 在某些情况下,lang 属性可能不会影响所显示的字体,例如在俄语区域设置中使用 lang="uk" 或在中文区域设置中使用 lang="ja")。 某些操作系统供应商不提供自定义 system-ui 的方式, 不同于通常允许用户自定义通用 sans-serifserif 字体族的 UA。 顾名思义,system-ui 旨在用于 Web 应用程序中的 UI 元素, 而对于大段文本 或文章是否合适,则取决于操作系统供应商的实现。

math
此字体族旨在用于数学表达式。

此类字体可能包含额外数据 (例如 OpenType MATH 表), 以协助方程排版的层级化处理过程。 特别地,它们可能包含对设置数学公式有用的 风格化与可拉伸的字形变体。

generic(fangsong)
此字体族用于中文的仿宋(Fang Song)字形。 仿宋是一种较为舒展的中间形态, 介于宋体(serif)与楷体(generic(kai))之间。 通常,与宋体风格相比, 水平线略带倾斜, 末端装饰更小, 且笔画宽度变化更小。 仿宋常用于中国政府的公文。

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

使用示例仿宋字体显示的中文文本
generic(kai)
此字体族用于简体与繁体中文。 这是一种重要的字体,能为中文文本提供书法风格。 它具有明显的手写特征。 楷体常用于公文与教科书。 台湾的大多数公文会通篇使用楷体。 楷体也可以与其他字体组合使用, 用于需要与其余内容区分的文本, 例如标题、参考文献、引文以及对话。

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

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

尽管视觉上更“粗重”, generic(khmer-mul) 中用于正文的字重仍保持不变(400)。

注: 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 风格。

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

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

注:在缺乏合适系统字体的平台上, 不期望 ui-serif 能映射到任何字体。

注:潜在问题参见 system-ui 的注释。

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

注:在缺乏合适系统字体的平台上, 不期望 ui-sans-serif 能映射到任何字体。

注:潜在问题参见 system-ui 的注释。

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

注:在缺乏合适系统字体的平台上, 不期望 ui-monospace 能映射到任何字体。

注:潜在问题参见 system-ui 的注释。

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

注:在缺乏合适系统字体的平台上, 不期望 ui-rounded 能映射到任何字体。

注:潜在问题参见 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 的使用值。

注: 在 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-font-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 第 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 属性 因而不能进行设置, 而是会重置为其初始值:

独立层叠

这些属性 (尽管属性名以 "font-" 开头) 并不是 长写属性, 不属于 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-style, font-width, font-size, 以及 font-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;   /* 适用于较旧的用户代理 */
  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 磅的 Charcoal, 粗细为 600, 那么作为 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

此 @ 规则遵循 CSS 的前向兼容解析规则。 与声明块中的属性一样, 用户代理不支持的任何描述符的声明 都必须忽略。 @font-face 规则需要 font-familysrc 描述符; 如果其中任一描述符缺失, 则执行 字体匹配算法 时 不得考虑该 @font-face 规则。

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

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

名称: font-family
用于: @font-face
值: <font-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( <font-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() 的本地已安装 <font-family-name> 参数 是一个格式相关的字符串, 用于在更大的字族中唯一标识某个字体字面。 名称可以选择加引号包裹。 如果未加引号, 遵循未加引号字体家族名处理惯例; 换句话说, 此名称必须是由空白字符分隔的标识符序列, 计算时用单个空格连接所有标识符, 转换为字符串; 因此, CSS 全局关键字inherit, 以及 <generic-font-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 描述符取值定义的字体会被加载:

/* 同源(即 domain、scheme、port 与文档一致)*/
    src: url(fonts/simple.woff);

    /* data url、无重定向,视为同源 */
    src: url("data:application/font-woff;base64,...");

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

使用下述src 描述符值定义的字体将无法加载:

/* 跨域,不同协议 */
    /* 响应中无 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%",则搜索算法可以 如下可视化:

      算法

      上图显示了字体 A、B 和 C 支持的字体宽度范围。可以 看出,因为字体 B 包含整个字体族中的最小宽度值,所以该算法会选择字体 B。但是,如果字体 B 因某种原因从 字体族中被排除,那么字体 C 将包含字体族中的最小距离,因此会 被选中。

      上一个示例类似,下面是样式为 "font-width: 75%" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 B 包含整个字体族中的最小宽度值, 所以该算法会选择字体 B。但是,如果字体 B 因某种原因从 字体族中被排除,那么字体 A 将包含字体族中的最小距离,因此会 被选中。

    2. 接下来尝试 font-style (参见 § 5.2 匹配字体样式)。 如果字体不具有任何斜体程度或倾斜角度强弱变化的概念,则其 样式 按照 font-style 属性定义中的说明进行映射。

      如果 font-style 的值为 italic

      1. 如果匹配集合中包含斜体值涵盖 italic 映射值的字体, 则斜体值不包含所需斜体映射值的字体 将从匹配集合中移除。

      2. 否则,首先按升序检查高于所需斜体值的斜体值, 然后检查低于所需斜体值的斜体值,直到达到 0。此阶段仅检查 正的斜体值。

      3. 对于具有 ital 轴的可变字体, 通过将 ital 值设置为 1 来创建匹配项。

      4. 如果未找到匹配项,则首先按升序检查大于或等于 11deg 的倾斜值, 然后按降序检查低于 11deg 的倾斜值,直到达到 0。此阶段仅 检查正的倾斜值。

        对倾斜体优先于常规体的阈值应低于平均角度

      5. 如果未找到匹配项,则按降序检查小于或等于 0 的斜体值, 直到找到匹配项。

      6. 如果未找到匹配项,则按降序检查小于或等于 0deg 的倾斜值, 直到找到匹配项。

        上一个示例类似,下面是 样式为 "font-style: italic" 的元素的概念性距离图:

        距离图

        可以看出,因为字体 D 包含整个 字体族中的最小斜体值,所以该算法会选择字体 D。但是,如果字体 D 因某种原因从字体族中被排除,那么字体 E 将包含字体族中的最小 距离,因此会被选中。如果 E 被排除,则会选择 C。如果 C 被 排除,则不会立即选择字体 B; 而是会考察倾斜值,并且可能选择某个倾斜值。 但是,如果未选择任何倾斜值,则随后会选择字体 B,接着是 字体 A。

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

      1. 如果匹配集合中包含倾斜值涵盖 oblique 值的字体, 则倾斜值不包含所需倾斜值的字体将从 匹配集合中移除。

      2. 否则,首先按升序检查高于所需倾斜值的倾斜值, 然后检查低于所需倾斜值的倾斜值,直到达到 0。此阶段仅检查 正的倾斜值。

      3. 对于具有 slnt 轴的可变字体, 通过将 slnt 值 设置为指定的倾斜值来创建匹配项。 否则,如果 font-synthesis-style 的 值为 auto, 则通过几何剪切到指定的倾斜值 生成一个后备匹配项。 ital 轴不用于满足 oblique 请求。

      4. 如果未找到匹配项,则首先按升序检查大于或等于 1 的斜体值, 然后按降序检查低于 1 的斜体值,直到达到 0。此阶段仅检查正的 斜体值。

      5. 如果未找到匹配项,则按降序检查小于或等于 0deg 的倾斜值, 直到找到匹配项。

      6. 如果未找到匹配项,则按降序检查小于或等于 0 的斜体值, 直到找到匹配项。

        上一个示例类似,下面是 样式为 "font-style: oblique 40deg" 的元素的概念性距离图:

        距离图

        可以看出,因为字体 D 包含整个 字体族中的最小倾斜值,所以该算法会选择字体 D。但是,如果字体 D 因某种原因从字体族中被排除,那么字体 E 将包含字体族中的最小 距离,因此会被选中。如果 E 被排除,则会选择 C。如果 C 被 排除,则不会立即选择字体 B; 而是会考察斜体值,并且可能选择某个斜体值。 但是,如果未选择任何斜体值,则随后会选择字体 B,接着是 字体 A。

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

      1. 如果匹配集合中包含倾斜值涵盖 oblique 值的字体, 则倾斜值不包含所需倾斜值的字体将从匹配 集合中移除。

      2. 否则,首先按降序检查低于所需倾斜值的倾斜值, 直到达到 0,然后检查 高于所需倾斜值的倾斜值。此阶段仅检查正的倾斜 值。

      3. 对于具有 slnt 轴的可变字体, 通过将 slnt 值 设置为指定的倾斜值来创建匹配项。 否则,如果 font-synthesis-style 的 值为 auto, 则通过几何剪切到指定的倾斜值 生成一个后备匹配项。 ital 轴不用于满足 oblique 请求。

      4. 如果未找到匹配项,则按降序检查小于 1 的斜体值,直到 达到 0, 然后按升序检查高于 1 的斜体值。此阶段仅检查正的斜体 值。

      5. 如果未找到匹配项,则按降序检查小于或等于 0deg 的倾斜值, 直到找到匹配项。

      6. 如果未找到匹配项,则按降序检查小于或等于 0 的斜体值, 直到找到匹配项。

      上一个示例类似,下面是样式为 "font-style: oblique 13deg" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 D 包含整个 字体族中的最小倾斜值,所以该算法会选择字体 D。但是,如果字体 D 因某种原因 从字体族中被排除,那么字体 C 将包含字体族中的最小距离, 因此会被选中。如果 C 被排除,则会选择 E。如果 E 被 排除,则不会立即选择字体 B;而是会 考察斜体值,并且可能选择某个斜体值。但是,如果未选择任何斜体值, 则随后会选择字体 B,接着是字体 A。

      如果 font-style 的值为 oblique,并且请求的角度小于 0deg 且大于 -11deg,则按照上述步骤执行, 但使用取反后的值和相反的方向。如果 font-style 的值为 oblique,并且请求的 角度小于或等于 -11deg,则按照上述步骤执行,但使用取反后的值和相反的 方向。

      如果 font-style 的值为 normal

      1. 按升序检查大于或等于 0 的倾斜值。

      2. 如果未找到匹配项,则按升序检查大于或等于 0 的斜体值

      3. 如果未找到匹配项,则按降序检查小于 0deg 的倾斜值, 直到找到匹配项。

      4. 如果未找到匹配项,则按降序检查小于 0 的斜体值,直到 找到匹配项。

      上一个示例类似,下面是样式为 "font-style: normal" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 C 包含整个 字体族中的最小倾斜值,所以该算法会选择字体 C。但是,如果字体 C 因某种原因 从字体族中被排除,则不会立即选择字体 B;而是会 考察斜体值,并且可能选择某个斜体值。但是,如果未选择任何斜体 值,则随后会选择字体 B,接着是字体 A。

      如果在上述搜索中找到一个倾斜角度,则所有不包含该倾斜 角度的字体都将从匹配集合中排除。否则,如果在 上述搜索中找到一个斜体值,则所有不包含该斜体值的字体都将从匹配 集合中排除。

      测试

      用户代理不要求区分斜体字体和倾斜字体。在此类用户 代理中,上述 font-style 匹配步骤通过 将斜体值和倾斜角度映射到同一标度来执行。此 映射的确切性质未定义,不过,斜体值 1 必须映射到与 倾斜角度 11deg 相同的值。在通过 @font-face 规则定义的字体 族中,必须使用 font-style 描述符的值来区分斜体和倾斜 字体。

      对于不包含任何斜体或倾斜字体的字体族,如果 font-synthesis 属性的值允许,用户代理 可以创建人工倾斜字体。

    3. 接下来匹配 font-weight。如果字体不 具有任何字重强弱变化的概念,则其字重按照 属性定义中的列表进行映射。如果使用 bolder/lighter 相对 字重,则根据继承的字重值计算有效字重,具体如 font-weight 属性定义中所述。如果执行上述步骤后 的匹配集合中包含字重值涵盖 font-weight 所需值的字体,则字重值不包含所需 font-weight 值的字体将从匹配集合中移除。如果没有字体包含 所需值,则使用以下规则选择一个字重值:

      • 如果所需字重在 400 到 500 之间(含两端),则按升序检查大于或 等于目标字重的字重,直到达到并检查 500, 然后按降序检查小于目标字重的字重, 接着检查大于 500 的字重,直到找到匹配项。

      • 如果所需字重小于 400,则首先按降序检查小于或等于 所需字重的字重,然后按升序检查 高于所需字重的字重,直到找到 匹配项。

      • 如果所需字重大于 500,则首先按升序检查大于或等于 所需字重的字重,然后按降序检查 低于所需字重的字重,直到找到 匹配项。

        测试
      上一个示例类似,下面是样式为 "font-weight: 400" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 B 包含整个字体族中的最小距离, 所以该算法会选择字体 B。但是,如果字体 B 因某种原因从 字体族中被排除,那么字体 C 将包含字体族中的最小距离,因此会 被选中。如果 C 被排除,则会选择 D,接着是字体 A, 然后是 E。

      上一个示例类似,下面是样式为 "font-weight: 450" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 C 包含整个字体族中的最小距离, 所以该算法会选择字体 C。但是,如果字体 C 因某种原因从 字体族中被排除,那么字体 D 将包含字体族中的最小距离,因此会 被选中。如果 D 也被排除,则会选择 B,接着是字体 A, 然后是 E。

      上一个示例类似,下面是样式为 "font-weight: 500" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 D 包含整个字体族中的最小距离, 所以该算法会选择字体 D。但是,如果字体 D 因某种原因从 字体族中被排除,那么字体 B 将包含字体族中的最小距离,因此会 被选中。如果 B 被排除,则会选择 C,接着是字体 B、A, 然后是 E。

      上一个示例类似,下面是样式为 "font-weight: 300" 的元素的概念性 距离图:

      距离图

      可以看出,因为字体 B 包含整个字体族中的最小距离, 所以该算法会选择字体 B。但是,如果字体 B 因某种原因从 字体族中被排除,那么字体 A 将包含字体族中的最小距离,因此会 被选中。如果 A 被排除,则会选择 C。

      一旦通过此过程确定了最接近的匹配字重, 不包含此确定字重的字体将从匹配 集合中移除。

      注: [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(<font-feature-value-name>) || historical-forms || styleset(<font-feature-value-name>#) || character-variant(<font-feature-value-name>#) || swash(<font-feature-value-name>) || ornaments(<font-feature-value-name>) || annotation(<font-feature-value-name>) ]
初始值: normal
适用元素: 所有元素和文本
继承性:
百分比: 不适用
计算值: 按指定
规范顺序: 遵循语法
动画类型: 离散型
Tests
<font-feature-index> = <integer>
<font-feature-value-name> = <ident>

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

对于下方列出的许多属性值,字体中可用若干种不同的替代字形。可用替代字形数量及其含义依赖于具体字体,因此在下列值定义中均标记为 特定字体。由于这些替代字形的本质与字体相关, @font-feature-values 规则用于为 特定字体家族或一组字体家族定义关联,将字体特有的数值 <font-feature-index> 与自定义 <font-feature-value-name> 绑定,然后通过本属性选择指定替代字形:

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

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

当给定家族或某一特定特性类型下,没有定义某个 <font-feature-value-name> 时,计算值必须视作已定义一样。 但若属性值中包含这些未定义的 <font-feature-value-name> 标识符,在选择字形时必须忽略。

/* 这两条样式规则效果相同 */

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

这样可以只为某组字体家族定义和使用这些值,但如果发生回退,因为字体家族名称已不同则会被忽略。如果某值超出字体支持范围也会被忽略。这些值绝不会应用于通用字体族。

各个值含义如下:

normal
下方所列特性均不启用。
historical-forms
启用历史字形(OpenType 特性: hist)。
historical form example
stylistic(<font-feature-value-name>)
启用风格化替代(特定字体,OpenType 特性: salt <font-feature-index>)。
stylistic alternate example
styleset(<font-feature-value-name>#)
启用风格集合(特定字体,OpenType 特性: ss<font-feature-index> OpenType 目前定义了 ss01ss20)。
styleset example
character-variant(<font-feature-value-name>#)
启用特定字符变体(特定字体,OpenType 特性: cv<font-feature-index> OpenType 目前定义了 cv01cv99)。
swash(<font-feature-value-name>)
启用花式体字形(特定字体,OpenType 特性: swsh <font-feature-index>, cswh <font-feature-index>)。
swash example
ornaments(<font-feature-value-name>)
启用替换为默认装饰体字形(若字体提供,特定字体,OpenType 特性: ornm <font-feature-index>)。 某些字体为大量字符提供装饰体替代字形;但将任意字符(如字母数字)作为装饰体展示是不好的实践,因为这会曲解数据语义。 鼓励字体设计者将所有装饰体(除 Unicode Dingbats 区块明确编码者等以外)都作为项目符号(U+2022)的替代字形, 以便作者可通过 ornaments() 选择所需字形。
ornaments example
annotation(<font-feature-value-name>)
启用替代注解体字形(特定字体,OpenType 特性: nalt <font-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 <font-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 前置内容 是逗号分隔的字体家族名称列表,需符合 <font-family-name>font-family 属性中的定义。 这意味着只允许命名字体家族; 如果规则里包含通用字体或系统字体,则为语法错误。 但是如果用户代理把某通用字体定义为一个具体命名字体(例如 Helvetica), 就会用该家族名关联的设置。 如果 <font-family-name> 列表中出现语法错误, 整个 @font-feature-values 规则无效,必须被忽略。

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

或者

多次指定同一 <font-feature-value-type> 是合法的; 它们的内容会级联在一起。 每个 特性值块 接受一个声明列表, 这些声明在此处称为 字体特性值声明, 其中声明名可以是任意 css 标识符, 值必须为一个或多个非负 <integer> 列表。

特性值块 接受任意声明名; 这些名称必须是 <font-feature-value-name>,遵循标准 CSS 语法规则, 并且是区分大小写的 (因此 foo: 1;FOO: 2 是两个不同特性)。

每个声明在 @annotation@ornaments@stylistic@swash 中的值,必须符合语法 <font-feature-index>, 否则此声明无效并必须被忽略。

每个声明在 @character-variant 中的值,必须符合语法 <font-feature-index [0,99]> <font-feature-index [0,∞]>, 否则声明无效并必须被忽略。

每个声明在 @styleset 中的值,必须符合语法 <font-feature-index [0,20]>+, 否则声明无效并必须被忽略。

注:每个特性名仅在一个 特性值块 内唯一。 不同 特性值块 间, 或同类型 特性值块 在不同 @font-feature-values 规则中, 名称可以复用且不会冲突。

对于 <font-family-name> prelude 中的每个字体家族名,在 @font-feature-values 里, 每个 字体特性值声明 都定义了 (家族名、特性块名、声明名)三元组 与声明值中的一个或多个整数间的映射。 若文档中同一三元组出现多次 (比如在一个代码块中), 以最后定义的为准。

例如,下面这些都定义了 完全相同的一组字体特性值:
/* 默认写法 */
@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;     /* 等价于 ss05 = 1 */
      swirly: 2;     /* 等价于 ss02 = 1 */
    }
  }

character-variant() 属性值和 @character-variant 描述符 支持两个值, 即启用某特性(用第一个值),并把它设为指定(第二个)值。

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

styleset() 属性值及 @styleset 规则, 多个值表示多个风格集合一起被启用。值为 1 到 99 时启用 OpenType 特性 ss01ss99。 但 OpenType 标准官方只定义了 ss01ss20。 对于 OpenType 字体,值大于 99 或等于 0 时, 在解析时不会报语法错误,但不会启用任何 OpenType 特性。

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

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

    @swash {
      swishy: 3 5;     /* swash 取多个值,语法错误 */
    }
  }

  p.codeblock {
    /* 等价于 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; }   /* 等价于 cv01 = 2 */
    @character-variant { beta-3: 2 3; }    /* 等价于 cv02 = 3 */
    @character-variant { epsilon: 5 3 6; } /* 超过2个值,语法错误,定义被忽略 */
    @character-variant { gamma: 12; }      /* 等价于 cv12 = 1 */
    @character-variant { zeta:   20 3; }   /* 等价于 cv20 = 3 */
    @character-variant { zeta-2: 20 2; }   /* 等价于 cv20 = 2 */
    @character-variant { silly: 105; }     /* >99, 忽略 */
    @character-variant { dumb: 323 3; }    /* >99, 忽略 */
  }

  #title {
    /* 使用 beta 的第3种变体,gamma 的第1种变体 */
    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(<font-feature-value-name>) || historical-forms || styleset(<font-feature-value-name>#) || character-variant(<font-feature-value-name>#) || swash(<font-feature-value-name>) || ornaments(<font-feature-value-name>) || annotation(<font-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 文档中针对给定文字体系和书写模式 定义的默认特性。 必需连字、常用连字和上下文形式 必须默认启用 (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. 默认启用的字体特性会被应用,其中包括给定文字体系所必需的特性。 有关这些特性的说明,请参阅§ 7.1 默认特性

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

    font-style 启用的值的应用会受到字体选择的影响,因为此 属性可能会选择 斜体或倾斜字体。所应用的值是由字体匹配算法确定的最接近匹配值。用户代理必须 因 font-style 属性而至多应用一个值;不得同时设置 "ital" 和 "slnt" 值。

    如果所选字体是在 @font-face 规则中定义的,则在此步骤中应用的值 应当限制在该 @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/none' 的有效 font-named-instance 描述符, 并且根据§ 5.1 本地化名称匹配规则, 加载的字体资源中包含具有该名称的命名实例, 则会应用该命名实例所表示的所有变体值。 这些值会限制在该字体所支持的值范围内。

  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 如果存在 wght 轴,font-weight 属性将设置该轴。
宽度(wdthfont-width 如果存在 wdth 轴,font-width 属性将设置该轴。
倾斜(slnt)或斜体(italfont-style font-style 属性将根据 其值设置 slntital 轴。
光学尺寸(opszfont-optical-sizing 如果存在 opsz 轴,font-optical-sizing 属性将设置该轴。

使用字体变体设置 不会影响需要使用后备字体时的字体选择, 而对同一轴使用字体属性 则会影响字体选择。

在可能的情况下, 作者通常应使用与字体变体相关的其他属性 (例如 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 声明中的其他轴值不会被忽略。

如果字体支持某个变体轴, 但其设置值大于或小于字体预定义的范围, 则会将其限制为该字体所支持的最接近值。

允许使用小数值或负值。

注: 最好通过使用 font-style 属性来获得倾斜字形。 不过,如果直接使用 slnt 轴, 即通过 font-variation-settings, 请记住,其定义中 正角度表示逆时针倾斜, 与 CSS 的方向相反。

如果同一轴名称出现多次,则最后一次出现时关联的值会取代该轴此前的任何值。通过访问此 属性的计算值,可以观察到这种去重。

计算值包含去重后的轴名称, 按代码单元升序排列。

尽管这是专门为 OpenType / TrueType 变体定义的, 但未来可能会加入其他支持字体变体的现代字体格式的 变体轴。 在可能的情况下, 为其他字体格式定义的变体 应尝试遵循已注册变体轴的模式。

可以使用以下机制 对 font-variation-settings 进行动画处理。如果两个 font-feature-settings 声明 “相似”,则可以在它们之间进行动画处理。 “相似”的声明是指其中出现相同属性集合(顺序可以任意)的声明。由于后续重复属性会替代先前的重复属性,因此即使 两个声明包含的属性数量不同,它们也可以“相似”。 如果两个声明“相似”, 则会在声明中的对应值之间成对进行动画处理。 否则,无法进行动画处理。 在这种情况下, 动画的“起始”值会在动画期间的某个未指定时间切换为“目标”值。

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>? ,
    [ <'font-palette'> && <percentage [0,100]>? ]# )
normal
如果 color-scheme 属性被设置为 normal' 以外的值, 用户代理应该视情况选择第一个浅色或深色调色板。 否则,用户代理使用默认调色板 或默认字形着色来显示彩色字体。

当彩色字体格式要求使用前景色时,用户代理应该考虑 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>

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

<palette-mix()>
此值定义了一个或多个调色板值之间插值中的一个位置, 这些调色板值可通过 <palette-identifier>、调色板 关键字 normallightdark 或另一个 <palette-mix()> 值来标识。

字体的字形必须使用这样一个调色板进行渲染,该调色板通过 按照 CSS Color 4 § 13. 颜色插值, 针对每个调色板颜色索引,在 作为参数指定的调色板列表中相匹配的颜色索引之间进行插值来创建, 并在需要时递归解析 <palette-mix()> 函数。

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

百分比按照 CSS Color 5 § 3.2 百分比归一化进行归一化。

Tests

注:名称 light' 和 dark 描述的是该调色板可用于的背景, 而不是调色板本身的颜色。

当深色模式生效时,使用深色模式调色板
@media (prefers-color-scheme: dark) {
        .banner {font-palette: dark;
      }
    }
一个字体具有一个包含以下三个条目的深色模式调色板:
  1. #eee8aa
  2. #dd4541
  3. #72342e

此外,还定义了两个自定义调色板,其中一个名为 "--warm":

  1. oklch(85% 0.14 88)
  2. oklch(62% 0.13 28)
  3. oklch(32% 0.05 29.6)

另一个名为 "--soft":

  1. color(display-p3 0.89 0.89 0.76)
  2. color(display-p3 0.75 0.55 0.55)
  3. color(display-p3 0.508 0.435 0.422)

此调色板混合:

font-palette: palette-mix(dark 20%, --warm 45%, --soft);

将创建以下调色板 (--soft 的百分比被省略,因此为 35%, 并且颜色插值方法被省略,因此为 oklab):

  1. oklab(88.389% -0.00651 0.09474)
  2. oklab(64.379% 0.11148 0.05236)
  3. oklab(42.124% 0.04469 0.02408)
在调色板之间做动画。
@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; /* ...不过第2号原本为粉色,被我覆写成 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
值: <font-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 作者选择 对某些表情符号码位使用表情符号呈现还是文本呈现。 传统上,这些呈现样式是通过 在某些码位后附加变体选择符 15(U+FE0E)或变体选择符 16(U+FE0F) 来选择的。 不过,font-variant-emoji 允许 Web 作者设置默认 呈现样式, 从而可以取代变体选择符。

只有 Unicode 列出的、会参与构成 Unicode 表情符号呈现序列的码位 才会受到此属性的影响。 在本 CSS 规范中, 这些字符称为表情符号呈现参与码位。 此属性对任何其他字符均无影响。

预计此属性会影响字体后备; 不过,字体后备与 font-variant-emoji 之间交互的确切方式明确未作规定。 不过,变体选择符必须包含在前一个簇中, 如上面的簇匹配一节所定义。 这种行为的自然结果 是变体选择符不得使用与前一个字符不同的字体来渲染。 因此,它会使字体后备表现得 就好像意图使用相应的变体选择符 (如值的说明中所述); 随后执行字体后备,包括簇后备规则, 并且必须考虑这些“附加的”变体选择符的 呈现偏好。

即使使用了 font-variant-emoji, 元素内容中存在变体选择符 15(U+FE0E)或变体选择符 16(U+FE0F) 也会覆盖 font-variant-emoji 中指定的渲染方式。 因此,font-variant-emoji 设置一个 默认呈现方式, 正在渲染的文本可以选择不采用该方式。

注: 不同平台对于 如何处理表情符号呈现序列有不同的惯例。 跨平台 UA 可能希望遵循各个平台各自的惯例, 也可能希望在所有平台上采用相同的方法。 当需要进行表情符号样式渲染时, UA 可能希望忽略不包含颜色表的字体。 另一个 UA 则可能希望改用相同的机械式簇后备算法, 就像处理任意其他簇时一样。

除 FE0E VARIATION SELECTOR-15 和 U+FE0F VARIATION SELECTOR-16 之外的变体选择符 不得对字体选择产生任何影响。 如果存在其中一个变体选择符, 但先前选择的字体不支持它, 则忽略该变体选择符。

当用户代理决定是否对某个特定字符使用表情符号呈现或文本呈现时,不应 考虑 BCP47 的 -u- 扩展,该扩展用于 langxml: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
为其定义给定特性值集合的一个或多个字体族的列表。
annotation类型为 CSSFontFeatureValuesMap,只读
等等。
对于给定的 font-variant-alternates 值类型,与特性值名称相关联的特性值映射

CSSFontFeatureValuesRule 的每个值映射属性都反映 通过相应特性值块定义的值。 因此,annotation 属性 包含 @annotation 特性值块中包含的值,而 ornaments 属性包含 @ornaments 特性值块中包含的值, 依此类推。

CSSFontFeatureValuesMap 接口使用 默认映射类方法, 但 set() 方法具有不同的行为。 它接收一个无符号整数序列,并 将其与给定的 featureValueName 相关联。该方法 与默认映射类方法的行为相同, 不同之处在于,单个 unsigned long 值会被视为仅包含 一个值的序列。如果传入的 值数量无效,该方法会抛出异常。如果相关联的 特性 值块 只允许有限数量的值,则当传给 set() 方法的输入 序列包含的值超过该数量限制时,会抛出 InvalidAccessError 异常。有关给定类型的 特性值块 所允许的最大值数量的详细信息,请参阅 多值特性值定义的说明。

注: get() 方法始终返回一个值序列,即使该序列只包含 一个值。

测试

12.3. CSSFontPaletteValuesRule 接口

CSSFontPaletteValuesRule 接口表示一个 @font-palette-values 规则。

[Exposed=Window]
  interface CSSFontPaletteValuesRule : CSSRule {
    readonly attribute CSSOMString name;
    readonly attribute CSSOMString fontFamily;
    readonly attribute CSSOMString basePalette;
    readonly attribute CSSOMString overrideColors;
  };

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 高级排版字体特性注册表。URL:https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.。CSS 层叠与继承第 5 级。2022 年 1 月 13 日。CR。URL:https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou。CSS 颜色模块 第 4 级。2026 年 8 月 6 日。CRD。URL:https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; Una Kravets; Lea Verou。CSS 颜色模块 第 5 级。2026 年 7 月 31 日。WD。URL:https://www.w3.org/TR/css-color-5/
[CSS-COLOR-ADJUST-1]
Elika Etemad; 等。CSS 颜色调整模块 第 1 级。2025 年 12 月 16 日。CR。URL:https://www.w3.org/TR/css-color-adjust-1/
[CSS-ENV-1]
CSS 环境变量模块第 1 级。2025 年 9 月 23 日。FPWD。URL:https://www.w3.org/TR/css-env-1/
[CSS-INLINE-3]
Elika Etemad。CSS 行内布局模块第 3 级。2024 年 12 月 18 日。WD。URL:https://www.w3.org/TR/css-inline-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin。CSS 语法模块第 3 级。2021 年 12 月 24 日。CRD。URL:https://www.w3.org/TR/css-syntax-3/
[CSS-TEXT-4]
Elika Etemad; 等。CSS 文本模块第 4 级。 2026 年 8 月 14 日。WD。URL:https://www.w3.org/TR/css-text-4/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad。CSS 值与单位 模块第 3 级。2024 年 3 月 22 日。CRD。URL:https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad。CSS 值与单位 模块第 4 级。2024 年 3 月 12 日。WD。URL:https://www.w3.org/TR/css-values-4/
[CSS-VARIABLES-1]
Tab Atkins Jr.。用于层叠 变量的 CSS 自定义属性模块第 1 级。2022 年 6 月 16 日。CR。URL:https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii。CSS 书写模式第 4 级。2019 年 7 月 30 日。CR。URL:https://www.w3.org/TR/css-writing-modes-4/
[CSS2]
Bert Bos; 等。层叠样式表第 2 级修订版 1(CSS 2.1)规范。2011 年 6 月 7 日。REC。URL:https://www.w3.org/TR/CSS2/
[CSS3TEXT]
Elika Etemad; Koji Ishii; Florian Rivoal。CSS 文本模块 第 3 级。2026 年 8 月 14 日。CRD。URL:https://www.w3.org/TR/css-text-3/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez。CSS 对象模型 (CSSOM)。2021 年 8 月 26 日。WD。URL:https://www.w3.org/TR/cssom-1/
[FETCH]
Anne van Kesteren。Fetch 标准。现行 标准。URL:https://fetch.spec.whatwg.org/
[GRAPHITE]
Graphite 技术概述。 2012 年。URL:https://graphite.sil.org/graphite_techAbout.html
[HTML]
Anne van Kesteren; 等。HTML 标准。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[I18N-GLOSSARY]
Richard Ishida; Addison Phillips。国际化 术语表。2024 年 10 月 17 日。NOTE。URL:https://www.w3.org/TR/i18n-glossary/
[INFRA]
Anne van Kesteren; Domenic Denicola。Infra 标准。现行标准。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 中 指示要求级别的关键词。1997 年 3 月。当前最佳实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[RFC8081]
C. Lilley。“font”顶级媒体 类型。2017 年 2 月。提议标准。URL:https://www.rfc-editor.org/info/rfc8081/
[UNICODE]
Unicode 标准。URL:https://www.unicode.org/versions/latest/
[UTS51]
Mark Davis; Ned Holbrook。Unicode 表情符号。2025 年 9 月 4 日。Unicode 技术标准 #51。URL:https://www.unicode.org/reports/tr51/tr51-29.html
[WEBIDL]
Edgar Chen; Timothy Gu。Web IDL 标准。现行 标准。URL:https://webidl.spec.whatwg.org/

参考性参考文献

[CHARMOD-NORM]
Addison Phillips; 等。万维网字符模型: 字符串匹配。2026 年 7 月 16 日。FPWD。URL:https://www.w3.org/TR/charmod-norm/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.。CSS 显示模块第 4 级。2025 年 11 月 6 日。WD。URL:https://www.w3.org/TR/css-display-4/
[CSS-FONT-LOADING-3]
Tab Atkins Jr.。CSS 字体加载模块第 3 级。2023 年 4 月 6 日。WD。URL:https://www.w3.org/TR/css-font-loading-3/
[CSS-FONTS-3]
John Daggett; Myles Maxfield; Chris Lilley。CSS 字体 模块第 3 级。2018 年 9 月 20 日。REC。URL:https://www.w3.org/TR/css-fonts-3/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal。CSS 溢出模块 第 3 级。2025 年 10 月 7 日。WD。URL:https://www.w3.org/TR/css-overflow-3/
[CSS-TRANSFORMS-1]
Simon Fraser; 等。CSS 变换模块第 1 级。2019 年 2 月 14 日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[CSS3-CONDITIONAL]
Chris Lilley; David Baron; Elika Etemad。CSS 条件规则模块第 3 级。2024 年 8 月 15 日。CRD。URL:https://www.w3.org/TR/css-conditional-3/
[IFT]
Chris Lilley; Garret Rieger; Skef Iterum。增量字体 传输。2025 年 11 月 18 日。CRD。URL:https://www.w3.org/TR/IFT/
[OPEN-FONT-FORMAT]
信息技术 — 音视频 对象编码 — 第 22 部分:开放字体格式。2019 年 1 月。已发布。URL:https://www.iso.org/standard/74461.html
[PFE-report]
Chris Lilley。渐进式字体增强:评估 报告。2020 年 10 月 15 日。Note。URL:https://www.w3.org/TR/PFE-evaluation/
[TRUETYPE]
TrueType™ 参考 手册。URL:https://developer.apple.com/fonts/TrueType-Reference-Manual/
[UAX29]
Josh Hadley。Unicode 文本 分段。2025 年 8 月 17 日。Unicode 标准附录 #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-font-family-name> 见各个属性 所有元素和文本 见各个属性 见各个属性 按语法 见各个属性
font-family [ <font-family-name> | <generic-font-family> ]# 取决于用户代理 所有元素和文本 不适用 离散 按语法 列表,每一项为字符串和/或 <generic-font-family> 关键字
font-feature-settings normal | <feature-tag-value># normal 所有元素和文本 不适用 离散 按语法 与指定值相同
font-kerning auto | normal | none auto 所有元素和文本 不适用 离散 按语法 与指定值相同
font-language-override normal | <string> normal 所有元素和文本 不适用 离散 按语法 指定的字符串或关键字 none
font-optical-sizing auto | none auto 所有元素和文本 不适用 离散 按语法 指定的关键字
font-palette normal | light | dark | <palette-identifier> | <palette-mix()> normal 所有元素和文本 不适用 按计算值 按语法 指定的关键字、标识符或 <palette-mix()> 函数。 如果生成的调色板等效,则必须将 <palette-mix()> 简化为单个关键字或标识符。
font-size <absolute-size> | <relative-size> | <length-percentage [0,∞]> | math medium 所有元素和文本 参照父元素的字体大小 按计算值类型 按语法 绝对长度
font-size-adjust none | <number [0,∞]> none 所有元素和文本 不适用 按计算值类型 按语法 数字或关键字 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 所有元素和文本 不适用 离散 按语法 指定的关键字
font-synthesis-position auto | none auto 所有元素和文本 不适用 离散 按语法 指定的关键字
font-synthesis-small-caps auto | none auto 所有元素和文本 不适用 离散 按语法 指定的关键字
font-synthesis-style auto | none | oblique-only auto 所有元素和文本 不适用 离散 按语法 指定的关键字 视觉
font-synthesis-weight auto | none auto 所有元素和文本 不适用 离散 按语法 指定的关键字 视觉
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(<font-feature-value-name>) || historical-forms || styleset(<font-feature-value-name>#) || character-variant(<font-feature-value-name>#) || swash(<font-feature-value-name>) || ornaments(<font-feature-value-name>) || annotation(<font-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(<font-feature-value-name>) || historical-forms || styleset(<font-feature-value-name>#) || character-variant(<font-feature-value-name>#) || swash(<font-feature-value-name>) || ornaments(<font-feature-value-name>) || annotation(<font-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 所有元素和文本 不适用 离散 按语法 指定的关键字
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 <font-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 <font-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 中根据字体类型加载字体。
选择倾向于使用斜体而非普通字体的阈值 应低于平均角度
添加更多示例和图片。