CSS 锚点定位模块 第1级

W3C 工作草案,

关于本文档的更多详情
此版本:
https://www.w3.org/TR/2026/WD-css-anchor-position-1-20260130/
最新发布版本:
https://www.w3.org/TR/css-anchor-position-1/
编辑草案:
https://drafts.csswg.org/css-anchor-position-1/
历史记录:
https://www.w3.org/standards/history/css-anchor-position-1/
反馈意见:
CSSWG 问题仓库
规范内反馈
编辑者:
Tab Atkins-Bittner (Google)
Elika J. Etemad / fantasai (Apple)
Ian Kilpatrick (Google)
前任编辑:
Jhey Tompkins (Google)
为本规范建议修订:
GitHub 编辑器

摘要

本规范定义了锚点定位, 允许一个定位元素可以根据页面上的一个或多个“锚点元素”来设置自己的尺寸和位置。

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

文档状态

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

本文档由 CSS 工作组 按照 推荐标准流程 作为工作草案发布。 工作草案的发布并不意味着 W3C 及其成员的认可。

本文件为草案,可能随时被更新、替换或废止。 不应将本文档引用为除“进行中工作”之外的其他用途。

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

本文件遵循 2025年8月18日 W3C 流程文档

本文件由遵循 W3C 专利政策的工作组产生。 W3C 维护着 该组相关专利披露的公开列表; 该页面也包含披露专利的说明。 任何个人若实际知晓某项专利且认为该专利包含必要权利要求, 必须依照 W3C 专利政策第6节进行披露。

1. 介绍

CSS 绝对定位允许作者将盒子放置在页面上的任意位置, 并不考虑除其包含块之外其他盒子的布局。 这种灵活性非常有用, 但也有局限——很多时候你希望相对于某个其他盒子进行定位。 锚点定位 (通过 position-anchorposition-area 属性 以及/或者 anchor 函数 anchor()anchor-size()) 让作者能够实现这一点, 即将一个绝对定位盒子“锚定”到页面上的一个或多个其他盒子 (它的锚点引用), 同时也允许尝试多个可能的位置, 以找到能够避免重叠/溢出的“最佳”位置。

例如,作者可能希望将工具提示定位在目标元素正上方且居中, 除非这会导致工具提示超出屏幕, 这种情况下应将其显示在目标元素下方。 这可以用以下 CSS 实现:
.anchor {
  anchor-name: --tooltip;
}
.tooltip {
  /* Fixpos 意味着我们不需要考虑包含块的关系;
     工具提示可以存在于 DOM 的任何地方。 */
  position: fixed;

  /* 所有锚定行为默认都会引用 --tooltip 锚点。 */
  position-anchor: --tooltip;

  /* 让工具提示的底部对齐到锚点顶部;
     这也会默认使工具提示和锚点(在水平方向的书写模式下)水平居中对齐。 */
  position-area: block-start;

  /* 如果工具提示溢出窗口则会自动切换,
     使其顶部对齐到锚点底部。 */
  position-try: flip-block;

  /* 防止过宽 */
  max-inline-size: 20em;
}

注意,使用 Popover API 会自动设置 position 并建立锚定关系, 而无需再设置 anchor-nameposition-anchor 的值 (通过定义隐式锚点元素), 因此这些属性无需显式再次设置。 如果使用正确的标记,这个例子可以简化为:

.tooltip {
  /* 使用 popover + popovertarget 属性会设置 'position: fixed',
     并已自动建立所需的 position-anchor 关系。 */
  position-area: block-start;
  position-try: flip-block;
  max-inline-size: 20em;
}

1.1. 值定义

本规范遵循 CSS 属性定义约定 (见 [CSS2]), 并采用 值定义语法 (见 [CSS-VALUES-3])。 未在本规范定义的值类型,可参见 CSS 值与单位 [CSS-VALUES-3] 规范。 与其它 CSS 模块结合时可能会扩展这些值类型的定义。

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

如同 CSS 中除选择器匹配以外的大多数操作, 本规范特性在 扁平元素树 上起效。

2. 锚点的确定

本规范的多个特性都涉及 锚点框 的位置与尺寸。 除非另有说明, 此处指相关 边框盒 边界,即相关 主盒锚点元素。 在多数情况下,相关的 锚点元素 通过 默认锚点元素position-anchor 属性指定, 该属性可指向主机语言定义的 隐式锚点元素, 或由 CSS anchor-nameanchor-scope 属性命名的锚点。 (anchor() 函数也可直接引用命名锚点。)

锚点框 的位置和尺寸在布局完成后确定。 此位置和尺寸包含 缩放定位相关的调整 (如 position: relativeposition: sticky), 也包括变换(如 transformoffset-path)。 此类情况下,锚点框绝对定位 元素的 包含块 坐标空间中的轴对齐边界矩形将被采用。 由于变换通常会在不同的线程上优化执行, 因此基于变换的 锚点框 位置更新 可能会延迟几帧。 作者可以在可行情况下用绝对或相对定位来避免该延迟。

如果 锚点框分片, 且引用该 锚点框绝对定位 盒的 包含块 在相关 分片上下文 外部, 将采用其 盒片段 的轴对齐包围矩形。 (如果 绝对定位 盒本身位于 分片上下文 内, 它视 锚点框 为未分片——并且本身可能被 分片上下文 分片。)

出于性能原因, 滚动会被特殊处理,详见 § 3.3 考虑滚动因素。 其它布局后效果(如滤镜) 不会影响 锚点框 的位置。

2.1. 创建锚点:anchor-name 属性

名称: anchor-name
取值: none | <anchor-name>#
初始值: none
适用元素: 所有生成 主框 的元素
继承性: no
百分比: n/a
计算值: 按指定值
规范顺序: 依语法
动画类型: 离散型
<anchor-name> = <dashed-ident>

anchor-name 属性声明 元素为一个锚元素, 其 主框 为一个 锚框, 并赋予其要被定位的 锚名称 列表。 取值定义如下:

none

该属性无效。

<anchor-name>#

若元素生成了一个 主框, 该元素为 锚元素, 并拥有所指定的 锚名称 列表。 每个 锚名称 都是一个 宽松匹配树域名

否则,该属性无效。

锚名称 不要求唯一。 并非所有元素都能成为 某个盒子的 目标锚元素。 因此如果作用域合适,某个名称可以复用在不同地方。

注: 如果多个元素共享同一个 锚名称, 且都对某个定位盒可见, 则 目标锚元素 为最近的祖先(如存在) 否则为 DOM 顺序里的最后一个。 可用 anchor-scope 属性进一步限制 某个引用盒可见的名称。

锚名称 默认不会包含 作用域限制; 即使元素有 样式布局包含 (或类似的包含方式), 其后代的 锚名称 依然对页面其他元素可见。

注: 当一个元素位于另一个元素的 跳过内容内 (例如由于content-visibility: hidden), 该元素不会成为可接受的锚元素, 实际上相当于没有任何名称。

注: Shadow DOM 树内的定位元素 可以引用更高层树定义的 锚名称。 当前还不能引用“更低层” shadow 树里的 锚名称

2.2. 限定锚点名称作用域:anchor-scope 属性

名称: anchor-scope
取值: none | all | <anchor-name>#
初始值: none
适用元素: 所有元素
继承性: no
百分比: n/a
计算值: 与指定相同
规范顺序: 遵循语法
动画类型: 离散型

该属性将指定的 锚点名称 及其查找限制在此元素的子树内。 见 § 2 锚点的确定

值含义如下:

none
锚名称 的作用域无变化。
all
指定由该元素或其后代定义的所有 锚名称 (只要其作用域未被后代通过 anchor-scope 限制)都只对该元素的后代可见; 并且限定后代只能匹配该子树内 锚名称锚元素

该值仅影响同一树作用域内的 锚名称, 就像是 严格匹配树域名。 (也就是说,anchor-scope: all 的效果等同于 anchor-scope: --foo, --bar, ..., 即列出所有相关的 锚名称。)

<anchor-name>
指定由该元素或其后代定义的匹配 锚名称 (只要其作用域未被后代通过 anchor-scope 限制)只对该元素的后代可见; 并限定后代只能匹配这些 锚名称锚元素 (在此子树内)。

<anchor-name> 表示一个 严格匹配树域名, 即只能与同一 shadow tree 里的 锚名称 匹配。[CSS-SCOPING-1]

该属性对隐式锚元素无效。

注: 由于会首先检查定位元素的祖先, 如果目标锚点就是祖先,通常无需设置 anchor-scope。 只有当目标锚点不是祖先, 或者你想有意“隐藏”一个锚点 不让页面其他位置引用时才需要使用。

当复用设计模式时, anchor-scope 可以防止相同组件间名称冲突。 例如,如果一个列表每项都包含了绝对定位元素, 且希望它们相对于各自的列表项定位,
li {
  anchor-name: --list-item;
  anchor-scope: --list-item;
}
li .positioned {
  position: absolute;
  position-anchor: --list-item;
  position-area: inline-start;
}

如果没有 anchor-scope, 所有 li 元素对于所有绝对定位元素都是可见的, 所以它们都会相对于最后一个 li定位, 堆叠在一起。

上例需修正,该用例现已自动实现。

2.3. 查找锚点

本规范中的若干内容, 会根据一个 目标锚元素, 和一个 锚点指示符 来定位。 锚点指示符可以是 <dashed-ident> (同时也是 树域引用), 用于与页面其它地方 anchor-name 的值匹配; 或关键字 auto, 或没有(指示符为空)。

注: 这些条件概括出的普遍规则是, 一个元素只有在其自身的盒已完全布局完成, 且要引用它的定位盒尚未布局时, 才能成为该定位盒的目标锚元素。 CSS 的布局规则对此提供了有用的保证, 取决于锚元素、定位元素以及它们各自的包含块之间的关系。 下列条件的列表 精确地将层叠上下文的规则 转化为与此目的直接相关的内容, 从而确保锚点定位不会出现循环依赖。

要确定 目标锚元素, 给定一个查询元素 query el 以及一个可选的 锚点指示符 anchor spec
  1. 如果未传递 anchor spec, 则返回 默认锚元素(如存在), 否则返回空。

  2. 如果 anchor specauto

    1. 如果 query el 有一个 隐式锚元素 并且它是 可接受的锚元素, 则返回该元素。

    2. 否则,返回空。

    注: 未来的 API 也可能定义隐式锚元素, 届时会在该算法中明确处理, 以确保兼容。

  3. 否则,anchor spec 是一个 <dashed-ident>

    如果 query el 的某个祖先 满足下述条件, 则返回距离 query el 最近的该元素。 否则,返回树顺序中最后一个满足条件的元素 el

    若无元素满足上述条件, 则返回空。

    注: anchor-scope 可限制特定 锚名称 的可见性, 从而影响哪些元素可被用作 锚元素

注: 由一个 anchor-name 定义在某个 shadow tree 中, 该名称不会被不同 shadow treeanchor 函数 样式所看到,以保证封装性。 但不同 shadow tree 中的元素 仍可互相锚定, 只要 anchor-nameanchor 函数 都来自同一树内的样式,比如用 ::part() 给 shadow 里的元素加样式。 (隐式锚元素 理论上也不限于单一树,但细节依赋值API而定。)

如果下列全部为真, 元素 possible anchor 就是 绝对定位元素 positioned el可接受的锚元素

2.4. 默认锚点:position-anchor 属性

名称: position-anchor
取值: normal | none | auto | <anchor-name>
初始值: normal
适用元素: 绝对定位框
继承性: no
百分比: n/a
计算值: 按指定值
规范顺序: 依语法
动画类型: 离散型

position-anchor 属性指定 默认锚元素, 该元素被 position-areaposition-try, 以及(默认情况下)应用于此元素的所有 锚函数 所使用。 position-anchor仅重置子属性(reset-only sub-property), 属于 position 属性的一部分。

normal

position-areanone, 则表现为 none。 否则, 等同于 auto

none

该框没有 默认锚元素

auto

若存在 隐式锚元素,则使用之; 否则该框没有 默认锚元素

<anchor-name>

由指定 <anchor-name> 选中的 目标锚元素 即为该盒子的 默认锚元素

主框 (principal box) 是 默认锚元素默认锚盒(default anchor box)

例如,下方代码 .foo.bar 两个元素 可以使用相同的定位属性, 只需改变所引用的锚元素即可:
.anchored {
  position: absolute;
  top: calc(.5em + anchor(outside));
  /* 未指定锚名称,
     因此自动引用默认锚盒。 */
}

.foo.anchored {
  position-anchor: --foo;
}
.bar.anchored {
  position-anchor: --bar;
}

2.4.1. 隐式锚点元素

某些规范可以定义,在特定情形下, 某个特定元素为另一个元素的 隐式锚点元素

TODO: 待 HTML 规范正式收录相关内容后,补充 popover 相关新例子

隐式锚点元素 可通过 auto 关键字在 position-anchor 中引用, 或在 锚点函数 中省略锚点引用时引用之。

伪元素隐式锚元素, 除非另有规定, 是其起始元素

2.5. 锚点相关性

判断元素 el 是否 与用户相关 时, 如果其某个后代作为定位盒的 目标锚点元素 (且该定位盒自身不是 被跳过 的, 且其 包含块 不是 elel 的后代), 则必须认为 el 与用户相关

注: 这意味着,例如, content-visibility: auto 子树里的锚点, 只要依赖它的定位盒本身也不是被跳过的, 就会阻止其子树 被跳过内容。 (除非锚点和定位盒都在同一个 content-visibility: auto 元素之下; 二者不会互相循环保持可见。)

3. 基于锚点的定位

绝对定位盒 可以相对于页面上的一个或多个 锚点框 进行定位。

position-area 属性提供了基于网格的便捷方式以便于相对于 默认锚点框 定位; 如需更复杂或相对于多个盒子的定位, 可在 内边距属性 中通过 anchor() 函数显式引用某锚点框的边。

3.1. position-area 属性

名称: position-area
取值: none | <position-area>
初始值: none
适用元素: 拥有 默认锚盒 的定位框
继承性: no
百分比: n/a
计算值: 关键字 none,或一对关键字,详见§ 3.1.3 <position-area> 的计算值与序列化
规范顺序: 依语法
动画类型: 待定(TBD)

大多数 锚点定位 的常见用例只关注 定位盒的 包含块 边界 及 默认锚点框 的边界。 可以把这些线看作构成了一个 3×3 网格; position-area 让你可以轻松指定 要将定位盒铺放在这个 position-area grid 中的哪个区域。

position-area: top left 示例, 适用于 horizontal-tb ltr 书写模式
none

该属性无效果。

<position-area>

如果该盒没有 默认锚点框 或不是 绝对定位盒, 此值无效果。

否则,选择 position-area grid 的一个区域, 并将其作为该盒的 包含块

注: 这意味着 内边距属性 表示相对 position-area 的偏移, 并且一些属性值(如 max-height: 100%) 也将相对于 position-area。

none 外的值还具有如下效果:

3.1.1. 解析 Position Area 网格

position-area 网格是一个 3×3 的网格, 每个轴由四条网格线组成。 顺序如下(使用 包含块的书写模式):

注意:默认锚点盒子 部分或全部在修改前的 包含块之外时, position-area 网格的某些行或列可能为零尺寸。

3.1.2. <position-area> 取值语法

位置由一对值指定, 可用 流向相关物理术语表达。 <position-area> 的允许语法为:

<position-area> = [
  [ left | center | right | span-left | span-right
  | x-start | x-end | span-x-start | span-x-end
  | self-x-start | self-x-end | span-self-x-start | span-self-x-end
  | span-all ]
  ||
  [ top | center | bottom | span-top | span-bottom
  | y-start | y-end | span-y-start | span-y-end
  | self-y-start | self-y-end | span-self-y-start | span-self-y-end
  | span-all ]
|
  [ block-start | center | block-end | span-block-start | span-block-end | span-all ]
  ||
  [ inline-start | center | inline-end | span-inline-start | span-inline-end
  | span-all ]
|
  [ self-block-start | center | self-block-end | span-self-block-start
  | span-self-block-end | span-all ]
  ||
  [ self-inline-start | center | self-inline-end | span-self-inline-start
  | span-self-inline-end | span-all ]
|
  [ start | center | end | span-start | span-end | span-all ]{1,2}
|
  [ self-start | center | self-end | span-self-start | span-self-end | span-all ]{1,2}
]

<position-area> 取值通过如下方式指定所选区域占据的网格行和列,从而选中 position-area 网格的某个区域:

start, end, self-start, self-end
top, bottom, left, right
y-start, y-end, self-y-start, self-y-end
x-start, x-end, self-x-start, self-x-end
block-start, block-end, self-block-start, self-block-end
inline-start, inline-end, self-inline-start, self-inline-end
center

对应的单个行或列, 取决于该关键字指定的是哪个轴。

类似于 anchor(), 普通逻辑关键字 (startend 等) 指的是盒子的 包含块的书写模式。 x-start 等在指定物理轴的方向上也是一样。

self-* 逻辑关键字 (self-startself-x-end 等) 是一样的,但指的是盒子自己的 书写模式

span-start, span-end, span-self-start, span-self-end
span-top, span-bottom, span-left, span-right
span-y-start, span-y-end, span-self-y-start, span-self-y-end
span-x-start, span-x-end, span-self-x-start, span-self-x-end
span-block-start, span-block-end, span-self-block-start, span-self-block-end
span-inline-start, span-inline-end, span-self-inline-start, span-self-inline-end

对应两个相邻的行或列, 取决于该关键字指定的是哪个轴: 包含中心行/列, 及与该关键字另一半相对应的行/列(参考单轨关键字)。

(例如 span-top 跨越前两行——中心行和顶部行。)

span-all

对应所有三行或列, 取决于该关键字指定的是哪个轴。

有些关键字对于所属轴是模糊的: centerspan-all, 以及未明确指定块或内联轴的 start 等关键字。 如果另一个关键字对于轴是明确的, 则模糊关键字指的是相反的轴。 (例如 block-start center 中, center 指的是内联轴。) 如果两个关键字都模糊, 则第一个关键字指盒子的 块轴, 第二个指 内联轴。 (例如 span-all start 等价于 span-all inline-start。)

如果只给出一个关键字, 且该关键字对于轴是明确的,则等价于第二个关键字为 span-all; 否则等价于重复该关键字。 (例如 top 等价于 top span-allcenter 等价于 center center。)

3.1.3. <position-area> 的计算值与序列化

计算值为两个关键字,分别指明每个轴选中的区段, 长(block-start)和短(start)逻辑关键字视为等价。 按上方语法顺序序列化, 逻辑关键字用短形式 (如 start start 而不是 block-start inline-start)。

3.2. 锚点相对内边距:anchor() 函数

绝对定位盒 可以在其 内边距属性中 使用 anchor() 函数 以引用一个或多个 锚点框 的位置。 anchor() 函数会被解析为 <length>。 它只能用于内边距属性中 (否则无效)。

名称: topleftrightbottom
新值: <anchor()>
<anchor()> = anchor( <anchor-name>? && <anchor-side>, <length-percentage>? )
<anchor-side> = inside | outside
       | top | left | right | bottom
       | start | end | self-start | self-end
       | <percentage> | center

anchor() 函数有三个参数:

表示 可解析锚点函数anchor()计算值 时(借助 样式与布局交错)解析为 能使定位盒的 内边距修饰包含块 对应边与 目标锚点元素锚点框 指定边对齐的 <length>

注: 这意味着过渡动画 只要属性里用到了锚函数, 面向各种可能的变化都会“如预期”生效: 锚盒移动、 锚元素被加入或移出文档、 锚上的anchor-name属性发生变化等等。

例如, .bar { inset-block-start: anchor(--foo block-start); } 中的 anchor() 解析为 使 .bar 元素的 block-start 边和 --foo 锚点的 block-start 边对齐的长度。

.bar { inset-block-end: anchor(--foo block-start); } 会解析为 使 .bar 元素的 block-end 边和 --foo 锚点的 block-start 边对齐的长度。

由于 inset-block-startinset-block-end 分别表示从包含块 block-start 和 block-end 边的内边距, 同一个 anchor() 通常会在两者中解析为不同的长度。

由于 anchor() 函数解析为 <length>, 因此可以像其它长度一样用于 数学函数 中。

需补一个更能体现 anchor() 特色的例子; 现在这个仅用 anchor-center 就可实现。[Issue #10776]

例如如下写法可让元素的 内边距修饰包含块 水平居中到 锚点框, 并自动尽可能铺宽而不溢出 包含块

.centered-message {
  position: fixed;
  max-width: max-content;
  justify-self: center;

  --center: anchor(--x 50%);
  --half-distance: min(
    abs(0% - var(--center)),
    abs(100% - var(--center))
  );
  left: calc(var(--center) - var(--half-distance));
  right: calc(var(--center) - var(--half-distance));
  bottom: anchor(--x top);
}

这很适合用于 input 等元素的错误信息提示, 居中能方便用户确认到底在说哪个输入框。

3.2.1. anchor() 的解析

仅当同时满足全部以下条件时,anchor() 函数才是 可解析锚点函数

如有任一条件不成立, anchor() 函数解析为其指定的回退值。如果未指定回退值, 该属性声明在计算值阶段视为无效

3.3. 考虑滚动因素

出于性能考虑, 实现通常会在独立的滚动/“合成”线程上处理滚动, 而该线程仅具有限制的能力(可进行简单移动/变换等,但不能布局或执行高开销操作), 因此可以对滚动反应得足够快,在用户看来近似“即时”。

如果滚动仅导致锚点定位元素移动, 理论上没有问题; 元素的移动完全可在滚动线程中执行, 使定位元素能和滚动内容同步平滑移动。 但锚点定位允许元素 使其对边的位置取决于不同滚动上下文中的内容, 这意味着滚动可能只移动某一边,从而导致尺寸改变,引发布局。 这种操作无法由滚动线程处理!

为兼顾性能与灵活锚定的需求, 锚点定位 结合使用记忆滚动偏移滚动补偿

下面细节略为技术性,总结如下:

最终效果是 锚点定位通常总能“如期工作”, 无论锚点如何锚定,但响应滚动的方式可能受到一定限制。

当一个绝对定位元素 开始生成盒子时 (即从 display:nonedisplay:contents 切换为任何其他 display 值时), 就会发生一次 锚重算点(anchor recalculation point), 与其开始运行 CSS 动画的时机一致。

元素在 确定回退定位样式时, 也会产生一次 锚重算点; 如果结果导致回退样式发生变化, 则被选择的回退样式关联的 锚重算点 作为结果使用。

当元素 abspos 发生一次 锚重算点, 那么对其所有 锚引用引用到的元素 anchor , 都会记录一个 记忆滚动偏移量(remembered scroll offset), 数值等于当前所有 滚动容器祖先的 滚动偏移量之和, 向上直至(但不包括) abspos包含块记忆滚动偏移量 还应计入其它依赖滚动的定位变动, 如 position: sticky。 如果 abspos默认锚元素, 无论它是否对该元素有 锚引用, 都要计算其 记忆滚动偏移量

所有 锚引用 的计算方式为: 先假定所有 滚动容器 处于其 初始滚动位置, 然后再加上各自关联的 记忆滚动偏移量

变换(transforms)和滚动问题类似, 所以锚定位默认也不会考虑变换。 我们能否直接把变换效果引入此流程?

上述机制允许定位元素对它的 锚引用的滚动(scroll) 仅响应一次, 但任何一个被滚动后, 该定位元素将不再看似锚定于它们 (但它仍会响应它们非滚动引起的移动)。 这个问题一般无法彻底解决, 但对一个 锚引用的滚动是可以响应的: 即 默认锚元素

一个绝对定位框 abspos, 若同时满足下列条件, 即补偿滚动(compensate for scroll) 水平轴或垂直轴的滚动:

注: 如果 abspos定位选项列表, 是否在某轴 补偿滚动 也会被选定的回退样式所影响。

abspos默认滚动偏移(default scroll shift) 是一对分别表示水平轴和垂直轴的长度。 每个长度计算如下:

完成 abspos 的布局后, 还要根据 默认滚动偏移 进行额外移动, 效果如同施加了一个 transform (在其它变换之前)。

明确定义快照的精确时机: 每帧更新, 在样式重计算前。

类似于 记忆滚动偏移量, 是否也可考虑 默认锚元素上的 transform?

注: 记忆滚动偏移量 会影响 anchor() 函数的值, 默认滚动偏移 则会在计算 内边距属性、 应用对齐等操作之后 直接移动该元素。 这通常是不可区分的, 但如 round(anchor(outside), 50px) 这类 非线性变换 默认锚元素位置的情况, 就会暴露出行为差异。

4. 基于锚点的对齐

4.1. 区域特定默认对齐

position-area 不是 none 时, 已用值normal 自对齐 会根据 <position-area> 的值变化, 以便让盒子朝向锚点对齐:

但如果相关轴只有一个 内边距属性auto, 默认对齐则沿着非 auto 的那一边, 且这是 unsafe 对齐。

注: 这种单 auto 行为保持了 指定某一个内边距值即可控制 绝对定位 盒的位置的惯例。

例如,假定为英文等价的书写模式(horizontal-tb, ltr), 值 span-x-start top 会解析为 垂直方向 start 区域(start), 和水平方向的 startcenter 区域, 因此默认对齐将是 align-self: end (使盒子的底部 外边距 正好与 top 区域的下边缘齐平), 以及 justify-self: end (使盒子的 end 侧 外边距 正好与 span-start 区域的 end 侧齐平)。
如果盒子溢出了其 内边距修饰包含块, 但仍可以放入其 原始包含块 内, 默认会“平移”以保持在 原始包含块 内, 即使这样会违反正常的对齐。 详见 CSS Box Alignment 3 § 4.4 Overflow Alignment: the safe and unsafe keywords and scroll safety limits

这种行为可以更好地保证定位盒保持可见, 且位于其预期的边界内, 即使 包含块 的尺寸比预期更小时也是如此。

例如 position-area: bottom span-right, 定位盒会从锚点左侧边缘拉伸到包含块右侧边缘, 默认在其间左对齐。 如果定位盒比这块空间还大 (比如锚点很靠近屏幕右边缘时), 盒子会左移以保持可见。

4.2. 锚点居中对齐:anchor-center 对齐值

名称: justify-selfalign-selfjustify-itemsalign-items
新值: anchor-center

自对齐属性允许绝对定位盒 在其 内边距修饰包含块 内自对齐。 现有的属性值和精心设置的 内边距属性 通常能满足常见的对齐需求, 但锚定定位中一个常见场景——居中覆盖 锚点框——实现起来需要较为复杂的设置。

新增的 anchor-center 值 让这类需求极为简单: 如果定位盒有 默认锚点框, 则尽可能在相关轴上居中于该 默认锚点框。 另外:

如果该盒不是 绝对定位盒, 或没有 默认锚点框, 则该值行为等同于 center, 不会影响 内边距属性 的解析。

注: 采用 anchor-center 时,默认情况下 如果锚点过于靠近盒子的 原始包含块 边缘, 就会从居中位置平移, 以确保仍然处于 原始包含块 内。 详见 CSS Box Alignment 3 § 4.4 Overflow Alignment: the safe and unsafe keywords and scroll safety limits

5. 基于锚点的尺寸

绝对定位盒 可以在其 尺寸属性 中用 anchor-size() 函数 引用一个或多个 锚点框 的尺寸。 anchor-size() 函数会被解析为 <length>。 该函数仅允许用于 可接受的 @position-try 属性 (否则无效)。

5.1. anchor-size() 函数

名称: widthheightmin-widthmin-heightmax-widthmax-heighttopleftrightbottommargin-topmargin-leftmargin-rightmargin-bottom
新值: <anchor-size()>
anchor-size() = anchor-size( [ <anchor-name> || <anchor-size> ]? , <length-percentage>? )
<anchor-size> = width | height | block | inline | self-block | self-inline

anchor-size() 类似 anchor(), 参数基本一致, 只是 <anchor-side> 关键字替换为 <anchor-size>, 指代盒子的对边间距。

物理方向的 <anchor-size> 关键字 (widthheight) 分别表示 目标锚点元素 的宽度和高度。 与 anchor() 不同,这里无需轴向对应限制; 比如 width: anchor-size(--foo height); 是合法的。

逻辑方向的 <anchor-size> 关键字 (blockinlineself-blockself-inline) 将按照盒子本身 (对于 self-blockself-inline) 或其 包含块 (对于 blockinline) 的 书写模式 映射到具体物理关键字。

如省略 <anchor-size> 关键字, 则表现为与 anchor-size() 使用的属性轴向一致的关键字。 (比如 width: anchor-size() 相当于 width: anchor-size(width)。)

可解析锚点尺寸函数anchor-size()计算值 阶段(借助 样式与布局交错) 解析为 <length>, 即 目标锚点元素锚点框 的相关两条边(左右或上下)的间距。

5.1.1. anchor-size() 的解析

仅当同时满足以下所有条件时, anchor-size()可解析锚点尺寸函数

如不满足上述任意条件, anchor-size() 解析为其回退值。 无回退值时,引用它的声明在计算值阶段 失效

6. 溢出管理

锚点定位虽然强大, 但也可能引入不可预知性。 锚点框 可能出现在页面任何位置, 因此将盒精确定位(比如放在锚点上方或右侧) 可能导致定位盒溢出其 包含块 或部分超出屏幕。

为解决这个问题, 绝对定位盒 可以用 position-try-fallbacks 属性 指定额外的 定位选项 (这些是根据盒子的现有样式生成的定位/对齐属性组合, 或由 @position-try 规则明确指定), 由 UA 在初始定位溢出时依次尝试。 每个选项会被应用到盒子上, 按 position-try-order 指定的顺序一一尝试, 第一个不导致溢出 包含块 的选项为最终方案。

一旦选项被选中, 元素会保持这些样式直到再次溢出, 即使此前(且可能更理想的)选项 再次可用也不会改变,除非发生溢出。 (参见 记录上一次成功的位置选项。)

例如, 下面的 CSS 会首先把 “popover” 定位在目标元素下方, 如果不适合,则切换到上方。 默认与锚点起始端对齐, 若依然不适合,则换到末端对齐。 如果两边都放不下, 则会占满整个水平空间并尽量锚点居中显示 (受益于 § 4.1 区域默认对齐方式)。
#myPopover {
  position: fixed;
  position-anchor: --button;
  position-area: bottom span-x-end;
  position-try-fallbacks: flip-x, flip-y, flip-x flip-y, bottom, top;

  /* popover 宽度不少于按钮宽 */
  min-width: anchor-size(width);

  /* popover 高度不少于 2 个菜单项 */
  min-height: 6em;
}

需要插图!

6.1. 提供回退选项:position-try-fallbacks 属性

名称: position-try-fallbacks
取值: none | [ [<dashed-ident> || <try-tactic>] | <position-area> ]#
初始值: none
适用元素: 绝对定位框
继承性: no
百分比: n/a
计算值: 按指定值
规范顺序: 依语法
动画类型: 离散型

该属性提供了一组可选定位样式, 当 绝对定位盒 溢出其 内边距修饰包含块 时会依次尝试。 这个 定位选项列表 最初只包含由元素的 回退基础样式(即不应用 position-try-fallbacks 时的 计算样式)生成的唯一一个 定位选项

列表中每个逗号分隔的条目都是一个独立选项:可以是 @position-try 块名称, 也可以是 <try-tactic>,代表自动转换现有计算样式。

各值含义如下:

none

该属性无效果; 该盒的 定位选项列表为空。

<dashed-ident>

如果有同名的 @position-try 规则, 其对应 定位选项 会加入 定位选项列表

否则该值没有效果。

<try-tactic>

通过 执行指定 try tactic 自动基于 基础样式 生成 定位选项, 并将其加入该盒的 定位选项列表

<try-tactic> = flip-block || flip-inline || flip-start || flip-x || flip-y
flip-block

交换 块轴(如 margin-block-startmargin-block-end)上的属性值, 本质上相当于绕 行轴做镜像。

flip-inline

交换 行轴上的属性值, 本质上相当于绕 块轴做镜像。

flip-x

交换 水平方向 (如 margin-leftmargin-right)上的值, 本质上绕 竖直方向做镜像。

flip-y

交换 竖直方向上的值, 本质上绕 水平方向做镜像。

flip-start

start 类属性互换, end 类属性之间也互换 (比如 margin-block-startmargin-inline-start), 等价于绕从 块起点-行起点块终点-行终点 的对角线做镜像。

若指定多个关键字, 则依次执行各变换,最后形成单一 定位选项。 逻辑方位以 书写模式包含块 解析。

<dashed-ident> || <try-tactic>

结合上述两类选项效果: 如有同名 @position-try 规则, 则先应用其 定位选项 到基础样式, 再依指定 <try-tactic> 变换后 加入到 定位选项列表

否则无效果。

<position-area>

自动创建只包含指定 position-area 属性的 定位选项

6.2. 确定回退顺序:position-try-order 属性

名称: position-try-order
值: normal | <try-size>
初始值: normal
适用对象: 绝对定位盒
是否继承:
百分比: 不适用
计算值: 同指定值
规范序: 按语法
动画类型: 离散

该属性允许元素按可用空间对其 定位选项 重新排序, 若希望盒子获得尽可能大空间而非严格遵循 position-try-fallbacks 中的声明顺序时可以使用。

<try-size> = most-width | most-height | most-block-size | most-inline-size
normal

定位选项position-try-fallbacks 中声明的顺序依次尝试。

most-width
most-height
most-block-size
most-inline-size

定位选项列表 中的每个条目, 应用该定位选项 到盒子, 并计算依该样式获得的 内边距修饰包含块 的尺寸 (并将 auto inset 值视为 0)。 将 定位选项列表 稳定排序,最大尺寸排前。

逻辑方向以 书写模式包含块 解析。

例如,以下样式会让列表弹窗最初自动选择锚点按钮上方或下方, 以获得更多可用空间为优先。
.anchor { anchor-name: --foo; }
.list {
  position: fixed;
  position-anchor: --foo;
  position-area: block-end span-inline-end;
  position-try-fallbacks: --bottom-scrollable, flip-block, --top-scrollable;
  position-try-order: most-height;
}
@position-try --bottom-scrollable {
  align-self: stretch;
}
@position-try --top-scrollable {
  position-area: block-start span-inline-end;
  align-self: stretch;
}

其中 基础样式--bottom-scrollable 选项的可用高度相同, 因为两者下 内边距修饰包含块 都是从锚点延展到包含块边界; flip-block 选项和 --top-scrollable 也同理。 因 position-try-order 稳定排序, 同高选项的排列顺序得以保持, *-scrollable 选项靠后; 高度占优势者排最前。

这会使盒子优先以自身原始高度对齐锚点,选取上下空间中大的一个 (用 基础样式flip-block), 若仍溢出,则退为填满当前空间并允许滚动 (用对应 *-scrollable 款), 这样不会溢出,也不会被强制塞到空间较小的一侧。

6.3. position-try 速记

名称: position-try
值: <'position-try-order'>? <'position-try-fallbacks'>
初始值: 见各自属性
适用对象: 见各自属性
是否继承: 见各自属性
百分比: 见各自属性
计算值: 见各自属性
动画类型: 见各自属性
规范序: 按语法

该速记属性同时设置 position-try-fallbacksposition-try-order。 如果省略了 <'position-try-order'>, 则该属性设置为其初始值。

6.4. @position-try 规则

@position-try 规则 定义一个具有指定名称的 定位选项, 其中可指定一组或多组可通过 position-try-fallbacks 应用于盒子的定位属性。

@position-try 规则的语法为:

@position-try <dashed-ident> {
  <declaration-list>
}

前导符指定的 <dashed-ident> 是该规则的名称。 如果声明了多个同名的 @position-try 规则, 它们会像 @keyframe 规则一样层叠

@position-try 规则仅接受 以下 属性

<declaration-list> 里的属性不得使用 !important。 若使用会使该属性无效,但不会导致整个 @property-try 规则无效。

所有 @position-try 中的属性 都以 Position Fallback Origin 的身份应用到盒子上, 这是一个新的 层叠源, 介于 作者源动画源 之间。

类似 动画源, 若值为 revert, 则视为该属性属于 作者源, 因此将回退到 用户源。 (和 动画源 一样, revert-layer 无特殊行为,按原样处理。)

注: @position-try 可接受属性 是仅影响盒子自身尺寸和定位的最小属性集合,不会影响其内容和其他样式。 这显著简化了位置回退的实现,并确保可根据可用空间移动锚定定位盒。 由于这些规则会覆盖 作者源 中的正常声明, 所以也降低了 @position-try 对其他属性层叠与继承的干扰。 未来扩展 容器查询 预计会支持基于所用位置回退条件查询元素, 以实现本文限制列表中不支持的条件样式。

注: 若多个元素要共用同一 @position-try 规则, 但各自锚点不同, 可省略 <anchor-name>,在 anchor() 中省略锚点名称, 并分别用 position-anchor 指定。

注: 最常用的回退定位方式(如初步将定位盒放在锚点某一侧,溢出时自动切到另一侧) 可直接用 position-try-fallbacks 关键字自动完成, 无需编写 @position-try

6.5. 应用位置回退

当一个定位盒 (应用任何 默认滚动平移 后) 溢出其 内边距修饰包含块, 且 定位选项列表 中有多于一个 定位选项 时, 会确定位置回退样式, 以尝试选出不溢出的选项。 选中的样式通过 样式与布局交错机制应用到元素上, 所以会影响 计算值 (可触发过渡等), 虽然其本身依赖于布局及 已用值

实现可视情况限制 定位选项列表 长度, 以减少多余布局消耗。此限制至少应为五个。

确定位置回退样式算法(对元素 abspos):
  1. current stylesabspos 当前的用值样式, 即来自 已计算基础样式 (可能是先前回退的结果)。

  2. 依次遍历 position options list定位选项列表)里的每个 option

    1. 如果 option 就是当前 abspos上一次成功的位置选项跳过

    2. adjusted styles应用位置选项 optionabspos 的结果。

    3. el rectabspos 的 margin box 大小和位置, cb rect 为以 adjusted styles 布局后的 abspos已修正内嵌包含块 的大小和位置。

    4. 如果 cb rect 某个轴为负尺寸且被修正为零尺寸, 跳过

      注: 这样可防止零尺寸的 el rect 被当作落入负尺寸的 cb rect 内 并被错误选为成功选项。

    5. 如果 el rect 并未完全包含在 cb rect 内, 跳过

    6. 返回 adjusted styles, 以及相应假设已计算的 记忆滚动偏移量集合。

  3. 断言:上一步未找到可避免溢出的 位置选项

  4. 返回 current styles

注: 后代溢出 el 不影响本算法,只判断 elmargin 盒

注: 本算法有意跳过当前已应用的 定位选项,因此其 记忆滚动偏移不会刷新;所有回退都失败时沿用当前样式,则 记忆滚动偏移 保持不变。

在一次完整布局过程中, 一旦盒子确定了其回退样式(或确定无需回退), 后续布局的盒不会更改这一结果。

举例,假如有两个定位盒 A 和 B, 先布局 A,后布局 B。 如果 B 溢出导致 A 的包含块出现滚动条, 这不会导致 A 回过头重新判断自己的回退样式以躲开溢出。 (否则最坏情况下可能死循环甚至布局炸裂。)

换句话说,布局“不向后追溯”。

6.5.1. 回退选项的维护与清除

对盒子的某些更改会直接影响 确定位置回退样式 并触发特殊处理,这些回退敏感更改包括:

为此只考虑 已计算基础样式 的变化, 即已计算样式 忽略所有来自 Transitions 或 Animations 级联来源的声明。

6.5.1.1. 记录上一次成功的位置选项

为了尽可能保持布局稳定, 确定回退定位样式时会优先考虑 上一次成功的位置选项, 其算法如下:

在确定和派发 ResizeObserver 事件时, 应按如下方式 记录上一次成功的位置选项

注: 该记录/移除的时机 特意与上次记忆尺寸的处理方式一致。

6.5.2. 应用位置选项

应用定位选项到盒子的元素 el: 给定 定位选项 new styles
  1. new styles 作为 位置回退源 插入层叠, 计算层叠,完成必要布局以得到 el已用样式

    为计算这些样式,应推算一个假定锚点重算点, 采用所得的假定记忆滚动偏移推敲 el 格式。

  2. 返回 el已用样式

执行 try-tactic 于元素 el 的一组 styles, 在两个方向 directions 之间, 返回变换后的样式集:
  1. directions 同轴而相反,视为“对立”;否则(如是不同轴)为“垂直”。

  2. el@position-try 可接受属性,作为 styles

  3. styles 替换变量、env() 等函数和 任意替代函数

    env() 如引用带方向或轴, (如 safe-area-inset-top), 则变量按 directions 改换。

    例如 top: env(safe-area-inset-top);directions 如为 up, left,则 env()env(safe-area-inset-left) 处理(下一步会替换到 left 属性上)。
  4. 交换 styles 中与 directions 关联的属性值。

    例:swap "top" 与 "left" 时,margin-topmargin-left 交换,widthheight 交换,等等。

    注: 如 directions 为同轴对立,某些属性(如 widthalign-self) 不交换,但其值可能会被下步骤改动。

  5. 按新方向修改属性值具体如下:

  6. 返回 styles

6.6. 条件隐藏:position-visibility 属性

名称: position-visibility
值: always | [ anchors-valid || anchors-visible || no-overflow ]
初始值: anchors-visible
适用对象: 绝对定位盒
是否继承:
百分比: 不适用
计算值: 同指定值
规范序: 按语法
动画类型: 离散

在某些情况下,显示 绝对定位盒 可能没有意义。 此属性允许依据常见布局条件有条件地显示这些盒子。

always

该属性无效果。 (无论锚点或溢出状态如何,盒子都会显示。)

anchors-valid

如果盒子的任一 所需锚点引用 不能解析为 目标锚点元素, 该盒子的 visibility 属性计算为 force-hidden

所需锚点引用 是什么? 指没有回退值的 anchor() 函数; 默认锚点 *有时* 也算在内? 此处待补充更细说明。

是“任一”锚点缺失就隐藏, 还是“全部”锚点缺失才隐藏? 两者皆有用例,是否要定规或允许控制?

anchors-visible

如果盒子有 默认锚点框 但该 锚点框 不可见被中间盒裁剪, 则盒子的 visibility 计算为 force-hidden

no-overflow

如盒子即便应用 position-try 后仍溢出其 内边距修饰包含块, 则其 visibility 计算为 force-hidden

锚盒 anchor 相对于依赖它的定位盒 abspos 来说, 如果其墨水溢出矩形 被一个盒子完全裁剪, 且该盒子是 anchor 的祖先, 但又是 abspos 包含块的后代, 那么就称 被中间盒裁剪。 这里的裁剪仅指 IntersectionObserver (默认)所检查的那些裁剪效果, 即由于 clip-pathoverflow, 或其它裁剪到 绘制包含 的效果, 溢出裁剪边 的裁剪。 如果 anchor 区域非零, 那么其与裁剪区域也必须有非零的相交面积, 才能视为没有被完全裁剪。

是否 被中间盒裁剪 必须在更新文档内容关联性 (见 content-visibility in [css-contain-2]) 并运行所有 ResizeObserver 后, 但必须在运行 IntersectionObserver 之前检查。 如为提升响应速度,也可在其它时机检查。

注: 这意味着如 abspos 和锚点元素在 DOM 中紧邻, 即使其默认锚被滚动移出,因被同一滚动器裁剪依然可见。

请确认本裁剪定义与 View Transitions 一致(后者有类似需求)。

注: 这保证“链式锚定”时, 若第一个 abspos 因锚点被隐藏导致隐藏, 则把它作锚点的其它 abspos 也会被隐藏,而不会浮到乱七八糟的位置。

7. 可访问性影响

CSS 锚点定位不会创建、删除或变更元素间的可访问性绑定。 作者需用合适标记手段确保可访问性关系。

由于本特性用法极多, CSS 锚点定位 不会自动在定位盒与其锚点间建立任何语义关系。 例如,设计中的视觉锚定关系 可能正好反映语义锚点; 也可能因视觉效果需要,连接到锚点的祖先、兄弟或后代元素; 也可能视觉上无需锚定却语义上绑定,反之亦然。

作者不应依赖 CSS 定位的可见连接 来建立元素间的语义关系。 若无合适标记支持, 这些仅视觉关联的元素在 DOM 层并无任何实际关系——若实际有语义关系缺乏标记支持, 就会导致如屏幕阅读器或键盘模式等非视觉用户代理难于甚至无法使用这些元素。

Web 平台有许多现有与即将到来的方案, 可用来明确表达语义关联,从而便于非视觉用户代理访问。 比如 HTML Popover API 会自动将触发按钮与 popover 元素关联, 并自动调整 Tab 顺序; 同时还会自动把触发按钮 设为该 popover 的 隐式锚点元素, 从而能直接配合锚点定位使用。

补一个 popover 示例。

更一般地, ARIA 特性如 aria-detailsaria-describedby 属性 可以让锚点元素建立关联,实现半自动连接。 同时加上定位元素的 role 属性, 非视觉代理即可获知两者关系,实现自动化导航。

但作者也别滥用这些特性, 否则页面满是多余的语义连接反而降低易读性。

欢迎建议优化本节, 尤其是常见场景作者指引与最佳实践示例。[Issue #10311]

8. DOM 接口

8.1. CSSPositionTryRule 接口

CSSPositionTryRule 接口代表 @position-try 规则:

[Exposed=Window]
interface CSSPositionTryRule : CSSRule {
  readonly attribute CSSOMString name;
  [SameObject, PutForwards=cssText] readonly attribute CSSPositionTryDescriptors style;
};

[Exposed=Window]
interface CSSPositionTryDescriptors : CSSStyleDeclaration {
  attribute CSSOMString margin;
  attribute CSSOMString marginTop;
  attribute CSSOMString marginRight;
  attribute CSSOMString marginBottom;
  attribute CSSOMString marginLeft;
  attribute CSSOMString marginBlock;
  attribute CSSOMString marginBlockStart;
  attribute CSSOMString marginBlockEnd;
  attribute CSSOMString marginInline;
  attribute CSSOMString marginInlineStart;
  attribute CSSOMString marginInlineEnd;
  attribute CSSOMString margin-top;
  attribute CSSOMString margin-right;
  attribute CSSOMString margin-bottom;
  attribute CSSOMString margin-left;
  attribute CSSOMString margin-block;
  attribute CSSOMString margin-block-start;
  attribute CSSOMString margin-block-end;
  attribute CSSOMString margin-inline;
  attribute CSSOMString margin-inline-start;
  attribute CSSOMString margin-inline-end;
  attribute CSSOMString inset;
  attribute CSSOMString insetBlock;
  attribute CSSOMString insetBlockStart;
  attribute CSSOMString insetBlockEnd;
  attribute CSSOMString insetInline;
  attribute CSSOMString insetInlineStart;
  attribute CSSOMString insetInlineEnd;
  attribute CSSOMString top;
  attribute CSSOMString left;
  attribute CSSOMString right;
  attribute CSSOMString bottom;
  attribute CSSOMString inset-block;
  attribute CSSOMString inset-block-start;
  attribute CSSOMString inset-block-end;
  attribute CSSOMString inset-inline;
  attribute CSSOMString inset-inline-start;
  attribute CSSOMString inset-inline-end;
  attribute CSSOMString width;
  attribute CSSOMString minWidth;
  attribute CSSOMString maxWidth;
  attribute CSSOMString height;
  attribute CSSOMString minHeight;
  attribute CSSOMString maxHeight;
  attribute CSSOMString blockSize;
  attribute CSSOMString minBlockSize;
  attribute CSSOMString maxBlockSize;
  attribute CSSOMString inlineSize;
  attribute CSSOMString minInlineSize;
  attribute CSSOMString maxInlineSize;
  attribute CSSOMString min-width;
  attribute CSSOMString max-width;
  attribute CSSOMString min-height;
  attribute CSSOMString max-height;
  attribute CSSOMString block-size;
  attribute CSSOMString min-block-size;
  attribute CSSOMString max-block-size;
  attribute CSSOMString inline-size;
  attribute CSSOMString min-inline-size;
  attribute CSSOMString max-inline-size;
  attribute CSSOMString placeSelf;
  attribute CSSOMString alignSelf;
  attribute CSSOMString justifySelf;
  attribute CSSOMString place-self;
  attribute CSSOMString align-self;
  attribute CSSOMString justify-self;
  attribute CSSOMString positionAnchor;
  attribute CSSOMString position-anchor;
  attribute CSSOMString positionArea;
  attribute CSSOMString position-area;
};

它的 name 属性 表示该规则前导部分声明的名称。

它的 style 属性 表示规则体中声明的属性,按指定顺序排列。 获取时,必须返回该 @position-try 规则的 CSSPositionTryDescriptors 对象, 其属性如下:

computed flag

未设置

readonly flag

未设置

declarations

规则中声明的描述符,按指定顺序排列。

parent CSS rule

上下文对象

owner node

Null

9. 附录:样式与布局交错

样式与布局交错 是一种技术, 在布局过程中允许对子树进行样式更新, 从而可对元素的 计算样式进行追溯性更新。

此概念并非本规范的正确定义, 可能应移至 Cascade, 但此处需要一个可引用的草稿。

注意: 样式与布局交错 已用于 容器查询容器查询长度。 如 10cqw 这类长度,会根据查询容器的尺寸布局信息解析为 计算长度, 因此当容器在布局间改变尺寸时可触发 过渡

被接受的 @position-try 属性 在解析回退时也会 交错 (见 position-try)。

显然还需补充更多细节, 但目前“像容器查询一样处理”即可。 该行为本身也未定义, 但至少在一定程度上已实现互操作。

10. 安全性考虑

本文件尚未发现安全性问题。

11. 隐私性考虑

本文件尚未发现隐私问题。

12. 变更记录

2025年12月22日工作草案 以来的重要变更:

2025年10月7日工作草案 以来的主要更改:

另见 先前变更

一致性

文档约定

一致性要求采用描述性断言和 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"> 区分,如下所示: 用户代理必须(MUST)提供可访问的替代方案。

一致性类别

本规范的一致性定义分为三类:

样式表
CSS 样式表
渲染器
用户代理(UA) 负责解释样式表语义并渲染使用这些样式表的文档。
编辑工具
UA 用于编写样式表。

如果样式表中使用的语法均符合本模块定义的通用 CSS 语法和各功能的专属语法,则该样式表符合本规范。

渲染器符合本规范的条件是,除按相关规范解释样式表外,还能正确解析并渲染本规范定义的所有功能。 但 UA 由于设备限制无法正确渲染文档,并不被视为不符合规范。(例如,UA 不要求在黑白显示器上渲染颜色。)

编辑工具符合本规范的条件是,其编写的样式表在语法上符合通用 CSS 语法和本模块各功能的专属语法, 并符合本模块描述的所有其他样式表一致性要求。

部分实现

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

不稳定和专有特性的实现

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

非实验性实现

一旦规范进入候选推荐(CR)阶段,非实验性实现就成为可能,且实现者应在能够证明其正确实现的情况下,发布无前缀的 CR 级特性实现。

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

关于提交测试用例和实现报告的进一步信息,可在 CSS 工作组网站 https://www.w3.org/Style/CSS/Test/ 上查阅。 如有问题,请联系 public-css-testsuite@w3.org 邮件列表。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-ALIGN-3]
Elika Etemad;Tab Atkins Jr.。CSS 盒对齐模块 3 级。2025 年 3 月 11 日。WD。URL:https://www.w3.org/TR/css-align-3/
[CSS-BOX-4]
Elika Etemad。CSS 盒模型模块 4级。2024 年 8 月 4 日。WD。URL:https://www.w3.org/TR/css-box-4/
[CSS-BREAK-4]
Rossen Atanassov;Elika Etemad。CSS 分片模块 4级。2018 年 12 月 18 日。FPWD。URL:https://www.w3.org/TR/css-break-4/
[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-CASCADE-6]
Elika Etemad;Miriam Suzanne;Tab Atkins Jr.。CSS 级联与继承 6 级。2024 年 9 月 6 日。WD。URL:https://www.w3.org/TR/css-cascade-6/
[CSS-CONTAIN-2]
Tab Atkins Jr.;Florian Rivoal;Vladimir Levin。CSS 包含模块 2级。2022 年 9 月 17 日。WD。URL:https://www.w3.org/TR/css-contain-2/
[CSS-DISPLAY-3]
Elika Etemad;Tab Atkins Jr.。CSS 显示模块 3级。2023 年 3 月 30 日。CR。URL:https://www.w3.org/TR/css-display-3/
[CSS-DISPLAY-4]
Elika Etemad;Tab Atkins Jr.。CSS 显示模块 4级。2025 年 11 月 6 日。WD。URL:https://www.w3.org/TR/css-display-4/
[CSS-ENV-1]
CSS 环境变量模块 1级。2025 年 9 月 23 日。FPWD。URL:https://www.w3.org/TR/css-env-1/
[CSS-LOGICAL-1]
Elika Etemad;Rossen Atanassov。CSS 逻辑属性与属性值模块 1级。2025 年 12 月 4 日。WD。URL:https://www.w3.org/TR/css-logical-1/
[CSS-MASKING-1]
Dirk Schulze;Brian Birtles;Tab Atkins Jr.。CSS 遮罩模块 1级。2021 年 8 月 5 日。CRD。URL:https://www.w3.org/TR/css-masking-1/
[CSS-OVERFLOW-3]
Elika Etemad;Florian Rivoal。CSS 溢出模块 3级。2025 年 10 月 7 日。WD。URL:https://www.w3.org/TR/css-overflow-3/
[CSS-OVERFLOW-4]
David Baron;Florian Rivoal;Elika Etemad。CSS 溢出模块 4级。2023 年 3 月 21 日。WD。URL:https://www.w3.org/TR/css-overflow-4/
[CSS-POSITION-3]
Elika Etemad;Tab Atkins Jr.。CSS 定位布局模块 3级。2025 年 10 月 7 日。WD。URL:https://www.w3.org/TR/css-position-3/
[CSS-POSITION-4]
Elika Etemad;Tab Atkins Jr.。CSS 定位布局模块 4级。2025 年 10 月 7 日。WD。URL:https://www.w3.org/TR/css-position-4/
[CSS-PSEUDO-4]
Elika Etemad;Alan Stearns。CSS 伪元素模块 4级。2025 年 6 月 27 日。WD。URL:https://www.w3.org/TR/css-pseudo-4/
[CSS-SCOPING-1]
Tab Atkins Jr.;Elika Etemad。CSS 作用域模块 1级。2014 年 4 月 3 日。FPWD。URL:https://www.w3.org/TR/css-scoping-1/
[CSS-SHADOW-1]
CSS 阴影模块 1 级(CSS Shadow Module Level 1)。编辑者草案(Editor's Draft)。 链接:https://drafts.csswg.org/css-shadow-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-SYNTAX-3]
Tab Atkins Jr.;Simon Sapin。CSS 语法模块 3级。2021 年 12 月 24 日。CRD。URL:https://www.w3.org/TR/css-syntax-3/
[CSS-TRANSFORMS-1]
Simon Fraser 等。CSS 变换模块 1级。2019 年 2 月 14 日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[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/
[CSS-VARIABLES-1]
Tab Atkins Jr.。CSS 可级联变量模块 1级。2022 年 6 月 16 日。CR。URL:https://www.w3.org/TR/css-variables-1/
[CSS-VIEWPORT-1]
Florian Rivoal;Emilio Cobos Álvarez。CSS 视口模块 1级。2024 年 1 月 25 日。FPWD。URL:https://www.w3.org/TR/css-viewport-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级(CSS 2.1)规范。2011 年 6 月 7 日。REC。URL:https://www.w3.org/TR/CSS2/
[CSSOM-1]
Daniel Glazman;Emilio Cobos Álvarez。CSS 对象模型(CSSOM)。2021 年 8 月 26 日。WD。URL:https://www.w3.org/TR/cssom-1/
[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/
[INTERSECTION-OBSERVER]
Stefan Zager;Emilio Cobos Álvarez;Traian Captan。Intersection Observer。2023 年 10 月 18 日。WD。URL:https://www.w3.org/TR/intersection-observer/
[MOTION-1]
Tab Atkins Jr.;Dirk Schulze;Jihye Hong。Motion 路径模块 1级。2024 年 11 月 5 日。WD。URL:https://www.w3.org/TR/motion-1/
[RESIZE-OBSERVER-1]
Aleks Totic;Greg Whitworth。Resize Observer。2020 年 2 月 11 日。FPWD。URL:https://www.w3.org/TR/resize-observer-1/
[RFC2119]
S. Bradner。指示 RFC 中需求级别的关键字。1997 年 3 月。最佳实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad;Tab Atkins Jr.。选择器 4级2026 年 1 月 22 日。WD。URL:https://www.w3.org/TR/selectors-4/
[STREAMS]
Adam Rice 等。Streams 标准。活标准。URL:https://streams.spec.whatwg.org/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 标准。活标准。URL:https://webidl.spec.whatwg.org/

参考文献(非规范性)

[CSS-CONDITIONAL-5]
Chris Lilley 等。CSS 条件规则模块 5级(CSS Conditional Rules Module Level 5)。2025年10月30日。工作草案(WD)。链接:https://www.w3.org/TR/css-conditional-5/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons。CSS 盒尺寸模块 4级(CSS Box Sizing Module Level 4)。2021年5月20日。工作草案(WD)。链接:https://www.w3.org/TR/css-sizing-4/
[CSS-TRANSITIONS-1]
Chris Marrin 等。CSS 过渡模块 1级(CSS Transitions Module Level 1)。2026年1月8日。工作草案(WD)。链接:https://www.w3.org/TR/css-transitions-1/
[DOM]
Anne van Kesteren。DOM 标准(DOM Standard)。实时标准(Living Standard)。 链接:https://dom.spec.whatwg.org/
[WEB-ANIMATIONS-1]
Brian Birtles 等。Web 动画(Web Animations)。2023年6月5日。工作草案(WD)。链接:https://www.w3.org/TR/web-animations-1/

属性索引

名称 取值 初始值 适用元素 继承性 %百分比 动画类型 规范顺序 计算值 新值
align-items anchor-center
align-self anchor-center
anchor-name none | <anchor-name># none 所有生成主框的元素 no n/a 离散型 依语法 按指定值
anchor-scope none | all | <anchor-name># none 所有元素 no n/a 离散型 依语法 按指定值
justify-items anchor-center
justify-self anchor-center
position-anchor normal | none | auto | <anchor-name> normal 绝对定位框 no n/a 离散型 依语法 按指定值
position-area none | <position-area> none 拥有默认锚盒的定位框 no n/a 待定 依语法 关键字 none 或一对关键字,详见
position-try <'position-try-order'>? <'position-try-fallbacks'> 见相关属性 见相关属性 见相关属性 见相关属性 见相关属性 依语法 见相关属性
position-try-fallbacks none | [ [<dashed-ident> || <try-tactic>] | <position-area> ]# none 绝对定位框 no n/a 离散型 依语法 按指定值
position-try-order normal | <try-size> normal 绝对定位框 no n/a 离散型 依语法 按指定值
position-visibility always | [ anchors-valid || anchors-visible || no-overflow ] anchors-visible 绝对定位框 no n/a 离散型 依语法 按指定值

IDL 索引

[Exposed=Window]
interface CSSPositionTryRule : CSSRule {
  readonly attribute CSSOMString name;
  [SameObject, PutForwards=cssText] readonly attribute CSSPositionTryDescriptors style;
};

[Exposed=Window]
interface CSSPositionTryDescriptors : CSSStyleDeclaration {
  attribute CSSOMString margin;
  attribute CSSOMString marginTop;
  attribute CSSOMString marginRight;
  attribute CSSOMString marginBottom;
  attribute CSSOMString marginLeft;
  attribute CSSOMString marginBlock;
  attribute CSSOMString marginBlockStart;
  attribute CSSOMString marginBlockEnd;
  attribute CSSOMString marginInline;
  attribute CSSOMString marginInlineStart;
  attribute CSSOMString marginInlineEnd;
  attribute CSSOMString margin-top;
  attribute CSSOMString margin-right;
  attribute CSSOMString margin-bottom;
  attribute CSSOMString margin-left;
  attribute CSSOMString margin-block;
  attribute CSSOMString margin-block-start;
  attribute CSSOMString margin-block-end;
  attribute CSSOMString margin-inline;
  attribute CSSOMString margin-inline-start;
  attribute CSSOMString margin-inline-end;
  attribute CSSOMString inset;
  attribute CSSOMString insetBlock;
  attribute CSSOMString insetBlockStart;
  attribute CSSOMString insetBlockEnd;
  attribute CSSOMString insetInline;
  attribute CSSOMString insetInlineStart;
  attribute CSSOMString insetInlineEnd;
  attribute CSSOMString top;
  attribute CSSOMString left;
  attribute CSSOMString right;
  attribute CSSOMString bottom;
  attribute CSSOMString inset-block;
  attribute CSSOMString inset-block-start;
  attribute CSSOMString inset-block-end;
  attribute CSSOMString inset-inline;
  attribute CSSOMString inset-inline-start;
  attribute CSSOMString inset-inline-end;
  attribute CSSOMString width;
  attribute CSSOMString minWidth;
  attribute CSSOMString maxWidth;
  attribute CSSOMString height;
  attribute CSSOMString minHeight;
  attribute CSSOMString maxHeight;
  attribute CSSOMString blockSize;
  attribute CSSOMString minBlockSize;
  attribute CSSOMString maxBlockSize;
  attribute CSSOMString inlineSize;
  attribute CSSOMString minInlineSize;
  attribute CSSOMString maxInlineSize;
  attribute CSSOMString min-width;
  attribute CSSOMString max-width;
  attribute CSSOMString min-height;
  attribute CSSOMString max-height;
  attribute CSSOMString block-size;
  attribute CSSOMString min-block-size;
  attribute CSSOMString max-block-size;
  attribute CSSOMString inline-size;
  attribute CSSOMString min-inline-size;
  attribute CSSOMString max-inline-size;
  attribute CSSOMString placeSelf;
  attribute CSSOMString alignSelf;
  attribute CSSOMString justifySelf;
  attribute CSSOMString place-self;
  attribute CSSOMString align-self;
  attribute CSSOMString justify-self;
  attribute CSSOMString positionAnchor;
  attribute CSSOMString position-anchor;
  attribute CSSOMString positionArea;
  attribute CSSOMString position-area;
};

问题索引

修正上述示例,因为现在用例已自动完成。
补一个更好的例子;目前这个例子用 anchor-center 就能轻松实现。[议题 #10776]
变换(transform)和滚动有类似的问题, 所以锚点定位通常也不会实时考虑变换的影响。 这个地方能否直接把 transform 效果也纳入?
应精确定义快照时机: 每一帧刷新前,在样式重算之前更新。
类似 记忆滚动偏移, 能否同步考虑 默认锚点元素 上的 transform?
请添加插图!
所需锚点引用 是什么? anchor() 函数未指定回退值的算, 默认锚点有时也算? 这里需要更详细的定义。
到底是 有任意 一个锚点缺失就算(隐藏), 还是 全部 锚点缺失才算? 两种做法都可能有需求, 是要统一规定还是考虑加以控制?
要确保这里对“裁剪”概念的定义 跟 View Transitions 保持一致, 那边有类似需求。
补充一个 popover 示例。
欢迎提出改进本节的建议, 尤其是作者指引与常见用法的最佳实践范例。[议题 #10311]
这个概念不应该放在本规范, 可能更适合放进 Cascade 里, 不过现在需要一份草稿来作引用。
显然这里还需要补充很多细节, 但目前“跟容器查询一样处理”就可以了。 那个行为本来也没明确定义过, 但各实现之间基本能互通吧?