CSS 图片模块第4级

W3C 工作草案

更多关于本文档的信息
此版本:
https://www.w3.org/TR/2025/WD-css-images-4-20250930/
最新发布版本:
https://www.w3.org/TR/css-images-4/
编辑草稿:
https://drafts.csswg.org/css-images-4/
历史版本:
历史记录:
https://www.w3.org/standards/history/css-images-4/
反馈:
CSSWG 问题仓库
跟踪器
规范内标注
编辑者:
Tab Atkins Jr. (Google)
Elika J. Etemad / fantasai (Apple)
Lea Verou (特邀专家)
为本规范建议编辑:
GitHub 编辑器
增量规范:
测试套件:
https://wpt.fyi/results/css/css-images/

摘要

本模块包含 CSS 第4级中与<image>类型和替换元素相关的特性。 它包括并扩展了 CSS 第2级[CSS2]以及本规范前一版本 [css-images-3]的功能。 与“CSS 图像模块第3级”[css-images-3]相比的主要扩展是对<image>类型的若干新增内容,比如image()记法、element() 记法,以及圆锥渐变。 本级当前作为对第3级模块的差异规范进行维护。

CSS是一种用于描述结构化文档(如 HTML 和 XML) 在屏幕、纸张等上的渲染的语言。

本文件状态

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

本文件由CSS 工作组作为工作草案, 采用推荐流程发布。 作为工作草案发布 并不代表 W3C 及其成员的认可。

这是一个草稿文档, 可能随时被更新、替换或废弃。 除非作为进行中的工作,否则不应引用本文件。

请通过在 GitHub 上提交 issue(推荐), 并在标题中注明规范代码“css-images”,格式如下: “[css-images] ……评论摘要……”。 所有问题和评论均会被归档。 或者,也可将反馈发送至(归档)公共邮件列表www-style@w3.org

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

本文件由依据W3C 专利政策运作的小组制作。 W3C 维护一份与该组成果相关的专利披露公开列表; 该页面还包括专利披露的说明。 任何个人如果确知某项专利中包含基本权利要求, 必须根据W3C 专利政策第6节进行披露。

1. 介绍

本节为非规范性内容。

本模块引入了更多表示二维图像的方法, 例如作为带有颜色回退的 URL圆锥渐变, 或文档中其他元素的渲染

1.1. 值定义

本规范遵循CSS 属性定义约定, 来自[CSS2],并采用值定义语法, 来自[CSS-VALUES-3]。 本规范未定义的值类型,参见 CSS Values & Units [CSS-VALUES-3]。 与其它 CSS 模块结合使用时,这些值类型的定义可能会被扩展。

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

2. 二维图像值:<image>类型

<image>值类型表示一个二维图像。它可以是url 引用图像记法, 或渐变记法。 其语法如下:

<image> = <url> | <image()> | <image-set()> | <cross-fade()> | <element()> | <gradient>

<image>可用于许多 CSS 属性, 包括background-imagelist-style-imagecursor属性[CSS2](在这些属性的值中替换 <url> 组件)。

在某些情况下,图片是无效的, 比如<url>指向的资源不是有效的图片格式 或加载失败。 一个无效图片会被渲染成 一个纯色透明图片且没有自然尺寸。 但无效图片在某些上下文下 会触发错误处理条款。 例如,在list-style-image中出现无效图片, 会被视为none, 从而允许list-style-type渲染出来。[CSS2]

图片加载时, 是一个加载中图片加载中图片 不是 无效图片, 但行为类似: 渲染为纯色透明图片,且无自然尺寸, 并可能在有回退渲染的上下文中触发回退渲染, 但不能触发回退资源的加载。 或者,如果加载中图片正替换一个已加载的图片 (如文档或样式表变化导致),且用户代理有跟踪此信息, 则可继续渲染已加载图片替换加载中图片

部分加载的图片(其自然尺寸已知但图片数据未完全加载) 可被视为加载中图片 或作为已加载图片但仅渲染部分数据。 例如,用户代理可以在交错 GIF 的首轮像素数据加载后立刻渲染 或在图片头(包含尺寸信息)解析后立刻渲染,并随着更多数据到来刷新渲染; 或者也可以等整个图片加载完毕再使用。

计算后 <image>值 是指定值,其中所有<url><color><length>已被计算。

2.1. 图像文件格式

至少,UA 必须支持下列图片文件格式, 当它们被<image>值引用时, 在所有允许使用<image>的属性中:

UA 也可以支持其它文件格式。

2.2. 图像引用:url() 记法

注:[css-images-3]一致,无变化。

2.3. 获取外部图片

为样式表获取外部图片, 给定<url> urlCSS 样式声明 declaration获取样式资源,参数为 url, 其中 ruleOrDeclaration 为 declaration, destination 为 "image", CORS 模式为 "no-cors", processResponse 为下列步骤, 给定response res 和 null、failure 或字节流 byteStream: 如果 byteStream 是字节流,则从字节流加载图片。

2.4. 分辨率/类型协商:image-set() 记法

为用户设备提供最合适的图像分辨率可能很困难。 理想情况下,图片应与用户设备的分辨率一致, 而这在不同用户间是变化的。 但其他因素也会影响图片选择决策; 例如,若用户处于慢速移动网络, 则他们可能更倾向于接收低分辨率图片, 而不是等待大尺寸的高分辨率图片加载完毕。 image-set()函数让作者可以忽略大多数这些问题, 只需提供多种分辨率的图片, 由 UA 根据具体情况自动选择最合适的。

该方案假设分辨率等同于文件大小, 因此无法很好地处理多分辨率矢量图片集, 或混合矢量与位图(如图标)。 例如,高分辨率用矢量, 低分辨率用像素优化的位图, 低带宽时再次用同一个矢量(虽然分辨率高但文件小)。

image-set() 的语法如下:

<image-set()> = image-set( <image-set-option># )
<image-set-option> = [ <image> | <string> ]
                     [ <resolution> || type(<string>) ]?

我们应增加 "w" 和 "h" 维度, 以匹配 HTML picture 的能力。

<string>image-set()中代表<url>

image-set() 函数不能嵌套自身, 无论是直接还是间接 (作为另一个<image>类型的参数)。

每个<image-set-option>都定义了image-set()函数的一个可选图片, 由三部分组成:

测试

image-set() 函数包含一个或多个 <image-set-option> 的列表, 并且必须从中只选一个, 用于决定它实际代表哪一个图片:

  1. 首先,将列表中所有在 type() 值中指定了未知或不支持的 MIME 类型的 <image-set-option> 移除。

  2. 其次,将列表中所有与前一个选项拥有相同 <resolution><image-set-option> 移除。

  3. 如果此时没有剩下任何 <image-set-option>, 则该函数代表一个 无效图片

  4. 最后,在剩余的 <image-set-option> 中, UA 按自身标准选择要加载的图片, (比如显示器分辨率、网络速度等)。

  5. 随后,image-set() 函数就代表所选 <image><image-set-option>

UA 可以在页面生命周期内更换 <image-set-option>, 如果选择标准发生了足够大的变化(如分辨率切换、网络变化等)。

此示例展示如何使用 image-set() 提供三种图片版本: 一个“普通”版本, 一个“高分辨率”版本, 以及一个用于高品质打印(因为打印机分辨率可能极高)的超高分辨率版本:
background-image: image-set( "foo.png" 1x,
                         "foo-2x.png" 2x,
                         "foo-print.png" 600dpi );
此示例展示 type() 函数的用法, 用于同时为新高质量格式和旧广泛支持格式提供多版本图片:
background-image: image-set( "foo.avif" type("image/avif"),
                         "foo.jpg" type("image/jpeg") );

注意 AVIF 图片放在前面; 由于两张图片分辨率相同(未指定时默认 1x), JPEG 图片因在后而会在支持 AVIF 的 UA 中被自动丢弃。

而在旧版 UA 中, AVIF 图片会被忽略 (因为 UA 知道不支持 "image/avif" 文件), 因此会选择 JPEG。

位图图片可以与矢量图片甚至 CSS 生成图片混用。

例如,下面这段代码 在高分辨率屏幕上采用细节丰富的图片, 在低分辨率场景则用普通 CSS linear-gradient() 代替:

background-image: image-set( linear-gradient(cornflowerblue, white) 1x,
                         url("detailed-gradient.png") 3x);

2.5. 图片回退与注解:image() 记法

image() 函数允许作者:

image() 记法定义如下:

image() = image( <image-tags>? [ <image-src>? , <color>? ]! )
<image-tags> = [ ltr | rtl ]
<image-src> = [ <url> | <string> ]

image() 中使用的 <string> 表示一个 <url>。 与 CSS 中的其它 URL 一样, 相对 URL 会在计算 image() 指定值时被解析为绝对 URL(详见 Values & Units [CSS-VALUES-3])。

如果图片的元数据(如 EXIF)中指定了方向, UA 必须按照元数据指定的方向旋转或翻转图片以正确显示。

2.5.1. 图片回退

如果 image() 中同时指定了 URL 和 <color>, 当 URL 表示为 无效图片加载中图片 时, image() 函数的渲染就如同未指定 URL 一样; 它会生成一个在 § 2.5.3 纯色图片 中指定的纯色图片。

如果只指定了 URL(未指定 <color>) 且其为 无效图片加载中图片image() 函数也表现为同样的无效或加载中图片。

测试
回退颜色可用于确保即使图片加载失败时文本依然可读。 例如,下面的传统代码在图片为矩形且不透明时表现良好:
body      { color: black; background: white; }
p.special { color: white; background: url("dark.png") black; }

当图片加载失败时, 背景色依然存在,确保白色文本可读。 但若图片带有透明度, 黑色会显示在透明处,这通常不是期望的效果。 image() 函数可解决此问题:

body      { color: black; background: white; }
p.special { color: white; background: image("dark.png", black); }

现在,图片加载时不会显示黑色, 但若图片加载失败, 黑色会出现,避免白色文本直接出现在白色背景上。

2.5.2. 图片片段

image() 中指定的 URL 表示资源的一部分 (例如通过 媒体片段标识符), 那么该部分会被裁剪出来并作为独立图片使用。

例如,给定如下图片和 CSS:

[9 circles, with 0 to 8 eighths filled in]

background-image: image('sprites.svg#xywh=40,0,20,20')

……元素的背景将是图片中从 (40px,0px) 开始、宽高为 20px 的部分, 也就是仅一个填充了四分之一的圆。

为了让作者利用 CSS 的前向兼容解析规则为图片切片提供回退, 支持 image() 记法的实现 必须 支持通过 image() 指定图片时的 xywh=#,#,#,# 形式的媒体片段标识符。[MEDIA-FRAGS]

注意,图片片段也可以与 url() 记法配合使用。 但不支持媒体片段的旧版 UA 会忽略片段,直接显示整个图片。

由于 image() 记法要求 UA 支持媒体片段, 作者可利用 CSS 的前向兼容解析规则, 在使用图片片段 URL 时提供回退:

background-image: url('swirl.png'); /* 旧 UA */
background-image: image('sprites.png#xywh=10,30,60,20'); /* 新 UA */

如果 URL 使用了实现不支持或不认可的片段标识符语法, 或对该类型图片无效, 则该 URL 应视为 无效图片

注: 这种错误处理仅限于 image(), 而不在 URL 的定义中,这样做是出于兼容性考虑。

2.5.3. 纯色图片

如果 image() 函数只指定了 <color> 参数(没有 URL), 则表示为指定颜色的纯色图片,且没有 自然尺寸

例如, 可以用这种方式简单地为背景图片“着色”, 即在其它图片上方叠加半透明色块:
background-image: image(rgba(0,0,255,.5)), url("bg-image.png");

background-color 不适合这种用法, 因为它生成的纯色总是在所有背景图片之下。

2.5.4. 双向敏感图片

在列出任何 <image-src>s 之前, 作者可以为图片指定方向性, 类似于在 HTML 元素上添加 dir 属性。 如果在带有相反 direction 的元素或内部使用定向图片, 则图片必须在内联方向上翻转 (如内联方向为 X 轴,则等同于 scaleX(-1) 变换)。

注: 未声明时, 图片默认无方向性, 因此不会受周围元素方向性的影响。

一个列表可以使用箭头图片作为项目符号指向内容。 如果列表中既有 LTR 也有 RTL 文本, 项目符号可能在左边也可能在右边, 图片设计为指向一侧的文本时,在另一侧则会指向外侧。 可以用如下代码修正:
<ul style="list-style-image: image(ltr 'arrow.png');">
  <li dir='ltr'>My bullet is on the left!</li>
  <li dir='rtl'>MY BULLET IS ON THE RIGHT!</li>
</ul>

效果应类似于:

⇒ My bullet is on the left!
  !THGIR EHT NO SI TELLUB YM ⇐

在 LTR 列表项中,图片会按原样显示。 但在 RTL 列表项中, 图片会在内联方向上翻转, 依然指向内容内侧。

2.6. 合成图片:cross-fade() 记法

在图片间过渡时, CSS 需要一种方式明确引用起始与结束图片的中间合成图片。 这可以通过 cross-fade() 函数实现, 它指定要合成的两张图片以及合成所处的过渡进度。

注: 作者也可用 cross-fade() 函数进行多种简单图片处理, 如用纯色为图片染色, 或合成径向渐变高亮页面的某一区域。

cross-fade() 语法定义如下:

cross-fade() = cross-fade( <cf-image># )
<cf-image> = [ <image> | <color> ] && <percentage [0,100]>? 

该函数表示由一张或多张图片合成生成的图片。

<percentage> 表示每张图片在与其它图片混合时保留的比例。 <percentage> 必须在 0%100% 之间(含);其它值无效。

若省略了某些百分比, 则所有已指定百分比相加后从 100% 减去, 结果向下取 0%, 然后在计算值时平均分配给所有省略百分比的图片。

虽然这不会反映在计算值中, 但如果所有参数的百分比和大于 100%, 尺寸/绘制细节会将它们缩放,使总和正好为 100%

另一方面, 当总和小于 100% 时, 尺寸/绘制细节等同于再加一个 透明参数, 其百分比设为补齐总和为 100% 所需的值。

如果提供了 <color>, 则代表一个“自动”尺寸的纯色图片(不会参与结果图片尺寸的计算;详见下文尺寸细节)。

测试

2.6.1. cross-fade() 尺寸

cross-fade() 所表示图片的尺寸是函数 <image> 参数的尺寸的加权平均; <color> 参数不影响尺寸。 其计算如下:

要确定 cross-fade() 的自然尺寸
  1. 归一化混合百分比, 得到 argsleftover

  2. 如果 leftover 为 100%, 则返回无 自然尺寸

  3. images 为空列表。

  4. 对函数参数中的每个 <cf-image> argument

    1. 如果 argument 不是 <image>, 或是无自然尺寸的 <image>继续

    2. item 为包含宽度、高度、百分比的 元组

    3. <image>, 按 对象尺寸协商 算法(按 cross-fade() 出现的上下文), 设置 item 的宽高为协商后 具体对象尺寸 的宽高。

    4. item 的百分比设为 argument 的百分比。

  5. images 为空, 返回无 自然尺寸

  6. 返回 自然宽度自然高度,为 images 中所有项的宽高按百分比加权平均。

    注: 百分比之和可能小于 100%, 因此简单加权平均前要先归一化。

2.6.2. cross-fade() 绘制

cross-fade() 所表示的图片为各输入参数的加权平均,计算如下:

要确定 cross-fade() 的外观
  1. 归一化混合百分比, 得到 argsleftover

  2. images 为空列表。

  3. size 为宽度和高度的 元组, 初始化为 cross-fade() 的 具体对象尺寸 (用 cross-fade() 的自然尺寸 计算)。

  4. cross-fade() 的每个 argument

    1. item 为包含图片和百分比的 元组

    2. argument<image>, 缩放为 size 的宽高,并将 item 的图片设为结果。 否则 argument<color>, 则 item 的图片为该 <color> 的纯色图片,尺寸为 size

    3. item 的百分比设为 argument 的百分比。

  5. leftover 大于 0%, 向 images 添加一个元组,内容为尺寸为 size 的纯色透明黑图片和百分比 leftover

  6. final image 为尺寸为 size 的图片, 每个像素为 images 中每项图片的同位置像素按百分比加权线性平均 (平均颜色通道和透明度通道)。 计算时每个像素的颜色须为预乘 sRGB。

    上述运算细节

    这是对源图片做 N 路 Porter-Duff dissolve 操作。 Wikipedia 定义 dissolve 为随机从各源图片的对应像素中按权重选取, 但像素无限细小时等同于在预乘色彩空间做平均。

    特别地,这意味着 cross-fade(white 50%, transparent 50%) 会生成半透明纯白图片。 (而不是非预乘空间平均后的半透明灰色。)

    由于转为预乘会有精度损失, 且图形库未必原生支持此操作, 只要实现达到上述效果,用什么方法都可以。

    例如,也可按每像素 alpha 重分配百分比, 再在非预乘空间平均颜色通道。 如渲染 cross-fade(rgb(255 0 0 / 1) 40%, rgb(0 255 0 / .5) 20%, rgb(0 0 255 / 0) 40%), 按 alpha 1 / .5 / 0 重分配百分比得 40% / 10% / 0% (归一化为 80% / 20% / 0%), 此时平均原始颜色通道即可得到 rgb(204 51 0 / .5)。 (注意 alpha 仍按原百分比平均,不用重分配后百分比。)

  7. 返回 final image

2.6.3. 简化复杂 cross-fade()

按 WG 决议, 定义图片“相等”的概念, 并在计算值时合并相同图片,百分比求和。

按 WG 决议, 在计算值时简化直接嵌套的 cross-fade(), 直接分发百分比并展平结构;cross-fade(A 10%, cross-fade(B 30%, C 70%) 90%) 变为 cross-fade(A 10%, B 27%, C 63%)

2.7. 元素作为图片:element() 记法

element() 函数允许作者将文档中的某个元素作为图片使用。 当被引用元素的外观发生变化时, 图片也会随之变化。 例如,这可以用于幻灯片中实时预览前一页/后一页, 或引用 canvas 元素以生成精美的渐变甚至动画背景。

注: element() 函数只复现被引用元素的外观, 而不是其实际内容和结构。 作者应仅将其用于装饰性目的, 且不得用 element() 跨页面复现具有重要内容的元素。 如需内容复用,应直接在文档中插入多份元素。

element() 的语法为:

element() = element( <id-selector> )

其中 <id-selector> 是一个 ID 选择器 [SELECT]

是否需要能够引用外部文档中的元素(如 SVG paint server)? 还是说仅用 url() 就足够了?

此名称与 GCPM 中某个类似函数冲突。 需要解决此冲突。

希望能够对元素做“倒影”, 无论是在元素自身的 background-image 还是伪元素中。 这种用法需要特殊处理以避免触发循环检测。

当 overflow:paged 时, 如何定位视图中的单独页面?

element() 函数引用其参数所匹配的元素。 首先在 elementSources 映射中查找 ID, 如该节所述。 若未找到,则在文档中查找。 如果匹配到多个元素,则引用第一个元素。

element() 函数表示的图片会根据元素在文档中的可见性有所不同:

被渲染的元素, 不是替换元素的后代, 且生成 堆叠上下文
该函数表示的图片,其 自然尺寸 等于被引用元素的 装饰边界框

注: 因为图片默认会裁剪超出自身边界的内容, 所以超出 装饰边界框 的装饰(如 box-shadow)可能会被裁剪。

图片通过渲染被引用元素及其后代生成(尺寸与文档中一致), 绘制在无限 透明画布上, 并将 装饰边界框的边与图片边界对齐。

要求元素必须有一定程度的堆叠上下文是为了高效实现。 是否需要完整堆叠上下文,还是伪堆叠上下文即可? 必须是正常情况下的堆叠上下文,还是渲染为 element() 时临时视为堆叠上下文即可?

如果被引用元素自身或祖先应用了 transform,则渲染为图片时必须忽略 transform。[CSS3-TRANSFORMS]

如果被引用元素在分页中被拆分, 则显示时应将页面内容区在分页方向上首尾相连,初始包含块的起始边对齐页面边缘。跨行/列被拆分的元素直接以 装饰边界框渲染。

实现可以重用为被引用元素生成的位图, 也可以重新渲染以提升图片质量(如检测到 SVG 片段时); 后者情况下,图片内被引用元素的布局不能因再生成而改变。 即,图片外观必须与被引用元素一致,仅光栅化质量有所区别。

有点无厘头的例子: p 元素可以作为文档其他部分的背景复用:

<style>
#src { color: white; background: lime; width: 300px; height: 40px; position: relative; }
#dst { color: black; background: element(#src); padding: 20px; margin: 20px 0; }
</style>
<p id='src'>I’m an ordinary element!</p>
<p id='dst'>I’m using the previous element as my background!</p>

未渲染元素,但能提供 绘制源
函数表示的图片,其 自然尺寸和外观与 绘制源一致。 宿主语言定义绘制源的尺寸和外观。
例如,element() 函数可以引用 HTML 文档中的 SVG <pattern> 元素:
<!DOCTYPE html>
<svg>
  <defs>
    <pattern id='pattern1'>
      <path d='...'>
    </pattern>
  </defs>
</svg>
<p style="background: element(#pattern1)">
  I’m using the pattern as a background!
  If the pattern is changed or animated,
  my background will be updated too!
</p>

HTML 还定义了一些元素(如 canvas, img, video )也提供绘制源。这意味着 CSS 可以引用一个正在绘制但未显示在页面上的 canvas:

<!DOCTYPE html>
<script>
  var canvas = document.querySelector('#animated-bullet');
  canvas.width = 20; canvas.height = 20;
  drawAnimation(canvas);
</script>
<canvas id='animated-bullet' style='display:none'></canvas>
<ul style="list-style-image: element(#animated-bullet);">
  <li>I’m using the canvas as a bullet!</li>
  <li>So am I!</li>
  <li>As the canvas is changed over time with Javascript,
      we’ll all update our bullet image with it!</li>
</ul>
其它情况

函数表示 无效图片

例如,以下所有 element() 用法都会得到透明背景:

<!DOCTYPE html>
<p id='one' style="display:none; position: relative;">one</p>
<iframe src="http://example.com">
  <p id='two' style="position: relative;">I’m fallback content!</p>
</iframe>
<ul>
  <li style="background: element(#one);">
    display:none 的元素不会被渲染,且 P 元素
    不提供绘制源。
  </li>
  <li style="background: element(#two);">
    替换元素如 IFRAME 的后代
    也不能在 element() 中被引用。
  </li>
  <li style="background: element(#three);">
    没有 id 为 "three" 的元素,因此也会
    渲染为透明图片。
  </li>
</ul>

若元素没有关联 box,则称为未渲染。 例如,元素或祖先为 display:none 时会这样。 宿主语言可能定义更多判断元素未渲染的情形; 如在 SVG 中,<defs> 元素的任意后代都视为未渲染。

element() 函数用途广泛。 例如,可以用它在幻灯片中显示上一页/下一页缩略预览:

<!DOCTYPE html>
<script>
function navigateSlides() {
  var currentSlide = ...;
  document.querySelector('#prev-slide').id = '';
  document.querySelector('#next-slide').id = '';
  currentSlide.previousElementSibling.id = 'prev-slide';
  currentSlide.nextElementSibling.id = 'next-slide';
}
</script>
<style>
.slide {
  /* 需要成为堆叠上下文才能被 element() 使用 */
  position: relative;
}
#prev-preview, #next-preview {
  position: fixed;
  ...
}
#prev-preview { background: element(#prev-slide); }
#next-preview { background: element(#next-slide); }
</style>
<a id='prev-preview'>Previous Slide</a>
<a id='next-preview'>Next Slide</a>
<section class='slide'>...</section>
<section class='slide current-slide'>...</section>
...

本例中,navigateSlides 函数会更新前后幻灯片的 id, 然后分别显示在幻灯片旁的小浮动框中。 由于通过 element() 不能直接与幻灯片互动(只是图片), 因此可以为预览框添加 click 事件用于页面导航。

2.7.1. 绘制源

宿主语言可以定义某些元素提供 绘制源。 绘制源有固有的外观,并可获得 具体对象尺寸,无需布局或渲染, 因此即使未渲染也可用作图片。

在 HTML 中, imgvideocanvas 元素提供绘制源。

在 SVG 中,提供 paint server 的元素即为绘制源。注:在 SVG1.1 中, <linearGradient><radialGradient><pattern> 元素提供绘制源。 绘制方式按规范描述,坐标系如下:

objectBoundingBox
坐标系原点在绘制目标 具体对象尺寸的左上角, 宽高与 具体对象尺寸一致。 一个 用户坐标等于 具体对象尺寸的宽高。
userSpaceOnUse
坐标系原点在绘制目标 具体对象尺寸的左上角, 宽高与 具体对象尺寸一致。用户坐标与 CSS px 单位等价。

注: 未来版本可能会定义如何引用外部文档中的绘制源, 或仅由脚本创建且从未插入文档的源。

2.7.2. 使用文档外部源:ElementSources 接口

element() 通常选择文档内的元素, 但提供 绘制源 的元素不一定要在文档中。 例如,一个 HTML canvas 元素可以完全用脚本创建、维护和绘制,无需直接插入文档。

只需有办法引用该元素即可, 因为 ID 选择器无法选中文档外元素。 elementSources Map 对象用于此目的。

partial namespace CSS {
  [SameObject] readonly attribute any elementSources;
};
测试

elementSources map 中,任何以字符串为键、值为提供 绘制源 的对象,都可以被 element() 函数引用。

每当 element() 使用 <id-selector> 时, 会先在 elementSources map 中查找该 ID 的值(不含 #):

这样复用 ID 选择器是和 Moz 行为一致的。 不想直接在语法最前面放 <custom-ident>,因为这样占用太多语法空间。 另一种可能是用语言定义的关键字后跟 <custom-ident>, 如 element(external fancy) 之类。 欢迎命名建议。

例如,可以用外部 canvas 实现炫酷动画背景:
<script>
var bg = document.createElement('canvas');
bg.height = 200;
bg.width = 1000;
drawFancyBackground(bg);
CSS.elementSources.set('fancy', bg);
</script>
<style>
h1 {
  background-image: element(#fancy);
}
</style>

随着 "fancy" canvas 绘制和动画变化,所有 H1 元素的背景会自动同步更新。

注意 elementSources map 会在文档查找前被查找, 所以即使文档中也有 #fancy 元素, 背景也会优先取 elementSources 中的值。

2.7.3. 循环检测

element() 函数可能产生无意义的循环关系, 如元素将自身作为自身背景。 但这种关系可以通过依赖图与常见的循环检测算法轻松可靠地检测和解决。

依赖图的边包括:

如果图中存在环路, 参与环路的所有 element() 都视为 无效图片

3. 渐变

渐变是一种图像,其颜色会从一种平滑过渡到另一种。 渐变常用于背景图片、按钮等场景以实现细微阴影效果。 本节描述的 渐变函数 允许作者用简洁语法指定这类图像, 以便 UA 在渲染页面时自动生成图片。 <gradient> 的语法如下:

<gradient> = [
  <linear-gradient()> | <repeating-linear-gradient()> |
  <radial-gradient()> | <repeating-radial-gradient()> |
  <conic-gradient()>  | <repeating-conic-gradient()> ]

和本规范定义的其它 <image> 类型一样, 渐变可用于任何接受图片的属性。 例如:

渐变被绘制在 具体对象尺寸 的盒子中, 称为 渐变盒。 但渐变本身没有 自然尺寸

测试
例如,如果你把渐变用作背景, 默认情况下渐变会绘制在与元素 padding box 大小相同的渐变盒中。 若 background-size 明确设为如 100px 200px, 那么 渐变盒 就是 100px × 200px。 同样,若渐变用于 list-style-image, 盒子会是 1em 的正方形, 即该属性的 默认对象尺寸

定义渐变时需要指定 起点终点,以及 渐变线(视渐变类型可能是线、射线或螺旋), 然后在这条线上指定各点的颜色。 颜色会平滑混合填充整条线, 各类渐变再定义如何利用 渐变线的颜色生成实际渐变。

3.1. 线性渐变:linear-gradient() 记法

本级为 <color-interpolation-method> 参数 加入 linear-gradient()repeating-linear-gradient(), 用于指定渐变线颜色插值的色彩空间与路径。 参见 CSS Color 4 §  12. 色彩插值

<linear-gradient-syntax> =
  [ [ <angle> | <zero> | to <side-or-corner> ] || <color-interpolation-method> ]? ,
  <color-stop-list>
<side-or-corner> = [left | right] || [top | bottom]
测试

3.1.1. 色彩空间对插值的影响:示例

本节为非规范性内容。

色彩空间对插值的影响可能非常显著。

本例中,红色到绿色(#f01 到 #081)的线性渐变 分别在三种色彩空间下绘制。 中间渐变使用 gamma 编码 sRGB, 这是 CSS Images 3 唯一的选择; 结果明显中点太暗。 上方渐变使用 CIE Lab, 得到更贴合人眼感知的效果; 下方渐变使用 Oklab, 在这里与 CIE Lab 几乎一致。

red to green gradient in three colorspaces

本例中,白色到 #01E 的线性渐变 分别在三种色彩空间下绘制。 中间渐变使用 gamma 编码 sRGB, 结果同样中点太暗、略微去饱和且带些紫色调。 上方渐变用 CIE Lab, 避免了中点太暗,但紫色调明显; 下方渐变用 Oklab, 得到更均匀且无紫色调的结果。

white to blue gradient in three colorspaces

本例中,#44C 到 #795 的线性渐变 分别在三种色彩空间下绘制。 这说明 CIE Lab 色相非线性影响所有偏蓝的颜色, 不仅仅是纯蓝到白色渐变。 中间渐变用 gamma sRGB, 结果同样中点太暗且略带紫色调。 上方渐变用 CIE Lab, 避免了中点太暗,但紫色调明显; 下方渐变用 Oklab, 同样更均匀且无紫色调。

blue to green gradient in three colorspaces

为渐变插值选择极坐标色彩空间(而不是直角坐标空间), 可避免颜色标之间色相差距大时的去饱和现象。 在极坐标色彩空间插值本质上能保持色度, 但中间颜色容易超出色域, 这时会做色域映射以回到色域内。

本例中,#A37 到 #595 的线性渐变 分别在五种色彩空间下绘制,其中两种为极坐标空间。 自上而下为:CIE LCH、CIE Lab、sRGB、Oklab、Oklch。

直角空间下的中间色偏灰, 极坐标空间下的中间色则沿着曲线、保持色度。

blue to green gradient in three colorspaces

3.2. 径向渐变:radial-gradient() 记法

3.2.1. 新增 <color-interpolation-method>

本级为 <color-interpolation-method> 参数 加入 radial-gradient()repeating-radial-gradient(), 用于指定渐变线颜色插值的色彩空间与路径。 参见 CSS Color 4 § 12. 色彩插值

<radial-gradient-syntax> =
  [ [ [ <radial-shape> || <radial-size> ]? [ at <position> ]? ] || <color-interpolation-method>]? ,
  <color-stop-list>
测试
本例中,相同颜色 color(display-p3 0.918 0.2 0.161) 和 #081 的径向渐变 在三种色彩空间下绘制。 注意,色标不必全部在同一色彩空间。 中间渐变用 gamma 编码 sRGB, 结果明显中点太暗。 上方渐变用 CIE Lab, 得到更贴合人眼感知的效果; 下方渐变用 Oklab, 结果与 CIE Lab 几乎一致。

red to green gradient in three colorspaces

3.2.2. 扩展 <radial-size>

本级扩展了 <radial-size> 选项, 引入了 circle()ellipse() <basic-shape> 的值:

<radial-size> = <radial-extent>{1,2} | <length-percentage [0,]>{1,2}

circle 作为 <radial-shape> 时,双组件值依然无效, 否则分别表示椭圆的水平半径(第一个)和垂直半径(第二个)。

对于 circle<percentage> 值是相对于 渐变盒宽高的“缩放对角线”计算的:sqrt(width² + height²)/sqrt(2)

3.3. 圆锥渐变:conic-gradient() 记法

圆锥渐变从指定圆心开始,类似于径向渐变, 但圆锥渐变的色标分布在圆周周围,而不是从圆心射出的线段上, 因此颜色会沿圆心旋转平滑过渡,而不是向外扩展。

圆锥渐变通过指定旋转角度、渐变中心和色标列表来定义。 不同于线性和径向渐变用 <length> 指定色标位置, 圆锥渐变的色标用 <angle> 指定。 然后从中心向各方向作射线,每条射线的颜色取其与渐变线相交处的颜色。

注: 这些渐变被称为“圆锥渐变”或“锥形渐变”, 是因为如果色标在某一侧明显较亮,会产生一个看起来像从上方观察的圆锥的图案。 在某些上下文中也叫“角度渐变”, 因为它们是通过改变射线的旋转角度生成的。

[An image showing a box with a background shading gradually clockwise from white to black, starting from the top. A gradient circle is shown, and the colors at 0 and 216 degrees respectively.]

本例直观展示了 conic-gradient(at 25% 30%, white, black 60%) 的绘制方式。注意色标位置始终解析为角度,at 25% 30% 仅影响渐变的二维平移,不影响渐变绘制方式。

3.3.1. conic-gradient() 语法

圆锥渐变的语法如下:

conic-gradient() = conic-gradient( [ <conic-gradient-syntax> ] )
<conic-gradient-syntax> =
  [ [ [ from [ <angle> | <zero> ] ]? [ at <position> ]? ] || <color-interpolation-method> ]? ,
  <angular-color-stop-list>

参数含义如下:

<angle> | <zero>
整个渐变按此角度旋转。 若省略,默认为 0deg。 如果 <angle> 为零,可省略单位标识符。
<position>
决定渐变的渐变中心<position> 类型(也用于 background-position) 定义见 [CSS-VALUES-3], 计算时以中心点为对象区域,以 渐变盒为定位区域。 若省略,默认为 center

圆锥渐变在 0deg 处通常会有明显的色彩跳变,通常通过让首尾色标颜色一致来避免。或许可以加一个自动实现的关键字。

是否有用为渐变裁剪指定半径(内外半径)?若有,则色标位置也可以支持长度,因为有了具体半径。

椭圆形圆锥渐变有用吗?图形库支持吗?

测试

3.3.2. 色标的放置

色标放置在绕 渐变中心 环绕成圆的渐变线上, 0% 和 100% 位置都在 0deg。 与线性渐变类似, 0deg 指向页面顶部, 角度递增则顺时针绕圆转动。

注: 可以把渐变线想象成一条螺旋, 只渲染 0deg 到 360deg 的部分。 这样能避免当角度超出渲染区域时关于“重叠”的困惑。

色标可以放在 0% 之前或 100% 之后的位置; 虽然这些区域不会直接被渲染, 但放在那里的色标仍可通过插值或重复(见 重复渐变)影响渲染区域内的色标颜色。 例如,conic-gradient(red -50%, yellow 150%) 生成的圆锥渐变, 在 0deg 处起始为红橙色(#f50), 到 360deg 变为橙黄色(#fa0)。

渐变某一点的颜色, 首先确定经过该点且以渐变中心为锚点的唯一射线, 然后该点颜色取自该射线与渐变线的交点处的颜色。

3.3.3. 圆锥渐变示例

下列所有 conic-gradient() 示例,除非另有说明,均假设应用于宽 300px、高 200px 的盒子。

下方展示了指定同一基本圆锥渐变的多种写法:
background: conic-gradient(#f06, gold);
background: conic-gradient(at 50% 50%, #f06, gold);
background: conic-gradient(from 0deg, #f06, gold);
background: conic-gradient(from 0deg at center, #f06, gold);
background: conic-gradient(#f06 0%, gold 100%);
background: conic-gradient(#f06 0deg, gold 1turn);

下方展示了指定同一基础圆锥渐变的多种方式。 展示即使色标角度超出 [0deg, 360deg) 区间不直接绘制, 但仍可影响可见部分的颜色。
background: conic-gradient(white -50%, black 150%);
background: conic-gradient(white -180deg, black 540deg);
background: conic-gradient(hsl(0,0%,75%), hsl(0,0%,25%));

下方演示了两种不同写法实现同一个旋转圆锥渐变:一种用旋转角,另一种不用:
background: conic-gradient(from 45deg, white, black, white);
background: conic-gradient(hsl(0,0%,75%), white 45deg, black 225deg, hsl(0,0%,75%));

注意如果把每个色标都加上旋转角, 得到的是完全不同的渐变:

background: conic-gradient(white 45deg, black 225deg, white 405deg);

一个圆锥渐变叠加径向渐变,绘制色相/饱和度圆盘:
background: radial-gradient(closest-side, gray, transparent),
            conic-gradient(red, magenta, blue, aqua, lime, yellow, red);
border-radius: 50%;
width: 200px; height: 200px;

同样效果也可用“longer”色相插值实现,写法更简洁,也方便切换色彩空间:

background: radial-gradient(closest-side, gray, transparent),
            conic-gradient(in hsl longer hue, red 0 100%);
transform: scaleX(-1);
border-radius: 50%;
width: 200px; height: 200px;

color wheel

用圆锥渐变绘制简单饼图。 0deg 的色标位置会被修正为等于前一个色标的位置, 这样不同颜色的色标之间会产生极小(不可见)的过渡, 从而形成纯色分段。
background: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg);
border-radius: 50%;
width: 200px; height: 200px;

3.4. 重复渐变:repeating-linear-gradient()repeating-radial-gradient()repeating-conic-gradient() 记法

除了 linear-gradient()radial-gradient()conic-gradient(), 本规范还定义了 repeating-linear-gradient()repeating-radial-gradient()、 以及 repeating-conic-gradient()。 这些写法接受与其非重复版本相同的参数, 语义也完全一致。

<repeating-conic-gradient()> = repeating-conic-gradient( [ <conic-gradient-syntax> ] )
<repeating-linear-gradient()> = repeating-linear-gradient( [ <linear-gradient-syntax> ] )
<repeating-radial-gradient()> = repeating-radial-gradient( [ <radial-gradient-syntax> ] )
测试
基本的重复圆锥渐变:
background: repeating-conic-gradient(gold, #f06 20deg);

利用突变的重复色标可创建星芒状背景:
background: repeating-conic-gradient(
        hsla(0,0%,100%,.2) 0deg 15deg,
        hsla(0,0%,100%,0) 0deg 30deg
    ) #0ac;

这里用突变的重复色标实现棋盘格:
background: repeating-conic-gradient(black 0deg 25%, white 0deg 50%);
background-size: 60px 60px;

同样的棋盘格也可用非重复圆锥渐变实现:

background: conic-gradient(black 25%, white 0deg 50%, black 0deg 75%, white 0deg);
background-size: 60px 60px;

3.5. 定义渐变颜色

渐变中的颜色通过 色标(即 <color> 和其在渐变线上的位置)以及 颜色过渡提示(即两个 色标之间代表过渡中点的位置) 指定,它们放置在 渐变线上,定义线上的每个点的颜色。 (每个 渐变函数 都定义了 渐变线的形状和长度, 以及其 起点终点;见上文。)

渐变区域的颜色会由渐变函数指定的方式, 与 渐变线上的具体点关联起来。 UA 可以对渐变颜色做轻微抖动(随机将像素用相邻渐变线上的颜色交替渲染),以获得更平滑的渐变。

3.5.1. 色标列表

色标过渡提示 通过 色标列表 指定, 即一个包含一个或多个 色标,中间可插入可选的 过渡提示 的列表:

<color-stop-list> =
  <linear-color-stop> , [ <linear-color-hint>? , <linear-color-stop> ]#?
<linear-color-stop> = <color> <color-stop-length>?
<linear-color-hint> = <length-percentage>
<color-stop-length> = <length-percentage>{1,2}

<angular-color-stop-list> =
  <angular-color-stop> , [ <angular-color-hint>? , <angular-color-stop> ]#?
<angular-color-stop> = <color> <color-stop-angle>?
<angular-color-hint> = <angle-percentage> | <zero>
<color-stop-angle> = [ <angle-percentage> | <zero> ]{1,2}

<color-stop> = <color-stop-length> | <color-stop-angle>
测试
注意,<color-stop-list><angular-color-stop-list> 在结构上完全相同, 只是二者在指定停靠点和提示位置时,一个接受<length>,另一个接受 <angle>

用铁路图表示时, 它们都遵循如下模式:

<color-stop> , <color-hint> , <color-stop> ,

带有两个位置的色标,等价于用相同颜色分别在两个位置各指定一个色标

注: 通常,这会在两个位置间形成一条纯色“带”,但如果使用 longer <color-interpolation-method>,则会在两个位置间形成彩虹渐变。

百分比位置是相对于起点终点之间渐变线的长度来解析的, 0% 对应起点,100% 对应终点。 长度值沿着渐变线起点终点方向测量。

色标过渡提示的位置 通常位于起点终点之间, 但不强制要求如此: 渐变线在两个方向上都是无限延伸的, 位置可以指定在渐变线上的任意点。

色标的位置被省略时, 会自动分配一个位置。 色标列表中的第一个或最后一个色标, 分别被分配到渐变线起点终点。 其它情况下, 会被分配到它前后两个色标位置的中点。 如果有连续多个色标都没有位置, 它们会在相邻有位置的色标之间平均分布。 详情见§ 3.5.3 色标“修正”

3.5.2. 为渐变线着色

在每个色标位置, 渐变线的颜色就是该色标的颜色。 在第一个色标之前, 渐变线的颜色为第一个色标的颜色; 在最后一个色标之后, 渐变线的颜色为最后一个色标的颜色。 在每对色标之间, 渐变线的颜色在两端色标颜色之间插值, 插值过程在指定的色彩空间中进行, 缺失分量的处理见CSS Color 4 § 12.2 缺失分量插值, 色相插值见CSS Color 4 § 12.4 色相插值, 使用预乘 alpha,见CSS Color 4 § 12.3 alpha 插值。 如果渐变函数未指定<color-interpolation-method>, 则渐变插值色彩空间使用默认的 Oklab,定义见[css-color-4]

注: <color-interpolation-method> 只影响色标之间的颜色。 第一个色标之前和最后一个色标之后的颜色等于首/尾色标, 与插值方式无关

测试
例如,给定以下渐变定义:
linear-gradient(in oklch, red, #888, green)

中性灰 #888 转换为 oklch 会得到无色相分量:oklch(0.6268 0 none)

因此,在第一个渐变区段, 色相取自 red, 即 oklch(0.628 0.2577 29.234); 在第二个区段 色相取自 green, 即 oklch(0.5198 0.1769 142.5)

默认情况下, 插值是线性的——在两个色标之间距离的 25%、50%、75% 处, 颜色分别是按 25%、50%、75% 比例混合两端色标的颜色。

但如果在两个色标之间提供了过渡提示, 插值就不是线性的, 而是由提示值控制:

  1. 计算过渡提示在两个色标之间距离中所占百分比, 用 0 到 1 的数字表示, 0 表示提示正好在第一个色标上, 1 表示提示正好在第二个色标上。 记该百分比为 H
  2. 对于两个色标之间的任意一点, 以同样方式计算其在两色标间的百分比, 记为 P
  3. C(该点的颜色权重), 等于 PlogH(.5)
  4. 此点的颜色为两端色标颜色的线性混合, 混合比例为 (1 - C) 用于第一个色标,C 用于第二个色标。

注: 过渡提示指定了“两端色标之间50%混色”的具体位置。 当提示正好位于两端色标中点时, 上述插值算法就等价于普通线性插值。 如果提示在别的位置, 则在两端色标间形成平滑的指数曲线, 且“半混色”正好出现在提示指定的位置。

下面是带和不带过渡提示的线性渐变对比示例(上方无提示,下方红蓝色标间有提示)。

上 - 无过渡提示(退回默认中点过渡):

background: linear-gradient(to right, red 0%, blue 100%);

下 - 有过渡提示:

background: linear-gradient(to right, red 0%, 25%, blue 100%);

如果多个色标位置相同, 渲染时会从列表中靠前的色标瞬间过渡到最后一个色标。 实际上该位置的颜色会突变,而不是平滑过渡。

3.5.3. 色标“修正”

在解析每个已用色标位置时, 必须按顺序执行以下步骤:

  1. 如果第一个色标没有位置, 则将其位置设为 0%。
  2. 如果最后一个色标没有位置, 则将其位置设为 100%。
  3. 如果某个色标过渡提示的位置 小于其前面列表中任何色标过渡提示的已指定位置, 则将其位置设为前面所有色标过渡提示中已指定位置的最大值。
  4. 如果仍有色标没有位置, 则对于每一段连续的无位置色标, 将它们均匀分布在前后已指定位置的色标之间。

应用这些规则后, 所有色标过渡提示都将有确定的位置和颜色, 并且它们会按升序排列。

测试

注: 建议作者在混合不同单位(如 px、em 或 %)时谨慎, 否则可能导致色标意外跑到前一个色标之前。 例如, 规则background-image: linear-gradient(yellow 100px, blue 50%) 在背景区高度至少为200px时不会触发修正。 如果高度为150px, 那么 blue色标位置等价于75px, 这会在 yellow色标之前, 并会被修正为100px。 此外,色标的相对顺序只有在布局完成后才能确定, 因此在动画过渡中不会平滑地插值。

下方是几组渐变对比。 每组后一项是对前一项手动“修正”后的结果, 按上述规则修正获得。 每一对的渲染效果是一样的。箭头上的数字表示转换中调用了哪些修正步骤。
1. linear-gradient(red, white 20%, blue)
   =1=>
   linear-gradient(red 0%, white 20%, blue 100%)

2. linear-gradient(red 40%, white, black, blue)
   =1,3=>
   linear-gradient(red 40%, white 60%, black 80%, blue 100%)

3. linear-gradient(red -50%, white, blue)
   =1,3=>
   linear-gradient(red -50%, white 25%, blue 100%)

4. linear-gradient(red -50px, white, blue)
   =1,3=>
   linear-gradient(red -50px, white calc(-25px + 50%), blue 100%)

5. linear-gradient(red 20px, white 0px, blue 40px)
   =2=>
   linear-gradient(red 20px, white 20px, blue 40px)

6. linear-gradient(red, white -50%, black 150%, blue)
   =1,2=>
   linear-gradient(red 0%, white 0%, black 150%, blue 150%)

7. linear-gradient(red 80px, white 0px, black, blue 100px)
   =2,3=>
   linear-gradient(red 80px, white 80px, black 90px, blue 100px)

4. 一维图像值:<image-1D> 类型与 stripes() 记法

虽然 <image> 值代表二维(2D)图片, <color> 可视为零维(0D)图片 (在任意轴上都不变化), 但某些场景需要一种一维(1D)图片, 用于沿某个抽象、无方向的单轴绘制线指定颜色。 <image-1D> 类型即表示此类一维图片, 包括 stripes() 函数记法

<image-1D> = <stripes()>
<stripes()> = stripes( <color-stripe># )
<color-stripe> = <color> && [ <length-percentage> | <flex> ]?

stripes() 函数将一维图片定义为一个用逗号分隔的彩色条带列表, 每个条带按顺序首尾相接地排列在绘制线上。

每个 <color-stripe> 项定义了一个指定<color>和厚度的纯色条带。 若省略厚度,则默认为 1fr。 厚度值的解释如下:

<percentage [0,100]>
百分比厚度相对于 total width,仅允许 0%100%(含)。
<length [0,∞]>
负长度值无效。
<flex>
<flex> 作为 total width 的一部分进行分配,分配比例为函数中所有 <flex> 项的总和, 先减去所有非 <flex> 项的厚度后(减法结果若小于 0 则取 0)。 如果 <flex> 值之和小于 1fr, 则剩余空间会乘以总和后再分配。

total widthstripes() 函数的使用场景决定。 如果所有条带之和小于 total width, 剩余的 绘制线部分为透明黑,等价于最后有个 transparent 参数。 若总和大于 total width,则超出的条带或部分会被截断。

例如,stripes(red 1fr, green 2fr, blue 100px)total width400px 时, 会得到 100px 的红色条带和 200px 的绿色条带, 红色占 1 份,绿色占 2 份,剩余 300px(400px 扣掉蓝色 100px)按 1:2 分配。

反之,stripes(red .1fr, green .2fr, blue 100px)total width400px 时,会得到 30px 红条带、60px 绿条带, 后面是 100px 蓝色,再加 210px 透明。 300px 剩余空间乘以 .3(flex 总和)只剩 90px,按 1:2 比例分配给红绿。

(这和 flex 布局处理一行上很小的 <flex> 总和的方式类似, 可以保证 <flex> 取零时行为连续、平滑。)

该函数的计算值为条带的有序列表, 每一项为计算色和厚度,厚度类型为<flex> 或计算后的<length-percentage>

5. CSS 中图片与对象的尺寸控制

5.1. 对象尺寸控制:object-fit 属性

名称: object-fit
取值: fill | none | [contain | cover] || scale-down
初始值: fill
适用元素: 替换元素
是否继承:
百分比: 不适用
计算值: 所指定的关键字
语法顺序: 依照语法
动画类型: 离散

object-fit 属性指定替换元素内容如何适配其已用高度与宽度所建立的盒子。

fill
替换内容被拉伸以填满元素的内容盒: 对象的具体对象尺寸等于元素的已用宽高。
none
替换内容不会缩放以适应元素的内容盒: 对象的具体对象尺寸通过默认尺寸算法计算(无指定尺寸), 且默认对象尺寸等于该替换元素的已用宽高。
contain
替换内容缩放时保持宽高比,同时适应元素内容盒: 它的具体对象尺寸会作为contain 约束,以元素的已用宽高为参考计算。

如果使用 scale-down 标志,则内容尺寸采用 nonecontain, 取其中更小的具体对象尺寸

注: nonecontain 都会尊重内容的自然宽高比, 因此“更小”是有定义的。

cover
替换内容缩放时保持宽高比,同时填满整个元素内容盒: 它的具体对象尺寸会作为cover 约束,以元素的已用宽高为参考计算。

如果使用 scale-down 标志,则内容尺寸采用 nonecover, 取其中更小的具体对象尺寸

注: nonecover 都会尊重内容的自然宽高比, 因此“更小”是有定义的。

scale-down
等价于 contain scale-down
测试

如果内容没有完全填满替换元素的内容盒,未填满的区域会显示替换元素的背景。 由于替换元素总是将其内容裁剪到内容盒内,所以内容绝不会溢出。 关于如何在内容盒内定位对象,请参见 object-position 属性。

该示例展示了 object-fit 的四种取值如何让替换元素(蓝色图形) 缩放以适应其高/宽盒子(绿色背景), 并使用 object-position 的初始值。 在本例中,scale-downscale-down contain 效果与 contain 完全相同, scale-down cover 效果与 none 完全相同。

注: object-fit 属性与 [SMIL10] 中的 fit 属性、 以及 preserveAspectRatio 属性[SVG11])上的 <meetOrSlice> 参数语义类似。

注: 根据 对象尺寸协商 算法, 具体对象尺寸(或本例中的内容尺寸)并不会直接缩放对象本身—— 它只是作为可见画布尺寸的信息传递给对象。 最终如何绘制由图片格式决定。 特别是,位图图片总是缩放到指定尺寸, 而 SVG 则将该尺寸作为“SVG 视口”(SVG 定义的术语), 再根据根 <svg> 元素上的若干属性决定如何绘制自身。

6. 图像处理

6.1. 覆盖图像分辨率:image-resolution 属性

图像分辨率被定义为 每单位长度的图像像素数, 例如每英寸像素数。 一些图像格式可以记录分辨率信息, 这有助于在排版过程中确定图像实际尺寸。 但这些信息也可能是错误的,此时应忽略。 默认情况下,CSS 假定图像分辨率为每个 CSS px 单位对应一个图像像素; 但 image-resolution 属性允许使用其他分辨率。

名称: image-resolution
取值: [ from-image || <resolution> ] && snap?
初始值: 1dppx
适用元素: 所有元素
是否继承:
百分比: 不适用
计算值: 指定的关键字和/或 <resolution>(可能因 snap 被调整,见下文)
语法顺序: 依照语法
动画类型: 离散

image-set() 记法可能会改变图片的自然分辨率, 理想情况下应自动识别而无需设置该属性。 我们该如何最好地处理?把初始值改为 auto,表示“1dppx,除非 CSS 另有说明”? 还是规定 image-resolution 对由 CSS 其他方式设置分辨率的图片无效? 还是在 image-set() 中直接规定所有图片都为 1dppx

image-resolution 属性用于指定元素中所有光栅图片的首选分辨率。 它影响内容图片(如替换元素和生成内容)和装饰图片(如 background-image)。 图片的首选分辨率用于确定图片的自然尺寸。 各取值含义如下:

<resolution>
明确指定首选分辨率。 这里的“点”指单个图像像素。
from-image
图片的首选分辨率取自图片格式声明 (自然分辨率)。 如果图片未指定自身分辨率,则采用显式分辨率(若有),否则默认 1dppx

注: CSS Images 3 § 2.1.2 图片元数据 对可用元数据做了限制。

snap
如果提供了 "snap" 关键字, 则计算的 <resolution>(如有) 会被调整为最接近的整数,使得一个图像像素能映射为整数个设备像素。 如果分辨率取自图片,则使用的自然分辨率同样会做此调整。

如 SVG 等矢量格式没有自然分辨率, 本属性对矢量图片无效。

打印机分辨率通常远高于显示器; 因此,在屏幕上看起来很清晰的图片打印出来可能会很模糊。 image-resolution 属性可用于在文档中嵌入高分辨率图片, 并保持合适的尺寸, 实现屏幕和纸张上都美观的显示:
img.high-res {
  image-resolution: 300dpi;
}

这样设置后,一张标称300dpi、宽5英寸的图片会实际以5英寸宽显示; 如果不设置该属性, 图片会显示为约15.6英寸宽, 因为图片像素宽15000,CSS 默认每英寸96像素。

有些图片格式可以将分辨率编码进图片数据中。 这条规则指定 UA 应采用图片自身分辨率, 若图片无分辨率,则每个 CSS px 对应1图像像素。
img { image-resolution: from-image }

下面两条规则都指定 UA 采用图片分辨率, 但若图片本身无分辨率,则采用 300dpi,而不是默认的 1dppx

img { image-resolution: from-image 300dpi }
img { image-resolution: 300dpi from-image }
使用此规则,图片分辨率被设置为 300dpi。 (图片内分辨率会被忽略。)
img { image-resolution: 300dpi }

而这条规则若在屏幕分辨率为 96dpi 时使用, 图片将以 288dpi 渲染 (即 3 个图片像素映射为 1 个设备像素):

img { image-resolution: 300dpi snap; }

snap 关键字也可和图片分辨率联用:

img { image-resolution: snap from-image; }

一张标称 300dpi 的图片在上述场景下显示为 288dpi (3 图片像素对 1 设备像素), 而标称 72dpi 的图片则以 96dpi 渲染 (1 图片像素对 1 设备像素)。

7. 插值

本节描述了本规范中新引入的值类型的插值方法, 以便于 CSS 过渡(Transitions)和动画(Animations)等模块使用。

如果下列算法仅说明两个值应“插值”或“过渡”,未给出细节, 则应按 Transitions 规范描述的方式插值。 否则,算法可能在详细描述中引用变量 t。 该变量从 0% 到 100%, 表示过渡进度, 其值由过渡持续时间、已过时间和所用时间函数确定。 例如,线性时间函数,持续 1s 时, 经过 0.3s,t 等于 30%。

7.1. 图像的插值 <image>

所有图像都可以插值, 但某些特殊类型的图像 (如某些渐变) 有其专门的插值规则。 通常, 图像插值的方式是将其缩放到起始图像的尺寸,并在过渡到结束图像的尺寸时做交叉淡入淡出。

具体来说, 插值过程中的每一时刻, 图像相当于 cross-fade( (100% - t) start image, end image)

特殊情况:插值到/从无图像(如 "background-image: url(foo);" 到 "background-image: none;")。

7.2. cross-fade() 的插值

cross-fade() 的三个分量独立插值。 注意这可能导致嵌套的 cross-fade() 记法。

7.3. 渐变的插值 <gradient>

本节有待进一步审查和完善。 尤其是 linear-gradient() 的处理不完整——我们希望明确插值渐变线(0% 到 100% 间距离)的“长度”, 以避免动画期间先变长后变短。

渐变图像可以在 CSS 过渡和动画中直接插值, 可以平滑地从一个渐变动画到另一个渐变。 允许插值的渐变有如下限制:

  1. 起始和结束渐变必须用同一个函数表示。 (例如,可以从 linear-gradient() 过渡到 linear-gradient(), 但不能从 linear-gradient() 过渡到 radial-gradient()repeating-linear-gradient()。)

  2. 起始和结束渐变必须有相同数量的 <color-stop>。 对于该目的,所有重复渐变视为有无限色标, 因此所有重复渐变都满足这一点。

  3. 渐变中不得混用<length><percentage>色标。

若两个渐变满足以上所有约束, 则应按下述方式插值。 若仅第三条不满足, 则在 50% 时突变(除非未来规范另有规定)。 若前两条任一不满足, 则应像一般图像那样用 cross-fade() 插值。

注: 50% 的突变是为了避免内容依赖交叉淡入淡出, 未来可为此情况增加更智能的插值规则。

  1. 将起始和结束渐变都转换为显式形式:

    线性渐变:
    • 若方向已用<angle>指定, 则已为显式形式。

    • 否则, 将方向换算为区间 [0deg,360deg) 的 <angle>,保证渲染等价。

      若起止渐变都用关键字指定方向, 且两方向对应的角度差大于 180deg, 则给角度较小的渐变方向加 360deg。这样可确保从 "to left" (270deg) 到 "to top" (0deg) 是顺时针转 1/4 圈, 而不是逆时针转 3/4 圈。

    径向渐变:
  2. 各分量和色标独立插值。 线性渐变分量只有角度。 径向渐变分量有中心的水平、垂直坐标和主轴/副轴长度。

  3. 插值色标时, 先将起始和结束渐变的每个色标一一配对(索引相同)。 对于重复渐变, 起始和结束渐变的第一个指定色标视为同一索引, 其余色标按顺序配对,多余部分循环和移位。 然后对每对色标分别插值位置和颜色。

7.4. stripes() 的插值 stripes()

类似渐变, 两个 stripes() 可以插值, 允许两张图片之间平滑动画。 stripes() 插值仅有如下限制:

  1. 起始和结束图片的 <color-stripe> 数量必须一致。

  2. 每对插值厚度类型必须相同, 即都为 <length-percentage>,或都为 <flex>

如两个图片满足这两条,则按下述方式插值。 若仅第二条不满足,则在 50% 时突变(除非未来规范另有说明)。 若第一条不满足,则用 cross-fade()(通用图片插值方式)。

注: 50% 突变是为了避免依赖交叉淡入淡出, 未来可为此情况增加更智能的插值规则。

  1. 各分量和条带独立插值。

  2. 插值条带时, 先将起始图片的每个条带与结束图片同索引条带配对, 然后每对条带分别插值厚度和颜色。

8. 序列化

本节描述了本规范引入的所有新属性和值类型的序列化方法, 以便与 CSS 对象模型 [CSSOM] 交互。

序列化本模块定义的任意函数时, 按其语法顺序序列化, 能省略的部分省略(不改变含义), 空格分隔的 token 用单空格连接, 每个序列化逗号后跟一个空格。

对于 cross-fade(), 始终要序列化 <percentage>

例如,以下渐变声明:
Linear-Gradient( to bottom, red 0%,yellow,black 100px)

应序列化为:

linear-gradient(rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 0, 0) 100px)

附录A:废弃特性与别名

实现必须接受 -webkit-image-set() 作为 image-set() 的解析时别名。 (它是有效值,参数与 image-set() 完全一致, 解析时会转为 image-set()。)

9. 隐私考量

注:[css-images-3] 无变化。

10. 安全考量

注:[css-images-3] 无变化。

11. 变更记录

2023年2月17日 工作草案以来的变更

2017年4月13日工作草案以来的变更

2012年9月11日工作草案以来的变更

Level 3 以来的变更

一致性

文档惯例

一致性要求通过描述性断言和 RFC 2119 术语结合表达。规范部分中的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”、“OPTIONAL”应按 RFC 2119 解释。 但为可读性,本规范未用全大写。

本规范所有文字均为规范性内容,除明确标记为非规范性、示例和注释的部分外。[RFC2119]

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

这是一个说明性示例。

说明性注释以“注”开头,并用 class="note" 区分,如下所示:

注,这是一个说明性注释。

告示(advisement)是强调的规范性段落,用 <strong class="advisement"> 区分,如下所示: UA 必须提供可访问性替代方案。

测试

与本规范内容相关的测试可在类似本区块的“测试”块中记录。 这些区块均为非规范性内容。


一致性类别

本规范的一致性定义了三类对象:

样式表
CSS 样式表
渲染器
UA,即解释样式表语义并渲染 使用它们的文档的用户代理。
创作工具
UA,即生成样式表的工具。

如果样式表中使用本模块定义语法的所有声明均符合通用 CSS 语法及本模块各特性的语法,样式表即符合本规范。

渲染器若能按相应规范解释样式表,且能解析本规范定义的所有特性并正确渲染文档,即为符合本规范。但因设备限制不能正确渲染文档不视为不合规。(例如,UA 不要求在黑白显示器上渲染颜色。)

创作工具如能生成语法正确的样式表且符合本模块及所有一致性要求,则为符合本规范。

部分实现

为便于作者利用向前兼容解析规则指定后备值,CSS 渲染器必须将不支持的 at 规则、属性、属性值、关键字及其他语法结构视为无效(并适当忽略)。尤其是,用户代理不得在单个多值属性声明中有选择性地忽略不支持的分量并保留支持的分量:如任何值被视为无效,CSS 要求整个声明被忽略。

非稳定和专有特性的实现

为避免与未来稳定的 CSS 特性冲突,CSSWG 建议遵循最佳实践实现不稳定特性及专有扩展

非实验性实现

一旦规范进入候选推荐(CR)阶段,就可进行非实验性实现,且实现者应发布已正确实现并通过规范验证的 CR 级特性的无前缀实现。

为确保各实现间 CSS 的互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布无前缀实现前向 W3C 提交实现报告(如有必要,还需提交测试用例)。提交给 W3C 的测试用例将由 CSS 工作组审查和修正。

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

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS 背景与边框模块 3 级。2024年3月11日。CRD。URL: https://www.w3.org/TR/css-backgrounds-3/
[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]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS 颜色模块 4 级。2025年4月24日。CRD。URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; 等。CSS 颜色模块 5 级。2025年3月18日。WD。URL: https://www.w3.org/TR/css-color-5/
[CSS-GRID-2]
Tab Atkins Jr.; 等。CSS 网格布局模块 2 级。2025年3月26日。CRD。URL: https://www.w3.org/TR/css-grid-2/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS 图像模块 3 级。2023年12月18日。CRD。URL: https://www.w3.org/TR/css-images-3/
[CSS-IMAGES-4]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS 图像模块 4 级。2023年2月17日。WD。URL: https://www.w3.org/TR/css-images-4/
[CSS-IMAGES-5]
CSS 图像模块 5 级。编辑草案。URL: https://drafts.csswg.org/css-images-5/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.. CSS 列表与计数器模块 3 级。2020年11月17日。WD。URL: https://www.w3.org/TR/css-lists-3/
[CSS-SHAPES-1]
Alan Stearns; Rossen Atanassov; Noam Rosenthal. CSS 形状模块 1 级。2025年6月12日。CRD。URL: https://www.w3.org/TR/css-shapes-1/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS 盒模型尺寸模块 3 级。2021年12月17日。WD。URL: https://www.w3.org/TR/css-sizing-3/
[CSS-UI-4]
Florian Rivoal. CSS 基本用户界面模块 4 级。2021年3月16日。WD。URL: https://www.w3.org/TR/css-ui-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-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS 值与单位模块 5 级。2024年11月11日。WD。URL: https://www.w3.org/TR/css-values-5/
[CSS2]
Bert Bos; 等。层叠样式表 2 级修订版(CSS 2.1)规范。2011年6月7日。REC。URL: https://www.w3.org/TR/CSS2/
[CSS3-TRANSFORMS]
Simon Fraser; 等。CSS 变换模块 1 级。2019年2月14日。CR。URL: https://www.w3.org/TR/css-transforms-1/
[CSSOM]
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/
[HTML]
Anne van Kesteren; 等。HTML 标准。现行标准。URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准。现行标准。URL: https://infra.spec.whatwg.org/
[MEDIA-FRAGS]
Raphaël Troncy; 等。Media Fragments URI 1.0(基础)。2012年9月25日。REC。URL: https://www.w3.org/TR/media-frags/
[MIMESNIFF]
Gordon P. Hemsley. MIME 嗅探标准。现行标准。URL: https://mimesniff.spec.whatwg.org/
[PNG]
Chris Lilley; 等。可移植网络图形(PNG)规范(第三版)。2025年6月24日。REC。URL: https://www.w3.org/TR/png-3/
[RFC2119]
S. Bradner. RFC中用于指示需求级别的关键词。1997年3月。最佳当前实践。URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECT]
Tantek Çelik; 等。选择器 3 级。2018年11月6日。REC。URL: https://www.w3.org/TR/selectors-3/
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器 4 级。2022年11月11日。WD。URL: https://www.w3.org/TR/selectors-4/
[SVG-INTEGRATION]
Cameron McCormack; Doug Schepers; Dirk Schulze. SVG 集成。2014年4月17日。FPWD。URL: https://www.w3.org/TR/svg-integration/
[SVG11]
Erik Dahlström; 等。可缩放矢量图形(SVG)1.1(第二版)。2011年8月16日。REC。URL: https://www.w3.org/TR/SVG11/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准。现行标准。URL: https://webidl.spec.whatwg.org/

参考性引用

[CSS-FLEXBOX-1]
Tab Atkins Jr.; 等。CSS 弹性盒布局模块 1 级。2018年11月19日。CR。URL: https://www.w3.org/TR/css-flexbox-1/
[SMIL10]
Philipp Hoschka. 同步多媒体集成语言(SMIL)1.0 规范。1998年6月15日。REC。URL: https://www.w3.org/TR/1998/REC-smil-19980615/

属性索引

名称 取值 初始值 适用元素 继承 %百分比 动画类型 语法顺序 计算值
image-resolution [ from-image || <resolution> ] && snap? 1dppx 所有元素 不适用 离散 依语法 指定关键字和/或 <resolution>(可能因 snap 被调整,见下文)
object-fit fill | none | [contain | cover] || scale-down fill 替换元素 不适用 离散 依语法 指定关键字

IDL 索引

partial namespace CSS {
  [SameObject] readonly attribute any elementSources;
};

问题索引

该方案假设分辨率就是文件大小的代理,因此无法妥善处理多分辨率的矢量图像集,或者矢量图像和位图(如图标)混用的情况。 例如,高分辨率用矢量,低分辨率用像素优化位图,低带宽下再用矢量(虽然分辨率高但体积小)。
建议增加 "w" 和 "h" 尺寸参数,以匹配 HTML 的 picture 元素的功能。
根据工作组决议,需定义图像的“相等性”概念,并在计算值阶段合并“相同”图像,百分比相加。
按工作组决议,计算值阶段应简化直接嵌套的 cross-fade(),通过分配百分比并展平结构;cross-fade(A 10%, cross-fade(B 30%, C 70%) 90%) 会变成 cross-fade(A 10%, B 27%, C 63%)
是否需要支持引用外部文档中的元素(如 SVG paint server)?还是用 url() 已足够?
此名称与 GCPM 中的某个类似函数冲突,需要想办法解决。
期望能对元素做“镜像”处理,无论作为该元素的 background-image,还是在伪元素中。需要特殊处理以避免触发循环检测。
当 overflow:paged 时,如何只针对单页视图?
元素要求具备一定的 stacking context 似乎对高效实现是必要的。 我们需要完整 stacking context,还是伪 stacking context? 是始终需要 stacking context,还是渲染到 element() 时再当作 stacking context?
这种 ID 选择器复用方式与 Moz 行为一致。为避免在语法首部直接放一个 <custom-ident> 占用太多语法空间, 还可以考虑以语言关键字开头,后接 <custom-ident>, 比如 element(external fancy) 之类。欢迎命名建议。
圆锥渐变中通常不希望 0deg 处有突变,通常通过首尾色标颜色相同来避免。或许可以考虑增加一个关键字自动实现这一点。
剪裁渐变时若有(内、外)半径会有用吗?如此一来,色标位置也可以支持长度单位,因为现在有了具体半径。
椭圆形圆锥渐变有实际用途吗?图形库支持吗?
image-set() 记法会改变图像的 自然分辨率,理想情况下应自动识别,无需手动设置属性。 我们该如何处理?把初始值改为 auto (表示“1dppx,除非 CSS 另有说明”)?还是规定 image-resolution 对已被 CSS 其他方式设置分辨率的图像无效?还是直接规定 image-set() 始终产出 1dppx 图像?
插值时遇到无图像的特殊情况,例如 "background-image: url(foo);" 到 "background-image: none;"。
本节有待进一步完善。尤其是 linear-gradient() 的插值处理不完整——我们实际上应当明确插值渐变线(0% 到 100% 间距离)的“长度”, 在动画期间避免先变长后变短。
CanIUse

Support:Android BrowserNoneBaidu BrowserNoneBlackberry BrowserNoneChromeNoneChrome for AndroidNoneEdgeNoneFirefoxNoneFirefox for AndroidNoneIENoneIE MobileNoneKaiOS BrowserNoneOperaNoneOpera MiniNoneOpera MobileNoneQQ BrowserNoneSafari10+Safari on iOS10.0+Samsung InternetNoneUC Browser for AndroidNone

Source: caniuse.com as of 2025-09-16

CanIUse

Support:Android BrowserNoneBaidu BrowserNoneBlackberry BrowserNoneChromeNoneChrome for AndroidNoneEdgeNoneFirefoxNoneFirefox for AndroidNoneIENoneIE MobileNoneKaiOS BrowserNoneOperaNoneOpera MiniNoneOpera MobileNoneQQ BrowserNoneSafariNoneSafari on iOSNoneSamsung InternetNoneUC Browser for AndroidNone

Source: caniuse.com as of 2025-09-16