CSSOM 视图模块

W3C 工作草案

关于本规范的更多详情
当前版本:
https://www.w3.org/TR/2025/WD-cssom-view-1-20250916/
最新发布版本:
https://www.w3.org/TR/cssom-view-1/
编辑草案:
https://drafts.csswg.org/cssom-view/
先前版本:
历史:
https://www.w3.org/standards/history/cssom-view-1/
反馈:
CSS 工作组问题仓库
规范内问题列表
编辑:
(Apple Inc)
(Mozilla)
历任编辑:
(Opera Software AS)
Glenn Adams (Cox Communications, Inc.)
Anne van Kesteren (Opera Software ASA)
为本规范提出修改建议:
GitHub 编辑器
历史遗留问题列表:
Bugzilla
测试套件:
https://wpt.fyi/results/css/cssom-view/

摘要

本规范引入的 API 为作者提供了一种检查与操控文档可视视图的方式。包括:获取元素布局盒的位置、通过脚本获取视口宽度,以及滚动某个元素。

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

本文档状态

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

本文档由 CSS 工作组工作草案 形式,根据 推荐标准路线 发布。 作为工作草案发布并不意味着获得 W3C 及其成员的认可。

这是一个草案文档,可能在任何时间被更新、替换或被其他文档废弃。不应将其引用为除“进行中工作”之外的其他形式。

欢迎通过 在 GitHub 提交 issue(首选)反馈意见,issue 标题中请包含规范代码 “cssom-view”,例如: “[cssom-view] …评论概要…”。所有问题与评论都会被 归档。 或者,也可发送反馈到(已归档)公共邮件列表 www-style@w3.org

本文档受 2025 年 8 月 18 日 W3C 流程文档 约束。

本文档由在 W3C 专利政策 下运作的小组制作。W3C 维护一个与该小组可交付成果相关的任何专利披露的公共列表;该页面亦包含披露专利的说明。 任何个人若实际知晓其认为包含 必要权利要求 的专利,必须依据 W3C 专利政策第 6 节 披露相关信息。

1. 背景

本规范中定义的许多特性,浏览器早已支持很长时间。本规范的目标是以所有浏览器都能实现且互操作的方式来定义这些特性。此外,规范也定义了一些新的滚动定制相关特性。

测试

基础 IDL 测试


2. 术语

本规范中使用的术语来自 DOM、CSSOM 和 HTML。[DOM] [CSSOM] [HTML]

一个元素 body(即 body 元素)在以下所有条件都为真时,被认为是 可能可滚动

注意: body 元素即使被认为是 可能可滚动,也可能没有 滚动盒。 例如,其 overflow 的使用值可能为 auto,但内容没有溢出其内容区域。

一个 滚动盒,属于 视口或元素,有两个 溢出方向,即该视口或元素的 块结束行内结束方向。 注意,初始滚动位置不一定与 滚动区域原点对齐,具体取决于 内容分布属性,参考 CSS Box Alignment 3 § 5.3 对齐溢出与滚动容器

术语 滚动区域 指的是一个 视口或元素的盒子,具体边界由该 视口或元素的 滚动盒溢出方向决定。

如果 溢出方向为… 对于 视口 对于元素
向右且向下
上边
初始包含块的上边。
右边
初始包含块的最右边,以及所有 视口后代盒子的右 外边距边的最右边。
下边
初始包含块的最下边,以及所有 视口后代盒子的下 外边距边的最下边。
左边
初始包含块的左边。
上边
元素的上 内边距边
右边
元素右 内边距边的最右边,以及所有元素后代盒子的右 外边距边的最右边(排除包含块是该元素祖先的盒子)。
下边
元素下 内边距边的最下边,以及所有元素后代盒子的下 外边距边的最下边(排除包含块是该元素祖先的盒子)。
左边
元素的左 内边距边
向左且向下
上边
初始包含块的上边。
右边
初始包含块的右边。
下边
初始包含块的最下边,以及所有 视口后代盒子的下 外边距边的最下边。
左边
初始包含块的最左边,以及所有 视口后代盒子的左 外边距边的最左边。
上边
元素的上 内边距边
右边
元素的右 内边距边
下边
元素下 内边距边的最下边,以及所有元素后代盒子的下 外边距边的最下边(排除包含块是该元素祖先的盒子)。
左边
元素左 内边距边的最左边,以及所有元素后代盒子的左 外边距边的最左边(排除包含块是该元素祖先的盒子)。
向左且向上
上边
初始包含块的最上边,以及所有 视口后代盒子的上 外边距边的最上边。
右边
初始包含块的右边。
下边
初始包含块的下边。
左边
初始包含块的最左边,以及所有 视口后代盒子的左 外边距边的最左边。
上边
元素上 内边距边的最上边,以及所有元素后代盒子的上 外边距边的最上边(排除包含块是该元素祖先的盒子)。
右边
元素的右 内边距边
下边
元素的下 内边距边
左边
元素左 内边距边的最左边,以及所有元素后代盒子的左 外边距边的最左边(排除包含块是该元素祖先的盒子)。
向右且向上
上边
初始包含块的最上边,以及所有 视口后代盒子的上 外边距边的最上边。
右边
初始包含块的最右边,以及所有 视口后代盒子的右 外边距边的最右边。
下边
初始包含块的下边。
左边
初始包含块的左边。
上边
元素上 内边距边的最上边,以及所有元素后代盒子的上 外边距边的最上边(排除包含块是该元素祖先的盒子)。
右边
元素右 内边距边的最右边,以及所有元素后代盒子的右 外边距边的最右边(排除包含块是该元素祖先的盒子)。
下边
元素的下 内边距边
左边
元素的左 内边距边

原点滚动区域的原点是,如果该 滚动区域视口,则为 初始包含块的原点;否则为元素默认滚动位置时的左上内边距边。x 坐标向右增加,y 坐标向下增加。

起始边:某个盒子或元素的一组边的起始边如下:

如果 溢出方向为向右且向下
上边和左边。
如果 溢出方向为向左且向下
上边和右边。
如果 溢出方向为向左且向上
下边和右边。
如果 溢出方向为向右且向上
下边和左边。

结束边:某个盒子或元素的一组边的结束边如下:

如果 溢出方向为向右且向下
下边和右边。
如果 溢出方向为向左且向下
下边和左边。
如果 溢出方向为向左且向上
上边和左边。
如果 溢出方向为向右且向上
上边和右边。

视觉视口是一种 视口,其 滚动区域是另一个 视口,称为 布局视口

除了滚动外,视觉视口还可能对其 布局视口应用缩放变换。 此变换应用于 布局视口的画布,但不会影响其内部坐标空间。

注意:视觉视口的缩放变换通常称为“捏合缩放(pinch-zoom)”。从概念上说,这种变换改变了 CSS 参考像素的大小,但会按比例改变布局视口的大小,从而不会导致页面内容重排。

缩放变换的幅度称为 视觉视口缩放因子

此动画展示了一个被缩放的视觉视口被“平移”(比如用户进行触摸拖动)的示例。页面被缩放后,布局视口会比视觉视口更大。

滚动增量会首先应用于视觉视口。当视觉视口到达其边界时,滚动增量会应用到布局视口。此行为由 执行滚动步骤实现。

文档 布局视口 视觉视口

VisualViewport 对象有一个 关联的文档, 这是一个 Document 对象。 它是拥有 Window 关联文档 ,该 VisualViewport 属于这个 Window。 布局视口 是该 Window 视口

在本规范要求中,display 属性的计算值为 table-columntable-column-group 的元素,必须被视为有一个关联的 盒子(分别为列或列组)。

术语 SVG 布局盒 指由 SVG 元素生成的 盒子,其不对应任何 CSS 定义的 display 类型。 (例如 盒子rect 元素生成。)

术语 变换 指 SVG 变换与 CSS 变换。[SVG11] [CSS-TRANSFORMS-1]

当某个方法或属性被称为调用另一个方法或属性时,用户代理必须调用该属性或方法的内部 API,以保证作者不能通过在 ECMAScript 中覆写属性或方法(如自定义属性或函数)来改变其行为。

除非另有说明,所有字符串比较均使用 is

2.1. CSS 像素

除非另有说明,本规范中定义的 API 的所有坐标和尺寸均以 CSS 像素为单位。[CSS-VALUES]

注意: 这不适用于如 matchMedia() 等,因为这些地方的单位已明确定义。

2.2. 缩放

有两种缩放方式:页面缩放,影响初始视口的大小;以及视觉视口的 缩放因子,类似放大镜,并不影响初始视口或实际视口。[CSS-DEVICE-ADAPT]

注意: “缩放因子”通常称为“捏合缩放(pinch-zoom)”;但也可能通过其他方式改变。例如,用户代理可能会对聚焦的输入框进行缩放以提高可读性。

2.3. Web 暴露的屏幕信息

用户代理可以选择隐藏输出设备屏幕的信息,以保护用户隐私。为确保各 API 一致处理,本规范定义了以下术语,每个术语都包含宽度和高度,原点为左上角,x、y 坐标分别向右和向下递增。

Web 暴露的屏幕区域包括以下之一:

Web 暴露的可用屏幕区域包括以下之一:

3. 通用基础设施

本规范依赖 WHATWG Infra 标准。[INFRA]

3.1. 滚动

当用户代理需要执行滚动 某个滚动盒 box 到指定位置 position,并指定一个关联元素或 伪元素 element ,可选地指定滚动行为 behavior(若省略则为 "auto"), 必须按照以下步骤进行:

  1. 中止 box 上正在进行的 平滑滚动
  2. 如果用户代理支持 scroll-behavior 属性,且以下任一条件为真:
    • behavior 为 "auto" 且 element 非空,并且其 scroll-behavior 属性计算值为 smooth
    • behaviorsmooth
    ...则对 box 执行 平滑滚动position。位置更新完成后,触发 scrollend 事件。 否则,对 box 执行 瞬时滚动position。瞬时滚动后触发 scrollend 事件。

    注意: behavior: "instant" 始终按此算法执行 瞬时滚动

    注意: 如果滚动位置因用户操作或编程调用未发生变化,也未产生任何平移,则不会触发 scrollend 事件,因为没有发生滚动。

当用户代理需要执行滚动 某个视口到指定位置 position,并可选指定滚动行为 behavior(若省略则为 "auto"), 必须按照以下步骤执行协调视口滚动:

  1. doc视口关联的 Document

  2. vvVisualViewport,其 关联文档doc

  3. maxX视口滚动盒宽度减去 vvwidth 属性值。

  4. maxY视口滚动盒高度减去 vvheight 属性值。

  5. dxposition 的水平分量减去 vvpageLeft 属性值。

  6. dyposition 的垂直分量减去 vvpageTop 属性值。

  7. visual xvvoffsetLeft 属性值。

  8. visual yvvoffsetTop 属性值。

  9. visual dx 为 min(maxX, max(0, visual x + dx)) - visual x

  10. visual dy 为 min(maxY, max(0, visual y + dy)) - visual y

  11. layout dxdx - visual dx

  12. layout dydy - visual dy

  13. elementdoc 的根元素(如有),否则为 null。

  14. 执行滚动 应用于 视口滚动盒 ,将其滚动到当前滚动位置 + (layout dx, layout dy),并将 element 作为关联元素,behavior 作为滚动行为。

  15. vv滚动盒 执行滚动 ,将其滚动到当前滚动位置 + (visual dx, visual dy),并将 element 作为关联元素,behavior 作为滚动行为。

注意: 从概念上讲,视觉视口会被滚动,直到“碰到”布局视口边缘,然后“推动”布局视口,将滚动增量应用到布局视口。但上述步骤的滚动会预先计算并按相反顺序应用,以便先滚动布局视口再滚动视觉视口。这是历史原因,以保证滚动事件顺序一致。可参见上方示例

用户对文档进行捏合缩放后,滚动鼠标滚轮请求用户代理向下滚动文档 50px。由于文档已捏合缩放,视觉视口有 20px 可滚动空间。用户代理将滚动分配为视觉视口向下滚动 20px,布局视口向下滚动 30px。
用户在移动端用户代理中查看文档。文档聚焦一个屏幕外的文本输入框,虚拟键盘弹出后缩小了视觉视口。此时用户代理必须让该元素在视觉视口中可见。用户代理会先滚动布局视口,使元素在其内可见,再滚动视觉视口,使元素对用户可见。

当滚动位置没有待更新或平移,且用户已完成手势时,滚动即完成。滚动位置更新包括鼠标滚轮平滑或瞬时滚动、键盘滚动、滚动捕捉事件、或其它导致滚动位置变化并可能插值的 API 和手势。触摸拖动或触控板滚动等用户手势,直到指针或按键释放才算完成。

当用户代理需要对 滚动盒 box进行 平滑滚动position,应以用户代理定义的方式和时长更新 box 的滚动位置。滚动完成时,box 的滚动位置必须为 position。滚动也可能被算法或用户中止

当用户代理需要对 滚动盒 box进行瞬时滚动position,应将 box 的滚动位置立即更新为 position

要对文档 document滚动到文档开头,执行以下步骤:

  1. viewportdocument 关联的视口
  2. position 为将 滚动区域的起始边viewport 的起始边对齐时 viewport 的滚动位置。
  3. 如果 positionviewport 当前滚动位置相同,且 viewport 没有正在进行的 平滑滚动,则中止后续步骤。
  4. viewport 执行滚动position, 关联元素为 document根元素(如有),否则为 null。

注意: 当跳转到 #top 片段标识符时会用到此算法,HTML 已定义。[HTML]

测试

3.2. WebIDL 值

当被要求为值 x 规范化非有限值 时,若 x 是三种特殊浮点文字值之一 (Infinity, -InfinityNaN), 则必须将 x 更改为值 0[WEBIDL]

4. Window 接口的扩展

enum ScrollBehavior { "auto", "instant", "smooth" };

dictionary ScrollOptions {
    ScrollBehavior behavior = "auto";
};
dictionary ScrollToOptions : ScrollOptions {
    unrestricted double left;
    unrestricted double top;
};

partial interface Window {
    [NewObject] MediaQueryList matchMedia(CSSOMString query);
    [SameObject, Replaceable] readonly attribute Screen screen;
    [SameObject, Replaceable] readonly attribute VisualViewport? visualViewport;

    // browsing context
    undefined moveTo(long x, long y);
    undefined moveBy(long x, long y);
    undefined resizeTo(long width, long height);
    undefined resizeBy(long x, long y);

    // viewport
    [Replaceable] readonly attribute long innerWidth;
    [Replaceable] readonly attribute long innerHeight;

    // viewport scrolling
    [Replaceable] readonly attribute double scrollX;
    [Replaceable] readonly attribute double pageXOffset;
    [Replaceable] readonly attribute double scrollY;
    [Replaceable] readonly attribute double pageYOffset;
    undefined scroll(optional ScrollToOptions options = {});
    undefined scroll(unrestricted double x, unrestricted double y);
    undefined scrollTo(optional ScrollToOptions options = {});
    undefined scrollTo(unrestricted double x, unrestricted double y);
    undefined scrollBy(optional ScrollToOptions options = {});
    undefined scrollBy(unrestricted double x, unrestricted double y);

    // client
    [Replaceable] readonly attribute long screenX;
    [Replaceable] readonly attribute long screenLeft;
    [Replaceable] readonly attribute long screenY;
    [Replaceable] readonly attribute long screenTop;
    [Replaceable] readonly attribute long outerWidth;
    [Replaceable] readonly attribute long outerHeight;
    [Replaceable] readonly attribute double devicePixelRatio;
};

当调用 matchMedia(query) 方法时,必须运行下列步骤:

  1. parsed media query list 为对 query 执行 解析 的结果。
  2. 返回一个新的 MediaQueryList 对象,其 this关联 Document 作为该对象的 document,并以 parsed media query list 作为其关联的 media query list
Tests

screen 属性必须返回与该 Screen 对象关联的 Window 对象的 Screen 对象。

注意: 通过 WindowProxy 对象访问 screen 时,在文档导航时可能会得到不同结果。

如果 关联文档fully active(完全活动) 的,则 visualViewport 属性必须返回与该 VisualViewport 对象关联的 VisualViewport 对象。否则,必须返回 null。

注意: VisualViewport 对象只对当前正在呈现其 Document 的窗口返回并有用。如果保留对某个关联文档未被呈现的 VisualViewport 的引用,则该 VisualViewport 中的值不得泄露关于浏览上下文的任何信息。

Tests

moveTo(x, y) 方法必须遵循下列步骤:

  1. 可选地,返回。

  2. targetthis相关全局对象browsing context

  3. 如果 target 不是由脚本创建的(即不是由用户动作创建的)辅助浏览上下文(auxiliary browsing context),则返回。

  4. 可选地,以用户代理定义的方式将 xy 限定,以使窗口不会移出可用空间。

  5. 移动 target 的窗口,使窗口左上角位于相对于输出设备左上角的坐标 (x, y),测量单位为 CSS pixels(正方向为右和下)。

moveBy(x, y) 方法必须遵循下列步骤:

  1. 可选地,返回。

  2. targetthis相关全局对象browsing context

  3. 如果 target 不是由脚本创建的辅助浏览上下文,则返回。

  4. 可选地,以用户代理定义的方式将 xy 限定,以使窗口不会移出可用空间。

  5. target 的窗口向右移动 xCSS pixels,并向下移动 y 个 CSS pixels。

resizeTo(width, height) 方法必须 遵循下列步骤:

  1. 可选地,返回。

  2. targetthis相关全局对象browsing context

  3. 如果 target 不是由脚本创建的辅助浏览上下文,则返回。

  4. 可选地,以用户代理定义的方式将 widthheight 限定,以使窗口不会过小或超出可用空间。

  5. 通过移动其右和下边缘来调整 target 窗口的大小,使视口的左右边距离为 widthCSS pixels,上下边距离为 height 个 CSS pixels。

  6. 可选地,以用户代理定义的方式移动 target 的窗口,使其不超出可用空间。

Tests

resizeBy(x, y) 方法必须遵循下列步骤:

  1. 可选地,返回。

  2. targetthis相关全局对象browsing context

  3. 如果 target 不是由脚本创建的辅助浏览上下文,则返回。

  4. 可选地,以用户代理定义的方式将 xy 限定,以使窗口不会过小或超出可用空间。

  5. 通过将其右边缘向右移动 xCSS pixels,并将其下边缘向下移动 y 个 CSS pixels,来调整 target 的窗口大小。

  6. 可选地,以用户代理定义的方式移动 target 的窗口,使其不超出可用空间。

innerWidth 属性必须返回包括已渲染滚动条(如有)大小在内的 视口 宽度,若不存在视口则返回零。

下面的代码片段展示了如何获取视口宽度:
var viewportWidth = innerWidth

innerHeight 属性必须返回包括已渲染滚动条(如有)大小在内的 视口 高度,若不存在视口则返回零。

scrollX 属性必须返回相对于 initial containing block 原点的 x 坐标, 即视口左侧的位置,若不存在视口则返回零。

pageXOffset 属性必须返回 scrollX 属性的值。

scrollY 属性必须返回相对于 initial containing block 原点的 y 坐标, 即视口顶部的位置,若不存在视口则返回零。

pageYOffset 属性必须返回 scrollY 属性的值。

当调用 scroll() 方法时,必须运行下列步骤:

  1. 如果以一个参数调用,请执行下列子步骤:

    1. options 为该参数。

    2. xoptionsleft 字典成员的值(若存在),否则为 视口 当前在 x 轴上的滚动位置。

    3. yoptionstop 字典成员的值(若存在),否则为 视口 当前在 y 轴上的滚动位置。

  2. 如果以两个参数调用,请执行下列子步骤:

    1. options 设为将 null 转换ScrollToOptions 字典的结果。[WEBIDL]

    2. xy 分别为传入的两个参数。

  3. xy 执行 规范化非有限值

  4. 如果不存在 视口,则中止这些步骤。

  5. viewport width 为排除滚动条宽度(如有)后的 视口 宽度。

  6. viewport height 为排除滚动条高度(如有)后的 视口 高度。

  7. 如果 视口 的溢出方向为向右
    x 为 max(0, min(x, 视口滚动区域 宽度 - viewport width))。
    如果 视口 的溢出方向为向左
    x 为 min(0, max(x, viewport width - 视口滚动区域 宽度))。
  8. 如果 视口 的溢出方向为向下
    y 为 max(0, min(y, 视口滚动区域 高度 - viewport height))。
    如果 视口 的溢出方向为向上
    y 为 min(0, max(y, viewport height - 视口滚动区域 高度))。
  9. position 为通过将 视口 滚动区域 的 x 坐标 x 与视口的左侧对齐,以及将该滚动区域的 y 坐标 y 与视口的顶部对齐,视口将会具有的滚动位置。

  10. 如果 position视口 当前的滚动位置相同,且该视口没有正在进行的 平滑滚动,则中止这些步骤。

  11. document 为该 视口 关联的 Document

  12. 对该视口执行滚动position,并以 document根元素(如有)作为关联元素,若无则为 null,滚动行为为 optionsbehavior 字段的值。

    用户代理对该步骤应使用协调的 viewportperform a scroll 还是对布局视口的滚动盒执行 perform a scroll 存在分歧。

Tests

当调用 scrollTo() 方法时,用户代理必须如同使用相同参数调用 scroll() 方法一样进行处理。

Tests

当调用 scrollBy() 方法时,用户代理必须运行下列步骤:

  1. 如果以两个参数调用,请执行下列子步骤:

    1. options 设为将 null 转换ScrollToOptions 字典的结果。[WEBIDL]

    2. xy 分别为传入的两个参数。

    3. left 字典成员的值为 x

    4. top 字典成员的值为 y

  2. lefttop 字典成员对 options 执行 规范化非有限值

  3. scrollX 的值加到 left 字典成员上。

  4. scrollY 的值加到 top 字典成员上。

  5. 如同以 options 作为唯一参数调用 scroll() 方法一样进行处理。

screenXscreenLeft 属性必须返回相对于 Web-exposed screen area 原点的客户端窗口左侧的 x 坐标,单位为 CSS pixels,若不存在则返回零。

Tests

screenYscreenTop 属性必须返回相对于 Web-exposed screen area 原点的客户端窗口顶部的 y 坐标,单位为 CSS pixels,若不存在则返回零。

outerWidth 属性必须返回客户端窗口的宽度;如果不存在客户端窗口则返回零。

outerHeight 属性必须返回客户端窗口的高度;如果不存在客户端窗口则返回零。

devicePixelRatio 属性必须返回下述 确定设备像素比率 算法的结果:

  1. 如果不存在输出设备,返回 1 并中止这些步骤。

  2. CSS pixel size 为在当前 page zoom 且使用 scale factor 为 1.0 时的 CSS pixel 的大小。

  3. device pixel size 为输出设备的设备像素的垂直尺寸。

  4. 返回 CSS pixel size 除以 device pixel size 的结果。

4.1. features 参数用于 open() 方法

HTML 定义了 open() 方法。本节定义了在 features 参数中给出的 位置 和 大小 的行为。[HTML]

要为给定的浏览上下文 target 使用一个 map tokenizedFeatures设置浏览上下文特性

  1. x 为 null。

  2. y 为 null。

  3. width 为 null。

  4. height 为 null。

  5. 如果 tokenizedFeatures["left"] 存在

    1. tokenizedFeatures["left"] 调用 解析整数规则,并将结果赋予 x

    2. 如果 x 是一个错误,则将 x 设为 0。

    3. 可选地,以用户代理定义的方式将 x 限定,使窗口不会移出 Web 暴露的可用屏幕区域

    4. 可选地,移动 target 的窗口,使窗口的左边位于相对于 Web 暴露的屏幕区域 左边缘 的水平坐标 x,以 CSS 像素(相对于 target)为度量单位。正方向为向右。

  6. 如果 tokenizedFeatures["top"] 存在

    1. tokenizedFeatures["top"] 调用 解析整数规则,并将结果赋予 y

    2. 如果 y 是一个错误,则将 y 设为 0。

    3. 可选地,以用户代理定义的方式将 y 限定,使窗口不会移出 Web 暴露的可用屏幕区域

    4. 可选地,移动 target 的窗口,使窗口的上边位于相对于 Web 暴露的屏幕区域 顶边 的垂直坐标 y,以 CSS 像素(相对于 target)为度量单位。正方向为向下。

  7. 如果 tokenizedFeatures["width"] 存在

    1. tokenizedFeatures["width"] 调用 解析整数规则,并将结果赋予 width

    2. 如果 width 是一个错误,则将 width 设为 0。

    3. 如果 width 不为 0:

      1. 可选地,以用户代理定义的方式将 width 限定,使窗口不会过小或超出 Web 暴露的可用屏幕区域

      2. 可选地,通过移动 target 的右边,使视口的左右边之间的距离为 width 个相对于 targetCSS 像素,以此来调整窗口的大小。

      3. 可选地,以用户代理定义的方式移动 target 的窗口,使其不会超出 Web 暴露的可用屏幕区域

  8. 如果 tokenizedFeatures["height"] 存在

    1. tokenizedFeatures["height"] 调用 解析整数规则,并将结果赋予 height

    2. 如果 height 是一个错误,则将 height 设为 0。

    3. 如果 height 不为 0:

      1. 可选地,以用户代理定义的方式将 height 限定,使窗口不会过小或超出 Web 暴露的可用屏幕区域

      2. 可选地,通过移动 target 的下边,使视口的上下边之间的距离为 height 个相对于 targetCSS 像素,以此来调整窗口的大小。

      3. 可选地,以用户代理定义的方式移动 target 的窗口,使其不会超出 Web 暴露的可用屏幕区域

一个 受支持的 open() 特性名 是下列之一:

width
视口的宽度。
height
视口的高度。
left
窗口的左侧位置。
top
窗口的顶部位置。

4.2. MediaQueryList 接口

本节与 HTML 中定义的 事件循环 集成。[HTML]

一个 MediaQueryList 对象在创建时具有一个关联的 media query list 和一个关联的 document

MediaQueryList 对象有一个关联的 media ,它是关联的 序列化 形式的 媒体查询列表

一个 MediaQueryList 对象具有一个关联的 matches state,当关联的 media query list 与该 document 的状态匹配时该值为 true,否则为 false。

在被要求为一个 Document doc 评估媒体查询并报告变更 时,运行下列步骤:

  1. 对于每个以创建顺序(最早创建者先)遍历的、其 documentdocMediaQueryList 对象 target,运行下列子步骤:

    1. 如果自上次运行这些步骤以来 targetmatches state 已改变,则在 target触发事件,事件名为 change,使用 MediaQueryListEvent,其 isTrusted 属性初始化为 true, 其 media 属性初始化为 targetmedia, 并且其 matches 属性初始化为 targetmatches state
一个检测视口方向变化的简单代码如下所示:
function handleOrientationChange(event) {
    if(event.matches) // landscapeelse}
var mql = matchMedia("(orientation:landscape)");
mql.onchange = handleOrientationChange;
[Exposed=Window]
interface MediaQueryList : EventTarget {
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
  undefined addListener(EventListener? callback);
  undefined removeListener(EventListener? callback);
           attribute EventHandler onchange;
};

属性 media 必须返回关联的 media

属性 matches 必须返回关联的 matches state

当调用方法 addListener(callback) 时,必须运行下列步骤:

  1. 使用 添加事件监听器 的步骤,在 this 上添加一个事件监听器,该监听器的 类型change,且其 回调callback

当调用方法 removeListener(callback) 时,必须运行下列步骤:

  1. 如果 this事件监听器列表包含 一个 事件监听器,其 类型change,其 回调callback,且 capture 为 false,则使用 移除事件监听器 的步骤,从 this 中移除该事件监听器。

注意: 本规范最初有一个自定义的回调机制,使用 addListener()removeListener(), 回调会以关联的 media query list 作为参数被调用。现在改为使用普通的事件机制。为向后兼容,addListener()removeListener() 方法基本上分别是 addEventListener()removeEventListener() 的别名,并且 change 事件会伪装成 MediaQueryList

下列为所有实现 MediaQueryList 接口的对象必须支持的 事件处理程序(及其对应的 事件处理类型),以作为 事件处理 IDL 属性

Event handler Event handler event type
onchange change
Tests
[Exposed=Window]
interface MediaQueryListEvent : Event {
  constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
};

dictionary MediaQueryListEventInit : EventInit {
  CSSOMString media = "";
  boolean matches = false;
};

属性 media 必须返回它被初始化为的值。

属性 matches 必须返回它被初始化为的值。

4.2.1. 事件摘要

本节为非规范性内容。

事件 接口 感兴趣的目标 描述
change MediaQueryListEvent MediaQueryList MediaQueryList matches state 发生变化时触发。

4.3. Screen 接口

正如其名称所示,Screen 接口表示有关输出设备屏幕的信息。

[Exposed=Window]
interface Screen {
  readonly attribute long availWidth;
  readonly attribute long availHeight;
  readonly attribute long width;
  readonly attribute long height;
  readonly attribute unsigned long colorDepth;
  readonly attribute unsigned long pixelDepth;
};

属性 availWidth 必须返回 Web 暴露的可用屏幕区域 的宽度。

属性 availHeight 必须返回 Web 暴露的可用屏幕区域 的高度。

属性 width 必须返回 Web 暴露的屏幕区域 的宽度。

属性 height 必须返回 Web 暴露的屏幕区域 的高度。

属性 colorDepthpixelDepth 应返回输出设备上每像素用于颜色的位数(不包括 alpha 通道)。如果用户代理无法返回输出设备所使用的确切位数,则应返回最接近的估计值,例如发送到显示器的帧缓冲使用的位数或任何内部表示的位数,这些值最接近输出设备将使用的值。用户代理必须返回一个至少等于 color 媒体特性乘以三的值。如果不同的颜色分量使用的位数不相等,则返回值可能大于 color 媒体特性值的三倍。如果用户代理不知道颜色深度或出于隐私原因不想返回它,应返回 24。

注意: 为了兼容性,属性 colorDepthpixelDepth 返回相同的值。

注意: 已知一些不符合规范的实现会返回 32 而不是 24。

Tests

5. Document 接口的扩展

partial interface Document {
  Element? elementFromPoint(double x, double y);
  sequence<Element> elementsFromPoint(double x, double y);
  CaretPosition? caretPositionFromPoint(double x, double y, optional CaretPositionFromPointOptions options = {});
  readonly attribute Element? scrollingElement;
};

dictionary CaretPositionFromPointOptions {
  sequence<ShadowRoot> shadowRoots = [];
};

elementFromPoint(x, y) 方法必须遵循以下步骤:

  1. 如果任一参数为负数,x大于视口宽度(不包括已呈现滚动条的大小,如果有),或y大于视口高度(不包括已呈现滚动条的大小,如果有),或者文档没有关联的视口,则返回 null 并终止这些步骤。

  2. 如果在盒子视口中能成为坐标 x,y 的命中测试目标, 应用适用于视口后代的变换后,返回关联的元素并终止这些步骤。

  3. 如果文档有根元素,则返回根元素并终止这些步骤。

  4. 返回 null。

注意:elementFromPoint() 方法不一定返回最顶部绘制的元素。例如,可以通过 CSS 属性 pointer-events 将某元素排除在命中测试目标之外。

测试

elementsFromPoint(x, y) 方法必须遵循以下步骤:

  1. sequence为一个新的空序列。

  2. 如果任一参数为负数,x大于视口宽度(不包括已呈现滚动条的大小,如果有),或y大于视口高度(不包括已呈现滚动条的大小,如果有),或者文档没有关联的视口,则返回sequence并终止这些步骤。

  3. 对于盒子视口中,以绘制顺序(从最顶部的盒子开始),能够成为坐标 x,y 的命中测试目标,即使没有重叠,应用适用于视口后代的变换后,将关联的元素添加到sequence中。

  4. 如果文档有根元素,且sequence的最后一项不是根元素,则将根元素添加到sequence中。

  5. 返回sequence

测试

caretPositionFromPoint(x, y, options) 方法必须返回运行以下步骤的结果:

  1. 如果文档没有关联的视口,返回 null。

  2. 如果任一参数为负数,x大于视口宽度(不包括已呈现滚动条的大小,如果有),y大于视口高度(不包括已呈现滚动条的大小,如果有),则返回 null。

  3. 如果在视口中的坐标 x,y 处,应用适用于视口后代的变换后,不会插入文本插入点指示器,则返回 null。

  4. 如果在视口中的坐标 x,y 处,应用适用于视口后代的变换后,文本插入点指示器会插入到也是替换元素的文本输入控件中,则返回一个插入点位置,其属性如下:

    插入点节点
    与该文本输入控件对应的节点。
    插入点偏移量
    文本插入点指示器将插入的左侧的 16 位单元数量。
  5. 否则:

    1. caretPosition为一个元组,包含caretPositionNode(一个节点)和caretPositionOffset(一个非负整数),表示应用适用于变换后的视口后代,在插入文本指示器时的位置。

    2. startNodecaretPositioncaretPositionNode,令startOffsetcaretPositioncaretPositionOffset

    3. startNode节点startNodeshadow root,并且startNode不是options["shadowRoots"]中任何一个的包含 shadow 的祖先,重复以下步骤:

      1. startOffset设置为startNode索引,在startNode宿主中。

      2. startNode设置为startNode宿主

    4. 返回一个插入点位置,其属性如下:

      1. 插入点节点设置为startNode

      2. 插入点偏移量设置为startOffset

注意:插入点位置不是实时的。

注意:命中测试的具体细节不在本规范范围内,因此elementFromPoint()caretPositionFromPoint() 的具体细节也不在范围内。命中测试有望在未来的 CSS 或 HTML 修订中被定义。

scrollingElement 属性,在获取时,必须运行以下步骤:

  1. 如果Document 处于怪异模式,执行以下子步骤:

    1. 如果body 元素存在,且不是可能滚动的,则返回body 元素并中止这些步骤。

      在此目的下, overflow:clip值在body 元素的父元素上必须视为overflow:hidden

    2. 返回 null 并中止这些步骤。

  2. 如果存在根元素,则返回根元素并中止这些步骤。

  3. 返回 null。

注意:对于总是采用 怪异模式行为的非兼容用户代理, 在 scrollTopscrollLeft 上, scrollingElement 属性也应始终返回 body 元素(或如果不存在则为 null)。 此 API 的存在是为了让 Web 开发者能正确获取用于滚动 API 的元素, 无需假设某个特定用户代理的行为,也无需通过实际滚动来判断哪个元素会滚动视口。

注意:body 元素与 HTML 的 document.body 不同,后者可能返回 frameset 元素。

测试

5.1. CaretPosition 接口

插入符号位置 指的是文本插入点指示器所在的位置。它总是关联一个插入符号节点插入符号偏移量。它由一个 CaretPosition 对象表示。

[Exposed=Window]
interface CaretPosition {
  readonly attribute Node offsetNode;
  readonly attribute unsigned long offset;
  [NewObject] DOMRect? getClientRect();
};

offsetNode 属性必须返回 插入符号节点

offset 属性必须返回 插入符号偏移量

getClientRect() 方法必须按照以下步骤执行,遇到返回值时即终止:

  1. 如果 插入符号节点是作为替换元素的文本输入控件, 且在文档中,则返回该控件中插入符号的 缩放 DOMRect 对象,插入位置由 插入符号偏移量值表示。 会应用该元素及其祖先的 变换

  2. 否则:

    1. caretRange 为一个折叠的 Range 对象,其 起始节点结束节点 都设置为 插入符号节点,其 起始偏移结束偏移 都设置为 插入符号偏移量

    2. 返回调用 caretRangeDOMRect 对象,即 getBoundingClientRect() 方法的结果。

注意:DOMRect 对象不是 实时 的。

测试

6. Element 接口的扩展

enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
dictionary ScrollIntoViewOptions : ScrollOptions {
  ScrollLogicalPosition block = "start";
  ScrollLogicalPosition inline = "nearest";
  ScrollIntoViewContainer container = "all";
};

enum ScrollIntoViewContainer { "all", "nearest" };

dictionary CheckVisibilityOptions {
    boolean checkOpacity = false;
    boolean checkVisibilityCSS = false;
    boolean contentVisibilityAuto = false;
    boolean opacityProperty = false;
    boolean visibilityProperty = false;
};

partial interface Element {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();

  boolean checkVisibility(optional CheckVisibilityOptions options = {});

  undefined scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
  undefined scroll(optional ScrollToOptions options = {});
  undefined scroll(unrestricted double x, unrestricted double y);
  undefined scrollTo(optional ScrollToOptions options = {});
  undefined scrollTo(unrestricted double x, unrestricted double y);
  undefined scrollBy(optional ScrollToOptions options = {});
  undefined scrollBy(unrestricted double x, unrestricted double y);
  attribute unrestricted double scrollTop;
  attribute unrestricted double scrollLeft;
  readonly attribute long scrollWidth;
  readonly attribute long scrollHeight;
  readonly attribute long clientTop;
  readonly attribute long clientLeft;
  readonly attribute long clientWidth;
  readonly attribute long clientHeight;
  readonly attribute double currentCSSZoom;
};

注意:checkOpacitycheckVisibilityCSS 属性是历史名称。 这些属性有与新命名方案一致的别名, 即 opacityPropertyvisibilityProperty

getClientRects() 方法被调用时,必须返回以下算法的执行结果:

  1. 如果所调用元素没有关联的 ,返回空的 DOMRectList 对象并停止算法。

  2. 如果元素有 SVG 布局盒,则返回包含一个 缩放 DOMRectList 对象的列表,包含一个描述该元素边界框的 DOMRect 对象,并应用元素及其祖先的 变换

  3. 返回包含按内容顺序排列的 DOMRect 对象的 DOMRectList ,每个对象对应一个 盒片段, 描述其边框区域(包括高或宽为零的片段),并且有如下约束:

    • 应用元素及其祖先的 变换

    • 如果调用该方法的元素 display 属性的计算值为 tableinline-table,则包含 table 盒和 caption 盒(如果有),但不包含匿名容器盒。

    • 将每个 匿名 块盒 替换为其子盒,直到最终列表中没有匿名块盒为止。

注意:DOMRect 对象由 getClientRects() 返回时不是 实时 的。

测试

getBoundingClientRect() 方法,在 某个元素 element 上调用时,必须返回 获取边界框 的结果。

要为 element 获取边界框,请运行以下步骤:
  1. list 为在 element 上调用 getClientRects() 的结果。

  2. 如果 list 为空,则返回一个 DOMRect 对象,其 xywidthheight 成员均为零。

  3. 如果 list 中所有矩形的宽或高都为零,则返回 list 中的第一个矩形。

  4. 否则,返回一个 DOMRect 对象,描述包含 list 中所有宽或高不为零的矩形的最小矩形。

注意:DOMRect 对象由 getBoundingClientRect() 返回后不是 实时的。

下方代码片段用于获取文档中第一个 div 元素的尺寸:
var example = document.getElementsByTagName("div")[0].getBoundingClientRect();
var exampleWidth = example.width;
var exampleHeight = example.height;
测试
注意:checkVisibility() 方法 提供了一套简单检查, 用于判断某个元素是否有可能“可见”。 默认采用非常简单和直接的方式, 基于 盒树, 但允许启用一些额外检查, 以满足对“可见性”更精确的需求。

checkVisibility(options) 方法 在 this 元素上调用时,必须运行以下步骤:

  1. 如果 this 没有关联的 , 返回 false。

  2. 如果 this扁平树 中的某个祖先具有 content-visibility: hidden, 返回 false。

  3. 如果 options 的字典成员 opacityPropertycheckOpacity 为 true, 且 this 或其在 扁平树 中的祖先 的 opacity 计算值为 0, 返回 false。

  4. 如果 options 的字典成员 visibilityPropertycheckVisibilityCSS 为 true, 且 this不可见的, 返回 false。

  5. 如果 options 的字典成员 contentVisibilityAuto 为 true 且 this扁平树 中的某个祖先 因 content-visibility: auto 跳过其内容, 返回 false。

  6. 返回 true。

测试

scrollIntoView(arg) 方法必须按以下步骤运行:

  1. behavior 为 "auto"。

  2. block 为 "start"。

  3. inline 为 "nearest"。

  4. containernull

  5. 如果 arg 是一个 ScrollIntoViewOptions 字典,则:

    1. behavior 设置为 optionsbehavior 字典成员。

    2. block 设置为 optionsblock 字典成员。

    3. inline 设置为 optionsinline 字典成员。

    4. 如果 optionscontainer 字典成员为 "nearest", 则将 container 设置为该元素。

  6. 否则,如果 arg 为 false,则将 block 设置为 "end"。

  7. 如果该元素没有任何关联的 , 或不可被用户代理功能访问, 则返回。

  8. 使用 behaviorblockinlinecontainer 将元素滚动到可视区域

  9. 可选地执行其他能让用户注意到该元素的操作。

组件可以用 scrollIntoView 将关注的内容滚动到指定的对齐方式:
<style>
    .scroller { overflow: auto; scroll-padding: 8px; }
    .slide { scroll-margin: 16px; scroll-snap-align: center; }
</style>
<div class="carousel">
    <div class="slides scroller">
        <div id="s1" class="slide">
        <div id="s2" class="slide">
        <div id="s3" class="slide">
    </div>
    <div class="markers">
        <button data-target="s1">1</button>
        <button data-target="s2">2</button>
        <button data-target="s3">3</button>
    </div>
</div>
<script>
    document.querySelector('.markers').addEventListener('click', (evt) => {
        const target = document.getElementById(evt.target.dataset.target);
        if (!target) return;
        // scrollIntoView 会正确对齐目标项,遵循 scroll-snap-align、
        // scroll-margin 以及滚动容器的 scroll-padding。
        target.scrollIntoView({
            // 只滚动最近的滚动容器。
            container: 'nearest',
            behavior: 'smooth'
        });
    });
</script>
测试

scroll() 方法必须运行以下步骤:

  1. 如果以一个参数调用,按以下子步骤进行:

    1. options 为该参数。

    2. optionslefttop 字典成员(如有)进行非有限值归一化

    3. xoptionsleft 字典成员的值(如有),否则为该元素当前 x 轴滚动位置。

    4. yoptionstop 字典成员的值(如有),否则为该元素当前 y 轴滚动位置。

  2. 如果以两个参数调用,按以下子步骤进行:

    1. options 为 null 转换ScrollToOptions 字典。[WEBIDL]

    2. xy 分别为参数。

    3. xy 进行非有限值归一化

    4. optionsleft 字典成员的值为 x

    5. optionstop 字典成员的值为 y

  3. document 为该元素的节点文档

  4. 如果 document 不是活动文档,终止这些步骤。

  5. windowdocumentdefaultView 属性值。

  6. 如果 window 为 null,终止这些步骤。

  7. 如果该元素是根元素document 处于怪异模式,终止这些步骤。

  8. 如果该元素是根元素,则在 window 上用 scroll() ,第一个参数为 windowscrollX,第二个参数为 y,终止这些步骤。

  9. 如果该元素是body 元素document 处于怪异模式,且该元素不是潜在可滚动,则在 window 上用 options 作为唯一参数调用 scroll(),终止这些步骤。

  10. 如果该元素没有任何关联的、没有关联的滚动盒或没有溢出,终止这些步骤。

  11. xy 为目标,按 optionsbehavior 字典成员为滚动行为,滚动该元素

当调用 scrollTo() 方法时,用户代理必须如同调用 scroll() 方法且参数相同一样处理。

当调用 scrollBy() 方法时,用户代理必须运行以下步骤:

  1. 如果以一个参数调用,按以下子步骤进行:

    1. options 为该参数。

    2. optionslefttop 字典成员(如有)进行非有限值归一化

  2. 如果以两个参数调用,按以下子步骤进行:

    1. options 为 null 转换ScrollToOptions 字典。[WEBIDL]

    2. xy 分别为参数。

    3. xy 进行非有限值归一化

    4. optionsleft 字典成员的值为 x

    5. optionstop 字典成员的值为 y

  3. scrollLeft 的值加到 left 字典成员。

  4. scrollTop 的值加到 top 字典成员。

  5. 如同以 options 作为唯一参数调用 scroll() 方法一样处理。

测试

scrollTop 属性,获取时,必须运行以下步骤:

  1. document 为该元素的节点文档

  2. 如果 document 不是活动文档,则返回 0 并终止这些步骤。

  3. windowdocumentdefaultView 属性值。

  4. 如果 window 为 null,返回 0 并终止这些步骤。

  5. 如果该元素是根元素document 处于怪异模式,返回 0 并终止这些步骤。

  6. 如果该元素是根元素,则返回 windowscrollY 值。

  7. 如果该元素是body 元素document 处于怪异模式,且该元素不是潜在可滚动,则返回 windowscrollY 值。

  8. 如果该元素没有任何关联的,返回 0 并终止这些步骤。

  9. 返回该元素滚动区域在与元素内边距边顶部对齐点的 y 坐标。

设置 scrollTop 属性时,必须运行以下步骤:

  1. y 为给定值。

  2. y 进行非有限值归一化

  3. document 为该元素的节点文档

  4. 如果 document 不是活动文档,终止这些步骤。

  5. windowdocumentdefaultView 属性值。

  6. 如果 window 为 null,终止这些步骤。

  7. 如果该元素是根元素document 处于怪异模式,终止这些步骤。

  8. 如果该元素是根元素,则在 window 上以 scroll() ,第一个参数为 windowscrollX,第二个参数为 y,终止这些步骤。

  9. 如果该元素是body 元素document 处于怪异模式,且该元素不是潜在可滚动,则在 window 上以 scroll() ,第一个参数为 scrollX,第二个参数为 y,终止这些步骤。

  10. 如果该元素没有任何关联的,没有关联的滚动盒或没有溢出,终止这些步骤。

  11. scrollLefty 为目标,滚动行为为 "auto",滚动该元素

测试

scrollLeft 属性,在获取时,必须按以下步骤返回结果:

  1. document 为该元素的 节点文档

  2. 如果 document 不是 活动文档,则返回 0 并终止这些步骤。

  3. windowdocumentdefaultView 属性值。

  4. 如果 window 为 null,返回 0 并终止这些步骤。

  5. 如果该元素是 根元素document 处于 怪异模式,则返回 0 并终止这些步骤。

  6. 如果该元素是 根元素,返回 windowscrollX

  7. 如果该元素是 body 元素document 处于 怪异模式,且该元素不是 潜在可滚动,则返回 windowscrollX

  8. 如果该元素没有任何关联的 ,则返回 0 并终止这些步骤。

  9. 返回该元素 滚动区域在与元素 内边距边左侧对齐点的 x 坐标。

设置 scrollLeft 属性时,必须运行以下步骤:

  1. x 为给定值。

  2. x 进行非有限值归一化

  3. document 为该元素的 节点文档

  4. 如果 document 不是 活动文档,终止这些步骤。

  5. windowdocumentdefaultView 属性值。

  6. 如果 window 为 null,终止这些步骤。

  7. 如果该元素是 根元素document 处于 怪异模式,终止这些步骤。

  8. 如果该元素是 根元素,在 window 上以 x 为第一个参数、windowscrollY 为第二个参数调用 scroll(),终止这些步骤。

  9. 如果该元素是 body 元素document 处于 怪异模式,且该元素不是 潜在可滚动,则在 window 上以 x 为第一个参数、windowscrollY 为第二个参数调用 scroll(),终止这些步骤。

  10. 如果该元素没有任何关联的 ,没有关联的 滚动盒 或没有溢出,终止这些步骤。

  11. 滚动该元素xscrollTop, 滚动行为为 "auto"。

测试

scrollWidth 属性必须按以下步骤返回结果:

  1. document 为该元素的 节点文档

  2. 如果 document 不是 活动文档,则返回 0 并终止这些步骤。

  3. viewport width视口的宽度(不包括滚动条宽度,如有),如果没有 视口则为 0。

  4. 如果该元素是 根元素document 不处于 怪异模式,则返回 max(视口 滚动区域宽度, viewport width)。

  5. 如果该元素是 body 元素document 处于 怪异模式,且该元素不是 潜在可滚动,则返回 max(视口 滚动区域宽度, viewport width)。

  6. 如果该元素没有任何关联的 ,则返回 0 并终止这些步骤。

  7. 返回该元素 滚动区域的宽度。

测试

scrollHeight 属性必须按以下步骤返回结果:

  1. document 为该元素的 节点文档

  2. 如果 document 不是 活动文档,则返回 0 并终止这些步骤。

  3. viewport height视口的高度(不包括滚动条高度,如有),如果没有 视口则为 0。

  4. 如果该元素是 根元素document 不处于 怪异模式,则返回 max(视口 滚动区域高度, viewport height)。

  5. 如果该元素是 body 元素document 处于 怪异模式,且该元素不是 潜在可滚动,则返回 max(视口 滚动区域高度, viewport height)。

  6. 如果该元素没有任何关联的 ,则返回 0 并终止这些步骤。

  7. 返回该元素 滚动区域的高度。

clientTop 属性必须按以下步骤运行:

  1. 如果该元素没有关联的 ,或 为内联,返回 0。

  2. 返回 未缩放border-top-width 属性的计算值加上在顶部 内边距边和顶部 边框边之间渲染的任何滚动条高度,忽略应用于该元素及其祖先的任何 变换

测试

clientLeft 属性必须按以下步骤运行:

  1. 如果该元素没有关联的 ,或 为内联,返回 0。

  2. 返回 未缩放border-left-width 属性的计算值加上在左侧 内边距边和左侧 边框边之间渲染的任何滚动条宽度,忽略应用于该元素及其祖先的任何 变换

clientWidth 属性必须按以下步骤运行:

  1. 如果该元素没有关联的 ,或 为内联,返回 0。

  2. 如果该元素是 根元素且其 节点文档不处于 怪异模式,或该元素是 body 元素且其 节点文档处于 怪异模式,则返回 视口宽度(不包括渲染的滚动条宽度,如有)。

  3. 返回 未缩放内边距边宽度(不包括在 内边距边边框边之间渲染的任何滚动条宽度),忽略应用于该元素及其祖先的任何 变换

clientHeight 属性必须按以下步骤运行:

  1. 如果该元素没有关联的 ,或 为内联,返回 0。

  2. 如果该元素是 根元素且其 节点文档不处于 怪异模式,或该元素是 body 元素且其 节点文档处于 怪异模式,则返回 视口高度(不包括渲染的滚动条高度,如有)。

  3. 返回 未缩放内边距边高度(不包括在 内边距边边框边之间渲染的任何滚动条高度),忽略应用于该元素及其祖先的任何 变换

currentCSSZoom 属性必须返回该元素的 有效缩放,如果该元素未被 渲染则返回 1.0。

测试

6.1. Element 滚动成员

确定滚动到可视区域的位置,对于一个 target,它可以是 Element伪元素Range, 并且有一个滚动行为 behavior、 块流方向位置 block、 行内基准方向位置 inline, 以及一个滚动盒 scrolling box, 按以下步骤进行:

  1. target bounding border box 为调用 Element 的 getBoundingClientRect() 返回的盒, 如果 targetElement,或调用 Range 的 getBoundingClientRect(), 如果 targetRange

  2. scrolling box edge Ascrolling box块流方向上的开始边,element edge Atarget bounding border box 在同一物理边上的边。

  3. scrolling box edge Bscrolling box块流方向上的结束边,element edge Btarget bounding border box 在同一物理边上的边。

  4. scrolling box edge Cscrolling box行内基准方向上的开始边,element edge Ctarget bounding border box 在同一物理边上的边。

  5. scrolling box edge Dscrolling box行内基准方向上的结束边,element edge Dtarget bounding border box 在同一物理边上的边。

  6. element heightelement edge Aelement edge B 之间的距离。

  7. scrolling box heightscrolling box edge Ascrolling box edge B 之间的距离。

  8. element widthelement edge Celement edge D 之间的距离。

  9. scrolling box widthscrolling box edge Cscrolling box edge D 之间的距离。

  10. positionscrolling box 按如下步骤应有的滚动位置:

    1. 如果 block 为 "start",则将 element edge Ascrolling box edge A 对齐。

    2. 否则,如果 block 为 "end",则将 element edge Bscrolling box edge B 对齐。

    3. 否则,如果 block 为 "center",则将 target bounding border box 的中心与 scrolling box 的中心在块流方向对齐。

    4. 否则,block 为 "nearest":

      如果 element edge Aelement edge B 都在 scrolling box edge Ascrolling box edge B 之外
      不做任何操作。
      如果 element edge Ascrolling box edge A 之外且 element height 小于 scrolling box height
      如果 element edge Bscrolling box edge B 之外且 element height 大于 scrolling box height
      element edge Ascrolling box edge A 对齐。
      如果 element edge Ascrolling box edge A 之外且 element height 大于 scrolling box height
      如果 element edge Bscrolling box edge B 之外且 element height 小于 scrolling box height
      element edge Bscrolling box edge B 对齐。
    5. 如果 inline 为 "start",则将 element edge Cscrolling box edge C 对齐。

    6. 否则,如果 inline 为 "end",则将 element edge Dscrolling box edge D 对齐。

    7. 否则,如果 inline 为 "center",则将 target bounding border box 的中心与 scrolling box 的中心在行内基准方向对齐。

    8. 否则,inline 为 "nearest":

      如果 element edge Celement edge D 都在 scrolling box edge Cscrolling box edge D 之外
      不做任何操作。
      如果 element edge Cscrolling box edge C 之外且 element width 小于 scrolling box width
      如果 element edge Dscrolling box edge D 之外且 element width 大于 scrolling box width
      element edge Cscrolling box edge C 对齐。
      如果 element edge Cscrolling box edge C 之外且 element width 大于 scrolling box width
      如果 element edge Dscrolling box edge D 之外且 element width 小于 scrolling box width
      element edge Dscrolling box edge D 对齐。
    9. 如果 targetElement,且目标元素定义了 滚动捕捉位置, 则如果其最近的 滚动容器滚动捕捉容器, 用户代理必须将结果 position 捕捉到该元素的某个 滚动捕捉位置; 即使 滚动容器样式为 scroll-snap-type: none,用户代理也可以这么做。

    10. 返回 position

将目标滚动到可视区域 target, 可以是 Element伪元素Range, 并带有滚动行为 behavior、 块流方向位置 block、 行内基准方向位置 inline, 以及一个可选的包含 Element,用于到达 container 后停止滚动, 按以下步骤运行:

  1. 对每个作为祖先的元素或建立了 视口滚动盒 scrolling box, 按从最内到最外 滚动盒的顺序,运行以下子步骤:

    1. 如果与 target 关联的 Document 与与该元素或 视口关联的 Document 不同源,则终止这些步骤。

    2. position 为运行确定滚动到可视区域的位置流程的结果, 以 targetbehaviorblockinlinescrolling box 为参数。

    3. 如果 position 不等于 scrolling box 当前的滚动位置, 或 scrolling box 有正在进行的平滑滚动

      1. 如果 scrolling box 关联的是元素
        执行滚动到该元素的 scrolling box,使其到达 position, 并以该元素作为关联元素,behavior 作为滚动行为。
        如果 scrolling box 关联的是 视口
        1. document视口关联的 Document

        2. root elementdocument根元素,如有则为其,否则为 null。

        3. 执行滚动视口position, 以 root element 作为关联元素,behavior 作为滚动行为。

    4. 如果 container 不为 null,且 scrolling box包含 container 的 shadow-including 祖先, 或 scrolling box视口,其 document包含 container 的 shadow-including 祖先, 则终止这些步骤。

滚动一个元素(或伪元素elementx,y,可选地带有滚动行为behavior(如果未指定则为"auto"),意味着:

  1. boxelement 关联的 滚动盒

  2. 如果 box 具有向右的溢出方向
    x 为 max(0, min(x, element 滚动区域宽度 - element 内边距边宽度))。
    如果 box 具有向左的溢出方向
    x 为 min(0, max(x, element 内边距边宽度 - element 滚动区域宽度))。
  3. 如果 box 具有向下的溢出方向
    y 为 max(0, min(y, element 滚动区域高度 - element 内边距边高度))。
    如果 box 具有向上的溢出方向
    y 为 min(0, max(y, element 内边距边高度 - element 滚动区域高度))。
  4. positionbox 对齐 滚动区域的 x 坐标xbox的左侧, 并将 滚动区域的 y 坐标y对齐到 box的顶部。

  5. 如果 positionbox当前滚动位置相同,且 box没有正在进行的平滑滚动,则终止这些步骤。

  6. 执行滚动boxposition, 并且以 element 作为关联元素,behavior 作为滚动行为。

7. HTMLElement 接口的扩展

partial interface HTMLElement {
  readonly attribute Element? scrollParent;
  readonly attribute Element? offsetParent;
  readonly attribute long offsetTop;
  readonly attribute long offsetLeft;
  readonly attribute long offsetWidth;
  readonly attribute long offsetHeight;
};

scrollParent 属性必须按以下步骤返回结果:

  1. 如符合下列任一条件,则返回 null 并终止本算法:

  2. ancestor 为该元素在扁平树中的包含块,并重复以下子步骤:

    1. 如果 ancestor初始包含块,则返回该元素所属文档的 scrollingElement, 如果未被 closed-shadow-hidden 隐藏,否则返回 null。

    2. 如果 ancestor 未被 closed-shadow-hidden 隐藏, 且是 滚动容器,则终止算法并返回 ancestor

    3. 如果 ancestorposition 属性的计算值为 fixed, 且没有祖先建立了固定定位的 包含块,则终止算法并返回 null。

    4. ancestorancestor扁平树中的包含块

测试

offsetParent 属性必须按以下步骤返回结果:

  1. 如符合下列任一条件,则返回 null 并终止本算法:

  2. ancestor 为该元素在扁平树中的父节点,并重复以下子步骤:

    1. 如果 ancestorclosed-shadow-hidden 隐藏, 且其 position 属性的计算值为 fixed, 且没有祖先建立了固定定位的 包含块,则终止算法并返回 null。

    2. 如果 ancestor 未被 closed-shadow-hidden 隐藏, 且满足下列至少一项,则终止算法并返回 ancestor

      • 该元素在固定定位的 包含块中,且 ancestor 是固定定位后代的包含块。

      • 该元素不在固定定位的 包含块中,且:

        • ancestor 是绝对定位后代的包含块(无论是否有绝对定位后代)。

        • 它是 body 元素

        • 该元素的 position 属性的计算值为 static, 且该祖先是如下 HTML 元素之一:tdthtable

      • 该元素与 ancestor有效缩放不同。

    3. 如果 ancestor扁平树中已无父节点,则终止算法并返回 null。

    4. ancestor 为其在扁平树中的父节点。

测试

offsetTop 属性必须按以下步骤返回结果:

  1. 如果该元素是 body 元素,或没有任何关联的 ,则返回 0 并终止算法。

  2. 如果该元素的 offsetParent 为 null,则返回该元素第一个关联 边框边顶部的 未缩放 y 坐标, 相对于 初始包含块原点,忽略应用于该元素及其祖先的任何 变换,并终止算法。

  3. 返回以下结果:用该元素第一个关联 边框边顶部的 未缩放 y 坐标 减去 offsetParent 的第一个关联 内边距边顶部的 y 坐标, 相对于 初始包含块原点, 忽略应用于该元素及其祖先的任何 变换

    注意:由多个行盒组成的内联元素,只考虑其第一个关联

测试

offsetLeft 属性必须按以下步骤返回结果:

  1. 如果该元素是 body 元素,或没有任何关联的 ,则返回 0 并终止算法。

  2. 如果该元素的 offsetParent 为 null,则返回该元素第一个关联 边框边左侧的 未缩放 x 坐标, 相对于 初始包含块原点,忽略应用于该元素及其祖先的任何 变换,并终止算法。

  3. 返回以下结果:用该元素第一个关联 边框边左侧的 未缩放 x 坐标 减去 offsetParent 的第一个关联 内边距边左侧的 x 坐标, 相对于 初始包含块原点, 忽略应用于该元素及其祖先的任何 变换

offsetWidth 属性必须按以下步骤返回结果:

  1. 如果该元素没有任何关联的 ,则返回 0 并终止算法。

  2. 返回该元素 主盒生成的所有片段的 边框盒的轴对齐包围盒的 未缩放宽度, 忽略应用于该元素及其祖先的任何 变换

    如果该元素的 主盒是被 块级后代“分割”的 行内级盒, 还要包含这些 块级后代生成的片段, 除非它们宽度或高度为零。

测试

offsetHeight 属性必须按以下步骤返回结果:

  1. 如果该元素没有任何关联的 ,则返回 0 并终止算法。

  2. 返回该元素 主盒生成的所有片段的 边框盒的轴对齐包围盒的 未缩放高度, 忽略应用于该元素及其祖先的任何 变换

    如果该元素的 主盒是被 块级后代“分割”的 行内级盒, 还要包含这些 块级后代生成的片段, 除非它们宽度或高度为零。

8. HTMLImageElement 接口的扩展

partial interface HTMLImageElement {
  readonly attribute long x;
  readonly attribute long y;
};

x 属性,在获取时,必须返回该元素第一个关联 缩放后的左边 边框边的 x 坐标, 该坐标相对于 初始包含块的原点,忽略应用于该元素及其祖先的 变换,若没有 则返回 0。

y 属性,在获取时,必须返回该元素第一个关联 缩放后的顶部 边框边的 y 坐标, 该坐标相对于 初始包含块的原点,忽略应用于该元素及其祖先的 变换,若没有 则返回 0。

测试

9. Range 接口的扩展

partial interface Range {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();
};

getClientRects() 方法在调用时,如果该 range 不在文档中,必须返回一个空的 DOMRectList 对象,否则返回一个 DOMRectList 对象, 其中包含一组按内容顺序排列的 DOMRect 对象,并满足如下约束:

注意:DOMRect 对象由 getClientRects() 返回后不是 实时的。

测试

getBoundingClientRect() 方法在调用时,必须返回如下算法结果:

  1. list 为对同一个 range 调用 getClientRects() 的结果。

  2. 如果 list 为空,则返回一个 DOMRect 对象,其 xywidthheight 成员均为零。

  3. 如果 list 中所有矩形的宽或高都为零,则返回 list 中的第一个矩形。

  4. 否则,返回一个 DOMRect 对象,描述包含 list 中所有宽或高不为零的矩形的最小矩形。

注意:DOMRect 对象由 getBoundingClientRect() 返回后不是 实时的。

测试

10. MouseEvent 接口的扩展

对象 IDL 片段重新定义了部分成员。我们能否解决此问题?

partial interface MouseEvent {
  readonly attribute double screenX;
  readonly attribute double screenY;
  readonly attribute double pageX;
  readonly attribute double pageY;
  readonly attribute double clientX;
  readonly attribute double clientY;
  readonly attribute double x;
  readonly attribute double y;
  readonly attribute double offsetX;
  readonly attribute double offsetY;
};

partial dictionary MouseEventInit {
  double screenX = 0.0;
  double screenY = 0.0;
  double clientX = 0.0;
  double clientY = 0.0;
};
测试

screenX 属性,获取时必须返回事件发生位置相对于 Web公开屏幕区域原点的 x 坐标。

screenY 属性,获取时必须返回事件发生位置相对于 Web公开屏幕区域原点的 y 坐标。

pageX 属性必须按以下步骤:

  1. 如果事件的 dispatch flag 已设置,返回事件发生位置相对于 初始包含块原点的水平坐标,并终止这些步骤。

  2. offset 为事件关联的 scrollX 属性值(如果有关联的 Window 对象则取其值,否则为0)。

  3. 返回 offset 与事件的 clientX 属性值之和。

pageY 属性必须按以下步骤:

  1. 如果事件的 dispatch flag 已设置,返回事件发生位置相对于 初始包含块原点的垂直坐标,并终止这些步骤。

  2. offset 为事件关联的 scrollY 属性值(如果有关联的 Window 对象则取其值,否则为0)。

  3. 返回 offset 与事件的 clientY 属性值之和。

clientX 属性,获取时必须返回事件发生位置相对于 视口原点的 x 坐标。

clientY 属性,获取时必须返回事件发生位置相对于 视口原点的 y 坐标。

x 属性,获取时必须返回 clientX 的值。

y 属性,获取时必须返回 clientY 的值。

offsetX 属性必须按以下步骤:

  1. 如果事件的 dispatch flag 已设置,返回事件发生位置相对于目标节点 内边距边的 x 坐标,忽略应用于元素及其祖先的 变换,并终止这些步骤。

  2. 返回事件的 pageX 属性值。

测试

offsetY 属性必须按以下步骤:

  1. 如果事件的 dispatch flag 已设置,返回事件发生位置相对于目标节点 内边距边的 y 坐标,忽略应用于元素及其祖先的 变换,并终止这些步骤。

  2. 返回事件的 pageY 属性值。

11. 几何

11.1. GeometryUtils 接口

enum CSSBoxType { "margin", "border", "padding", "content" };
dictionary BoxQuadOptions {
  CSSBoxType box = "border";
  GeometryNode relativeTo; // XXX default document (i.e. viewport)
};

dictionary ConvertCoordinateOptions {
  CSSBoxType fromBox = "border";
  CSSBoxType toBox = "border";
};

interface mixin GeometryUtils {
  sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
  DOMQuad convertQuadFromNode(DOMQuadInit quad, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMQuad convertRectFromNode(DOMRectReadOnly rect, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMPoint convertPointFromNode(DOMPointInit point, GeometryNode from, optional ConvertCoordinateOptions options = {}); // XXX z,w turns into 0
};

Text includes GeometryUtils; // like Range
Element includes GeometryUtils;
CSSPseudoElement includes GeometryUtils;
Document includes GeometryUtils;

typedef (Text or Element or CSSPseudoElement or Document) GeometryNode;

getBoxQuads(options) 方法必须运行以下步骤:

  1. DOM 顺序

    p1 = 即使在 RTL 下也是左上

    缩放为 0 时除以零,返回 0x0

    不允许跨 frame,抛出 WrongDocumentError?

    点是被平面化的(3D变换),z=0。类似 getClientRect

    测试块在内联

    伪元素 before/after 是元素的子节点

    viewport box 都一样

测试

convertQuadFromNode(quad, from, options) 方法必须运行以下步骤:

  1. ...

convertRectFromNode(rect, from, options) 方法必须运行以下步骤:

  1. ...

convertPointFromNode(point, from, options) 方法必须运行以下步骤:

  1. ...

12. VisualViewport

12.1. VisualViewport 接口

[Exposed=Window]
interface VisualViewport : EventTarget {
  readonly attribute double offsetLeft;
  readonly attribute double offsetTop;

  readonly attribute double pageLeft;
  readonly attribute double pageTop;

  readonly attribute double width;
  readonly attribute double height;

  readonly attribute double scale;

  attribute EventHandler onresize;
  attribute EventHandler onscroll;
  attribute EventHandler onscrollend;
};

offsetLeft 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口左边缘到布局视口左边缘的偏移。

offsetTop 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口上边缘到布局视口上边缘的偏移。

pageLeft 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口左边缘到初始包含块布局视口文档的左边缘的偏移。

pageTop 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口上边缘到初始包含块布局视口文档的上边缘的偏移。

width 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口的宽度,排除任何渲染的固定在视觉视口上的垂直经典滚动条的宽度。

注意:由于该值以 CSS 像素返回,如果 页面缩放缩放因子增加,则该值会减小。

注意:固定在视觉视口上的滚动条不会随着视觉视口缩放和移动而改变尺寸或位置。由于该值是 CSS 像素,排除滚动条宽度时,用户代理必须按 CSS 像素测量滚动条大小。也就是说,排除量在放大时减少,缩小时增加。

height 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0。

  2. 否则,返回视觉视口的高度,排除任何渲染的固定在视觉视口上的水平经典滚动条的高度。

scale 属性必须运行以下步骤:

  1. 如果视觉视口关联文档不是完全激活,返回 0 并终止步骤。

  2. 如果没有输出设备,返回 1 并终止步骤。

  3. 否则,返回视觉视口缩放因子

onresize事件处理器 IDL 属性,用于 resize 事件。

onscroll事件处理器 IDL 属性,用于 scroll 事件。

onscrollend事件处理器 IDL 属性,用于 scrollend 事件。

13. 事件

13.1. 视口缩放

本节与 HTML 中定义的 事件循环 集成。[HTML]

当要求对 Document doc 运行缩放步骤时,执行以下步骤:

  1. 如果 doc视口宽度或高度发生了变化 (例如用户调整了浏览器窗口大小, 或改变了 页面缩放, 或 iframe 元素的尺寸被更改), 自上次运行这些步骤以来, 触发一个名为 resize 的事件, 目标是与 doc 关联的 Window 对象。

  2. 如果与 doc 关联的 VisualViewportscalewidthheight 属性自上次运行这些步骤以来发生了变化, 触发一个名为 resize 的事件, 目标是 VisualViewport

测试

13.2. 滚动

本节与 HTML 中定义的 事件循环 集成。[HTML]

每个 Document 关联一个 待触发滚动事件目标列表,初始为空。

每个 Document 关联一个 待触发滚动结束事件目标列表,初始为空。

每当 视口被滚动(无论是因用户交互还是 API),用户代理必须运行以下步骤:

  1. doc视口关联的 Document

  2. 如果 doc捕捉容器, 则为 docdoc最终捕捉目标(块轴为 newBlockTarget,行内轴为 newInlineTarget)运行更新 scrollsnapchanging 目标的步骤。

  3. 如果 doc 已在其 待触发滚动事件目标列表中,则中止这些步骤。

  4. doc 添加到其 待触发滚动事件目标列表

每当一个元素被滚动(无论是因用户交互还是 API),用户代理必须运行以下步骤:

  1. doc 为该元素的 节点文档

  2. 如果该元素是 捕捉容器, 则为该元素以其最终捕捉目标(块轴为 newBlockTarget,行内轴为 newInlineTarget)运行更新 scrollsnapchanging 目标的步骤。

  3. 如果该元素已在 doc待触发滚动事件目标列表中,则中止这些步骤。

  4. 将该元素添加到 doc待触发滚动事件目标列表

每当 视觉视口被滚动(无论是因用户交互还是 API),用户代理必须运行以下步骤:

  1. vv 为被滚动的 VisualViewport 对象。

  2. docvv关联文档

  3. 如果 vv 已在 doc待触发滚动事件目标列表中,则中止这些步骤。

  4. vv 添加到 doc待触发滚动事件目标列表

当要求对 Document doc 运行滚动事件步骤时,执行以下步骤:

  1. doc 运行分发待触发 scrollsnapchanging 事件的步骤。

  2. 对于 doc待触发滚动事件目标列表中的每个 target,按添加顺序运行以下子步骤:

    1. 如果 targetDocument触发名为 scroll 的冒泡事件于 target

    2. 否则,触发名为 scroll 的事件于 target

  3. 清空 doc待触发滚动事件目标列表

  4. doc 运行分发待触发 scrollsnapchange 事件的步骤。

每当滚动完成时,用户代理必须运行以下步骤:

scrollend 事件的分发顺序是什么?是根据滚动开始顺序还是滚动完成顺序?

  1. 对于每个被滚动的滚动盒 box

    1. 如果 box 属于 视口,令 doc视口关联的 Documenttarget视口。 如果 box 属于 VisualViewport,令 docVisualViewport关联文档targetVisualViewport。 否则,box 属于一个元素,令 doc 为元素的 节点文档target 为该元素。

    2. 如果 box 属于 捕捉容器 snapcontainer, 为 snapcontainer 运行更新 scrollsnapchange 目标的步骤。

    3. 如果 target 已在 doc待触发滚动结束事件目标列表中,则中止这些步骤。

    4. target 添加到 doc待触发滚动结束事件目标列表

  2. doc 运行分发待触发 scrollsnapchange 目标的步骤。

  3. 对于 doc待触发滚动结束事件目标列表中的每个 target,按添加顺序运行以下子步骤:

    1. 如果 targetDocument触发名为 scrollend 的冒泡事件于 target

    2. 否则,触发名为 scrollend 的事件于 target

  4. 清空 doc待触发滚动结束事件目标列表

13.3. 事件摘要

本节为非规范性内容。

事件 接口 关注目标 描述
resize Event Window, VisualViewport Window视口被缩放时触发。VisualViewport视觉视口 被缩放或 布局视口被缩放时触发。
scroll Event VisualViewport, Document, 元素 VisualViewportDocument 或元素被滚动时触发,分别对应 VisualViewport视口 或元素被滚动。
scrollend Event Document, 元素, VisualViewport VisualViewportDocument 或元素的滚动结束时触发:VisualViewport视口 或元素已滚动,滚动序列已结束且所有滚动偏移变更已应用。

14. 布局后状态快照

部分 CSS 特性会将布局后的状态(如滚动位置)用作下一轮样式和布局更新的输入。

当要求对 Document doc 运行布局后状态快照步骤时,执行以下步骤:

  1. 对每个需要快照布局后状态的 CSS 特性,在 doc 中快照相关状态。

快照的状态由其他规范定义。这些步骤不得使 doc 或其他 Document 失效,以至于其他布局后快照步骤能观察到此次快照。因此,快照的顺序不应影响结果。

15. 隐私注意事项

Screen 接口会暴露用户显示配置的信息,可能被用于指纹识别算法。用户代理可选择隐藏或量化屏幕尺寸或配置信息,以保护用户隐私。

MouseEvent 包含事件的屏幕相对坐标信息。用户代理可以将这些属性设置为模糊真实屏幕位置的值,以保护用户隐私。

16. 安全注意事项

本规范暂无新的安全注意事项被报告。

17. 变更

本节记录了本规范各版本之间的一些变更。该节并不详尽。一般不会列出 bug 修复和编辑性变更。

2016年3月17日工作草案之后的变更

2013年12月17日工作草案之后的变更

2011年8月4日工作草案之后的变更

2009年8月4日工作草案之后的变更

2008年2月22日工作草案之后的变更

18. 致谢

编辑们感谢 Alan Stearns、Alexey Feldgendler、Antonio Gomes、Björn Höhrmann、Boris Zbarsky、Chris Rebert、Corey Farwell、Dan Bates、David Vest、Elliott Sprehn、Garrett Smith、Henrik Andersson、Hallvord R. M. Steen、Kang-Hao Lu、Koji Ishii、Leif Arne Storset、Luiz Agostini、Maciej Stachowiak、Michael Dyck、Mike Wilson、Morten Stenshorne、Olli Pettay、Pavel Curtis、Peter-Paul Koch、Rachel Kmetz、Rick Byers、Robert O’Callahan、Sam Weinig、Scott Johnson、Sebastian Zartner、Stewart Brodie、Sylvain Galineau、Tab Atkins、Tarquin Wilton-Jones、Thomas Moore、Thomas Shinnick 以及 Xiaomei Ji 对本文档的贡献。

特别感谢最早在 Windows Internet Explorer 浏览器中广泛部署并实现本规范中许多特性的微软员工。

一致性

文档约定

规范性要求通过描述性断言和 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" 标记,例如: UA 必须提供可访问性替代方案。

测试

与本规范内容相关的测试可能会以 “测试” 区块形式记录在此类块中。此类区块均为非规范性内容。


一致性类别

本规范定义了三类一致性类别:

样式表
一个 CSS 样式表
渲染器
解释样式表语义并渲染相关文档的 UA
编辑工具
编写样式表的 UA

如果样式表中使用本模块定义语法的所有语句,均符合通用 CSS 语法和本模块定义的各特性语法,则其符合本规范。

渲染器符合本规范,需按相关规范解释样式表,支持本规范定义的所有特性,正确解析并按要求渲染文档。但由于设备限制导致 UA 无法正确渲染文档,并不意味着 UA 不符合规范(例如 UA 不要求在单色显示器上渲染颜色)。

编辑工具符合本规范,需编写符合通用 CSS 语法及本模块各特性语法的样式表,并满足本模块描述的所有其他样式表合规要求。

部分实现

为了让作者能够利用前向兼容的解析规则分配回退值,CSS 渲染器必须将任何没有可用支持级别的 at-规则、属性、属性值、关键字及其他语法结构视为无效(并 适当忽略)。尤其是,用户代理不得在单个多值属性声明中有选择地忽略不支持的组件值而保留支持的值:如果任何值被视为无效(不支持的值必须如此处理),CSS 要求整个声明被忽略。

不稳定与专有特性的实现

为避免与未来稳定 CSS 特性冲突,CSSWG 推荐遵循最佳实践,以实现不稳定特性和专有扩展

非实验性实现

当规范进入候选推荐阶段后,可以进行非实验性实现,且实现者应发布任何已按规范正确实现并通过验证的 CR 级特性的无前缀实现。

为确保和维护 CSS 在不同实现间的互操作性,CSS 工作组要求非实验性 CSS 渲染器提交实现报告(如有需要,还需提交用于该报告的测试用例)至 W3C,方可发布任何 CSS 特性的无前缀实现。提交给 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-BACKGROUNDS-3]
Elika Etemad;Brad Kemper。CSS 背景和边框模块第3级。2024年3月11日。CRD。URL:https://www.w3.org/TR/css-backgrounds-3/
[CSS-BORDERS-4]
Elika Etemad等。CSS 边框和盒装饰模块第4级。2025年7月22日。FPWD。URL:https://www.w3.org/TR/css-borders-4/
[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-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-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-DEVICE-ADAPT]
Florian Rivoal;Emilio Cobos Álvarez。CSS 视口模块第1级。2024年1月25日。FPWD。URL:https://www.w3.org/TR/css-viewport-1/
[CSS-DISPLAY-4]
Elika Etemad;Tab Atkins Jr.。CSS 显示模块第4级。2024年12月19日。FPWD。URL:https://www.w3.org/TR/css-display-4/
[CSS-OVERFLOW-3]
Elika Etemad;Florian Rivoal。CSS 溢出模块第3级。2023年3月29日。WD。URL:https://www.w3.org/TR/css-overflow-3/
[CSS-POSITION-3]
Elika Etemad;Tab Atkins Jr.。CSS 定位布局模块第3级。2025年3月11日。WD。URL:https://www.w3.org/TR/css-position-3/
[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-SCROLL-SNAP-1]
Matt Rakow等。CSS 滚动捕捉模块第1级。2021年3月11日。CR。URL:https://www.w3.org/TR/css-scroll-snap-1/
[CSS-SCROLL-SNAP-2]
Elika Etemad;Tab Atkins Jr.;Adam Argyle。CSS 滚动捕捉模块第2级。2024年7月23日。FPWD。URL:https://www.w3.org/TR/css-scroll-snap-2/
[CSS-TEXT-3]
Elika Etemad;Koji Ishii;Florian Rivoal。CSS 文本模块第3级。2024年9月30日。CRD。URL:https://www.w3.org/TR/css-text-3/
[CSS-TEXT-4]
Elika Etemad等。CSS 文本模块第4级。2024年5月29日。WD。URL:https://www.w3.org/TR/css-text-4/
[CSS-TRANSFORMS-1]
Simon Fraser等。CSS 变换模块第1级。2019年2月14日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[CSS-VALUES]
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-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]
Daniel Glazman;Emilio Cobos Álvarez。CSS 对象模型(CSSOM)。2021年8月26日。WD。URL:https://www.w3.org/TR/cssom-1/
[CSSOM-VIEW-1]
Simon Pieters。CSSOM 视图模块。2016年3月17日。WD。URL:https://www.w3.org/TR/cssom-view-1/
[DOM]
Anne van Kesteren。DOM 标准。Living Standard。URL:https://dom.spec.whatwg.org/
[GEOMETRY-1]
Simon Pieters;Chris Harrelson。几何接口模块第1级。2018年12月4日。CR。URL:https://www.w3.org/TR/geometry-1/
[HTML]
Anne van Kesteren等。HTML 标准。Living Standard。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola。Infra 标准。Living Standard。URL:https://infra.spec.whatwg.org/
[MEDIAQUERIES-5]
Dean Jackson等。媒体查询第5级。2021年12月18日。WD。URL:https://www.w3.org/TR/mediaqueries-5/
[RFC2119]
S. Bradner。用于在RFC中指示要求级别的关键词。1997年3月。最佳当前实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad;Tab Atkins Jr.。选择器第4级。2022年11月11日。WD。URL:https://www.w3.org/TR/selectors-4/
[SVG11]
Erik Dahlström等。可缩放矢量图(SVG) 1.1 第二版。2011年8月16日。REC。URL:https://www.w3.org/TR/SVG11/
[SVG2]
Amelia Bellamy-Royds等。可缩放矢量图(SVG) 2。2018年10月4日。CR。URL:https://www.w3.org/TR/SVG2/
[UIEVENTS]
Gary Kacmarcik;Travis Leithead。UI 事件。2024年9月7日。WD。URL:https://www.w3.org/TR/uievents/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 标准。Living Standard。URL:https://webidl.spec.whatwg.org/

参考性引用

[CSS-UI-4]
Florian Rivoal。CSS 基本用户界面模块第4级。2021年3月16日。WD。URL:https://www.w3.org/TR/css-ui-4/
[CSS-WRITING-MODES-3]
Elika Etemad;Koji Ishii。CSS 书写模式第3级。2019年12月10日。REC。URL:https://www.w3.org/TR/css-writing-modes-3/

IDL 索引

enum ScrollBehavior { "auto", "instant", "smooth" };

dictionary ScrollOptions {
    ScrollBehavior behavior = "auto";
};
dictionary ScrollToOptions : ScrollOptions {
    unrestricted double left;
    unrestricted double top;
};

partial interface Window {
    [NewObject] MediaQueryList matchMedia(CSSOMString query);
    [SameObject, Replaceable] readonly attribute Screen screen;
    [SameObject, Replaceable] readonly attribute VisualViewport? visualViewport;

    // browsing context
    undefined moveTo(long x, long y);
    undefined moveBy(long x, long y);
    undefined resizeTo(long width, long height);
    undefined resizeBy(long x, long y);

    // viewport
    [Replaceable] readonly attribute long innerWidth;
    [Replaceable] readonly attribute long innerHeight;

    // viewport scrolling
    [Replaceable] readonly attribute double scrollX;
    [Replaceable] readonly attribute double pageXOffset;
    [Replaceable] readonly attribute double scrollY;
    [Replaceable] readonly attribute double pageYOffset;
    undefined scroll(optional ScrollToOptions options = {});
    undefined scroll(unrestricted double x, unrestricted double y);
    undefined scrollTo(optional ScrollToOptions options = {});
    undefined scrollTo(unrestricted double x, unrestricted double y);
    undefined scrollBy(optional ScrollToOptions options = {});
    undefined scrollBy(unrestricted double x, unrestricted double y);

    // client
    [Replaceable] readonly attribute long screenX;
    [Replaceable] readonly attribute long screenLeft;
    [Replaceable] readonly attribute long screenY;
    [Replaceable] readonly attribute long screenTop;
    [Replaceable] readonly attribute long outerWidth;
    [Replaceable] readonly attribute long outerHeight;
    [Replaceable] readonly attribute double devicePixelRatio;
};

[Exposed=Window]
interface MediaQueryList : EventTarget {
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
  undefined addListener(EventListener? callback);
  undefined removeListener(EventListener? callback);
           attribute EventHandler onchange;
};

[Exposed=Window]
interface MediaQueryListEvent : Event {
  constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
};

dictionary MediaQueryListEventInit : EventInit {
  CSSOMString media = "";
  boolean matches = false;
};

[Exposed=Window]
interface Screen {
  readonly attribute long availWidth;
  readonly attribute long availHeight;
  readonly attribute long width;
  readonly attribute long height;
  readonly attribute unsigned long colorDepth;
  readonly attribute unsigned long pixelDepth;
};

partial interface Document {
  Element? elementFromPoint(double x, double y);
  sequence<Element> elementsFromPoint(double x, double y);
  CaretPosition? caretPositionFromPoint(double x, double y, optional CaretPositionFromPointOptions options = {});
  readonly attribute Element? scrollingElement;
};

dictionary CaretPositionFromPointOptions {
  sequence<ShadowRoot> shadowRoots = [];
};

[Exposed=Window]
interface CaretPosition {
  readonly attribute Node offsetNode;
  readonly attribute unsigned long offset;
  [NewObject] DOMRect? getClientRect();
};

enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
dictionary ScrollIntoViewOptions : ScrollOptions {
  ScrollLogicalPosition block = "start";
  ScrollLogicalPosition inline = "nearest";
  ScrollIntoViewContainer container = "all";
};

enum ScrollIntoViewContainer { "all", "nearest" };

dictionary CheckVisibilityOptions {
    boolean checkOpacity = false;
    boolean checkVisibilityCSS = false;
    boolean contentVisibilityAuto = false;
    boolean opacityProperty = false;
    boolean visibilityProperty = false;
};

partial interface Element {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();

  boolean checkVisibility(optional CheckVisibilityOptions options = {});

  undefined scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
  undefined scroll(optional ScrollToOptions options = {});
  undefined scroll(unrestricted double x, unrestricted double y);
  undefined scrollTo(optional ScrollToOptions options = {});
  undefined scrollTo(unrestricted double x, unrestricted double y);
  undefined scrollBy(optional ScrollToOptions options = {});
  undefined scrollBy(unrestricted double x, unrestricted double y);
  attribute unrestricted double scrollTop;
  attribute unrestricted double scrollLeft;
  readonly attribute long scrollWidth;
  readonly attribute long scrollHeight;
  readonly attribute long clientTop;
  readonly attribute long clientLeft;
  readonly attribute long clientWidth;
  readonly attribute long clientHeight;
  readonly attribute double currentCSSZoom;
};

partial interface HTMLElement {
  readonly attribute Element? scrollParent;
  readonly attribute Element? offsetParent;
  readonly attribute long offsetTop;
  readonly attribute long offsetLeft;
  readonly attribute long offsetWidth;
  readonly attribute long offsetHeight;
};

partial interface HTMLImageElement {
  readonly attribute long x;
  readonly attribute long y;
};

partial interface Range {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();
};

partial interface MouseEvent {
  readonly attribute double screenX;
  readonly attribute double screenY;
  readonly attribute double pageX;
  readonly attribute double pageY;
  readonly attribute double clientX;
  readonly attribute double clientY;
  readonly attribute double x;
  readonly attribute double y;
  readonly attribute double offsetX;
  readonly attribute double offsetY;
};

partial dictionary MouseEventInit {
  double screenX = 0.0;
  double screenY = 0.0;
  double clientX = 0.0;
  double clientY = 0.0;
};

enum CSSBoxType { "margin", "border", "padding", "content" };
dictionary BoxQuadOptions {
  CSSBoxType box = "border";
  GeometryNode relativeTo; // XXX default document (i.e. viewport)
};

dictionary ConvertCoordinateOptions {
  CSSBoxType fromBox = "border";
  CSSBoxType toBox = "border";
};

interface mixin GeometryUtils {
  sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
  DOMQuad convertQuadFromNode(DOMQuadInit quad, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMQuad convertRectFromNode(DOMRectReadOnly rect, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMPoint convertPointFromNode(DOMPointInit point, GeometryNode from, optional ConvertCoordinateOptions options = {}); // XXX z,w turns into 0
};

Text includes GeometryUtils; // like Range
Element includes GeometryUtils;
CSSPseudoElement includes GeometryUtils;
Document includes GeometryUtils;

typedef (Text or Element or CSSPseudoElement or Document) GeometryNode;

[Exposed=Window]
interface VisualViewport : EventTarget {
  readonly attribute double offsetLeft;
  readonly attribute double offsetTop;

  readonly attribute double pageLeft;
  readonly attribute double pageTop;

  readonly attribute double width;
  readonly attribute double height;

  readonly attribute double scale;

  attribute EventHandler onresize;
  attribute EventHandler onscroll;
  attribute EventHandler onscrollend;
};

问题索引

各用户代理对于此处是用(协调的)视口 执行滚动,还是用滚动盒 执行滚动于布局视口的滚动盒上存在分歧。
对象 IDL 片段重定义了一些成员。我们能否解决这个问题?
DOM 顺序

p1 = 即使是 RTL 也为左上角

缩放为 0 意味着除以零,返回 0x0

不允许跨 frame,抛出 WrongDocumentError?

点会被平面化(3D 变换),z=0。类似 getClientRect

测试块在内联

伪元素 before/after 作为元素的子节点

所有 viewport box 都一样

...
...
...
scrollend 事件的分发顺序是什么?是基于滚动开始顺序还是滚动完成顺序?
CanIUse

Support:Android Browser3+Baidu Browser13.52+Blackberry Browser10+Chrome9+Chrome for Android139+Edge12+Firefox6+Firefox for Android142+IE10+IE Mobile10+KaiOS Browser2.5+Opera12.1+Opera MiniAllOpera Mobile12.1+QQ Browser14.9+Safari5.1+Safari on iOS5.0+Samsung Internet4+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser2.1+Baidu Browser13.52+Blackberry Browser7+Chrome4+Chrome for Android139+Edge12+Firefox18+Firefox for Android142+IE11+IE Mobile11+KaiOS Browser2.5+Opera11.6+Opera MiniAllOpera Mobile12+QQ Browser14.9+Safari3.1+Safari on iOS3.2+Samsung Internet4+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser2.3+Baidu Browser13.52+Blackberry Browser7+Chrome15+Chrome for Android139+Edge12+Firefox3+Firefox for Android142+IE6+IE Mobile10+KaiOS Browser2.5+Opera11+Opera MiniAllOpera Mobile12+QQ Browser14.9+Safari5+Safari on iOS4.0+Samsung Internet4+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser139+Baidu Browser13.52+Blackberry BrowserNoneChrome44+Chrome for Android139+Edge14+Firefox48+Firefox for Android142+IENoneIE MobileNoneKaiOS Browser2.5+Opera31+Opera MiniNoneOpera Mobile80+QQ Browser14.9+Safari9+Safari on iOS9.0+Samsung Internet4+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser139+Baidu Browser13.52+Blackberry BrowserNoneChrome61+Chrome for Android139+Edge79+Firefox36+Firefox for Android142+IENoneIE MobileNoneKaiOS Browser2.5+Opera48+Opera MiniNoneOpera Mobile80+QQ Browser14.9+Safari14+Safari on iOS14.5+Samsung Internet8.2+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser2.3+Baidu Browser13.52+Blackberry Browser7+Chrome4+Chrome for Android139+Edge12+Firefox12+Firefox for Android142+IE9+IE Mobile10+KaiOS Browser2.5+Opera10.6+Opera MiniAllOpera Mobile11+QQ Browser14.9+Safari4+Safari on iOS4.0+Samsung Internet4+UC Browser for Android15.5+

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

CanIUse

Support:Android Browser139+Baidu Browser13.52+Blackberry Browser (limited)7+Chrome61+Chrome for Android139+Edge79+Firefox36+Firefox for Android142+IE (limited)8+IE Mobile (limited)10+KaiOS Browser2.5+Opera48+Opera MiniNoneOpera Mobile80+QQ Browser14.9+Safari16.0+Safari on iOS16.0+Samsung Internet8.2+UC Browser for Android15.5+

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