CSS 滚动捕捉模块第 1 级

W3C 候选推荐标准快照,

此版本
https://w3org.cn/TR/2021/CR-css-scroll-snap-1-20210311/
最新发布版本
https://w3org.cn/TR/css-scroll-snap-1/
编辑草案
https://drafts.csswg.org/css-scroll-snap-1/
历史版本
实现报告
https://wpt.fyi/results/css/css-scroll-snap
测试套件
http://test.csswg.org/suites/css-scroll-snap-1_dev/nightly-unstable/
问题追踪
CSS 工作组问题仓库
编辑
Matt Rakow (Microsoft)
Jacob Rossi (Microsoft)
Tab Atkins-Bittner (Google)
Elika J. Etemad / fantasai (特邀专家)
建议编辑此规范
GitHub 编辑器

摘要

本模块包含通过“吸附位置(snap positions)”来控制平移和滚动行为的功能。

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

关于本文档

本节描述了本文件发布时的状态。其他文件可能会取代本文件。W3C 当前出版物列表和本技术报告的最新修订版本可在 https://w3org.cn/TR/ 的 W3C 技术报告索引中找到。

本文档由 CSS 工作组发布,作为一份候选推荐标准快照。作为候选推荐标准发布并不意味着得到 W3C 成员的认可。候选推荐标准快照已接受广泛审查,旨在收集实施经验。本文档旨在成为 W3C 推荐标准;它将至少保留为候选推荐标准直至 以收集更多反馈。

请通过在 GitHub 上提交 issue(推荐方式)来反馈意见,并在标题中包含规范代码“css-scroll-snap”,格式如下:“[css-scroll-snap] …评论摘要…”。所有议题和评论都会被存档。或者,也可以将反馈发送至(已存档的)公共邮件列表 www-style@w3.org

本文档受 2020年9月15日版 W3C 流程文档 约束。

本文档由在 W3C 专利政策下运作的团体编写。W3C 维护着一份与该团体交付成果相关的专利披露公开列表;该页面还包含了披露专利的指南。任何对个人认为包含必要权利要求 (Essential Claim(s)) 的专利具有实际知情权的个人,必须根据 W3C 专利政策第 6 节披露相关信息。

测试套件和实施报告将在 CR(候选推荐)期间制作。

以下功能存在风险,可能会在 CR 期间被删除:

“风险(At-risk)”是 W3C 流程中的术语,并不一定意味着该特性面临被删除或推迟的危险。这表示工作组认为该特性可能难以及时实现互操作,将其标记为此类允许工作组在转向“建议推荐标准(Proposed Rec)”阶段时,在必要的情况下删除该特性,而无需先发布一个不包含该特性的新“候选推荐标准(Candidate Rec)”。

1. 引言

本节不具有规范性。

可滚动内容的流行用户体验(UX)范式经常采用内容分页或将其划分为逻辑分区。这在触控交互中尤为重要,因为用户通过在平铺的内容广度上快速平移,比通过点击导航深入层级结构更快捷、更容易。例如,用户通过平移照片幻灯片视图查看相册中的多张照片,比点击相册中的单张照片更容易。

然而,考虑到触控平移和鼠标滚轮滚动等滚动输入的不精确性,网页开发者很难保证受控良好的滚动体验,特别是在创建分页内容效果时。例如,用户很容易停在一个尴尬的滚动位置,导致平移时某个项目只显示了一部分。

为此,本模块引入了滚动吸附位置,这些位置强制执行滚动容器的滚动口在滚动操作完成后可能停下的位置。

此外,为了在关闭吸附功能时也能提供更好的分页和滚动定位控制,本模块为所有滚动容器定义了 scroll-padding 属性,用于调整滚动容器最佳观看区域,以实现分页和滚动进入视图的操作。同样,scroll-margin 属性可用于任何盒子,以调整其视觉区域,用于滚动进入视图的操作。

1.1. 模块交互

本模块扩展了 [CSS2] 第 11.1 节中定义的滚动用户界面功能。

本模块中的任何属性都不适用于 ::first-line::first-letter 伪元素。

1.2. 值的定义

本规范遵循 CSS 属性定义约定[CSS2]),使用 值定义语法[CSS-VALUES-3])。本规范未定义的值类型在 CSS Values & Units [CSS-VALUES-3] 中定义。与其他 CSS 模块的组合可能会扩展这些值类型的定义。

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

2. 激励性示例

在此示例中,排列在滚动容器中的一系列图像被用于构建照片库。在此示例中,滚动容器比其中包含的图像大(这样可以同时看到多张图像),且图像尺寸各不相同。使用基于元素的强制吸附位置,滚动操作总是会以图像在滚动容器的滚动口中居中而结束。
img {
    /* Specifies that the center of each photo
       should align with the center of the scroll
       container in the X axis when snapping */
    scroll-snap-align: none center;
}
.photoGallery {
    width: 500px;
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
    /* Requires that the scroll position always be
       at a snap position when the scrolling
       operation completes. */
    scroll-snap-type: x mandatory;
}
<div class="photoGallery">
    <img src="img1.jpg">
    <img src="img2.jpg">
    <img src="img3.jpg">
    <img src="img4.jpg">
    <img src="img5.jpg">
</div>
示例中滚动容器内容的布局。红色矩形代表滚动吸附口(snapport),黄色矩形代表吸附区域。由于 scroll-snap-align 在内联(水平)轴上为“center”,因此在每个滚动位置都建立了一个吸附位置,将吸附口的 X 中心(由红色虚线表示)与吸附区域的 X 中心(由黄色虚线表示)对齐。
此示例构建了一个分页文档,将每一页对齐在滚动容器边缘附近(但不完全在边缘上)。这允许上一页从上方“窥视”出来,以便让用户意识到他们尚未到达文档顶部。使用邻近吸附位置而非强制吸附位置,允许用户在页面中途停止(而不是强制他们一次吸附一页)。然而,如果滚动操作结束时靠近某个吸附位置,则会调整滚动位置以按指定方式对齐页面。
.page {
    /* Defines the top of each page as the
       edge that should be used for snapping */
    scroll-snap-align: start none;
}
.docScroller {
    width: 500px;
    overflow-x: hidden;
    overflow-y: auto;
    /* Specifies that each element’s snap area should
       align with a 100px offset from the top edge. */
    scroll-padding: 100px 0 0;
    /* Encourages scrolling to end at a snap position when the
        operation completes, if it is near a snap position */
    scroll-snap-type: y proximity;
}
<div class="docScroller">
    <div class="page">Page 1</div>
    <div class="page">Page 2</div>
    <div class="page">Page 3</div>
    <div class="page">Page 4</div>
</div>
示例中滚动容器内容的布局。红色矩形代表滚动吸附口(由于 scroll-padding,从顶部缩进了 100px),黄色矩形代表吸附区域。由于 scroll-snap-align 在 Y 轴上为“start”,因此在每个滚动位置都建立了一个吸附位置,将吸附口的 Y 起点(由红色虚线表示)与吸附区域的 Y 起点(由黄色虚线表示)对齐。

3. 滚动吸附模型

本模块定义了滚动吸附位置的控件,这些位置是产生滚动容器内特定内容对齐方式的滚动位置。通过在相关滚动容器上使用 scroll-snap-type 属性,作者可以要求滚动口在滚动操作(包括编程滚动,如 scrollTo() 方法)后停在吸附位置上的特定倾向。

吸附位置被指定为元素滚动吸附区域(其边框盒,由 scroll-margin 修改)在滚动容器滚动吸附口(其滚动口,由 scroll-padding 缩减)内的特定对齐方式(scroll-snap-align)。这在概念上等同于指定对齐主体对齐容器内的对齐方式。满足指定对齐方式的滚动位置即为吸附位置

调整滚动容器的滚动口位置使其与吸附位置对齐的行为称为吸附;如果滚动口的滚动位置为该吸附位置且没有正在进行的滚动操作,则称滚动容器已吸附到该吸附位置。CSS 滚动吸附模块特意不指定也不强制要求执行吸附位置所需的任何精确动画或物理效果;这留给用户代理决定。

吸附位置仅影响元素包含块链上最近的祖先滚动容器

4. 捕获滚动吸附区域:滚动容器上的属性

4.1. 滚动吸附规则:scroll-snap-type 属性

名称scroll-snap-type
none | [ x | y | block | inline | both ] [ mandatory | proximity ]?
初始值 none(无)
应用于所有元素
可继承
百分比 不可用
计算值 指定的关键字
规范顺序按语法
动画类型 离散 (discrete)

scroll-snap-type 属性指定滚动容器是否为滚动吸附容器、其吸附严格度以及考虑哪些轴。如果未指定严格度值,则假定为 proximity

在此示例中,启用了块轴(水平书写时为 y 轴,垂直书写时为 x 轴)上的标题吸附。
html {
  scroll-snap-type: block;   /* applied to main document scroller */
}
h1, h2, h3, h4, h5, h6 {
  scroll-snap-align: start;  /* snap to the start (top) of the viewport */
}

用户代理必须将根元素上设置的 scroll-snap-type 值应用于文档视口。注意,与 overflow 不同,scroll-snap-type会从 HTML body 传播。

4.1.1. 滚动吸附轴:x, y, block, inlineboth

轴值指定受吸附位置影响的轴,以及吸附位置是按轴独立评估还是作为 2D 点整体评估。各值定义如下:

x
滚动容器仅在其水平轴上吸附吸附位置
y
滚动容器仅在其垂直轴上吸附吸附位置
block
滚动容器仅在其块轴上吸附吸附位置
inline
滚动容器仅在其内联轴上吸附吸附位置
both
滚动容器在两个轴上独立吸附吸附位置(可能在每个轴上吸附到不同的元素)。

4.1.2. 滚动吸附严格度:none, proximitymandatory

严格度值none, proximity, mandatory)指定在滚动容器上强制执行吸附位置的严格程度(通过强制调整滚动位置)。各值定义如下:

none(无)
如果指定在滚动容器上,则滚动容器不得吸附
mandatory
如果指定在滚动容器上,则要求滚动容器在没有进行中的滚动操作时必须吸附到吸附位置。如果存在有效的吸附位置,则滚动容器必须在滚动结束时吸附(如果不存在,则不发生吸附)。
proximity
如果指定在滚动容器上,则滚动容器可以在滚动结束时由 UA 根据滚动参数自行决定是否吸附到吸附位置。

作者在使用强制吸附位置时应考虑不同尺寸的屏幕以及(如果适用)不同尺寸的内容。特别是,尽管对大于滚动口的被吸附元素的访问由 UA 处理,但如果作者将强制吸附分配给非相邻的兄弟元素,当内容长度超过屏幕时,中间的内容可能会变得无法访问。

如果一个盒子是滚动容器或者 scroll-snap-type 的值不为 none,则该盒子捕获吸附位置。如果一个盒子的包含块链上最近的吸附位置捕获祖先是一个滚动容器,且其 scroll-snap-type 的值为非 none,则该祖先为该盒子的滚动吸附容器。否则,该盒子没有滚动吸附容器,其吸附位置不会触发吸附

4.1.3. 布局更改后的重新吸附

如果文档的内容或布局发生更改(例如内容被添加、移动、删除、调整大小),导致滚动吸附口的内容发生变化,UA 必须重新评估由此产生的滚动位置,并在需要时重新吸附。如果滚动容器在内容更改前已吸附,且该相同的吸附位置仍然存在(例如其关联元素未被删除),则内容更改后,滚动容器必须重新吸附到该相同的吸附位置。如果多个盒子在之前已吸附且它们的吸附位置不再重合,则如果其中一个已获得焦点或成为目标,滚动容器必须重新吸附到该盒子;否则,重新吸附到哪一个由 UA 定义。(例如,随着布局的移动导致其他元素的吸附位置对齐和失对齐,UA 可以跟踪当前吸附的元素。)

由于重新吸附操作而导致的向新盒子或不同盒子的滚动,必须表现和动画化得与其他任何“滚动进入视图”操作一样,包括遵循 scroll-behavior 等控件。然而,重新吸附到与之前相同的盒子的滚动行为由 UA 定义。例如,当吸附到某个部分的开始处时,如果文档较早部分动态添加了内容,UA 可能选择不对滚动到该部分新位置的过程进行动画处理,以营造没有滚动的错觉。

在下面的示例中,日志控制台在最初加载以及每当有消息添加到底部时,除非用户从边缘滚动离开,否则始终保持吸附在内容底部。
.log {
  scroll-snap-type: proximity;
  align-content: end;
}
.log::after {
  display: block;
  content: "";
  scroll-snap-align: end;
}

这些规则创建了一个单一的滚动吸附区域,由 ::after 伪元素表示,定位在滚动吸附容器的最底部。如果用户滚动到“靠近”底部的位置,容器将吸附到该位置。如果更多内容被动态添加到容器中,它将保持吸附状态(因为如果滚动吸附区域在更改后仍然存在,滚动容器被要求重新吸附到相同的区域)。然而,如果用户已经滚动到日志的其他位置,它将不会执行任何操作。

4.2. 滚动吸附口:scroll-padding 属性

名称scroll-padding
[ auto | <length-percentage> ]{1,4}
初始值 auto
应用于滚动容器
可继承
百分比 相对于滚动容器滚动口的相应维度
计算值 每侧可以是关键字 auto 或计算出的 <length-percentage>
动画类型 按计算值类型
规范顺序按语法

此属性指定(针对所有滚动容器,而不仅是滚动吸附容器)定义滚动口最佳观看区域的偏移量:即作为将对象置于用户视野内的目标区域。这允许作者排除滚动口中被其他内容(如固定定位的工具栏或侧边栏)遮挡的区域,或者仅仅是在目标元素和滚动口边缘之间留出更多呼吸空间。

scroll-padding 属性是一个简写属性,可以在一个声明中设置所有 scroll-padding-* 完整属性,并按照 padding 属性为其完整属性赋值的方式,为代表每一侧的完整属性分配值。各值的含义如下:

<length-percentage>

定义从滚动口相应边缘向内的偏移量。当应用于根视口时,该偏移量的计算和应用相对于布局视口(而非视觉视口),方式与固定定位盒子上的相应插入属性相同;最佳观看区域是与视觉视口相交的剩余区域。

auto

表示滚动口相应边缘的偏移量由 UA 确定。这通常应默认为 0px 的使用长度,但 UA 可以使用启发式方法检测何时非零值更为合适。

例如,UA 可以检测到 position:fixed 元素何时被用作遮挡其下方内容的不透明“不可滚动”页眉,并将顶部偏移解析为该元素的高度,以便“向下翻页”操作(例如按下 PgDn)自动滚动一“可视页”的内容。

这些偏移量减少了对于滚动操作而言被认为是“可视”的滚动口区域:它们对布局、滚动原点或初始位置,或元素是否被实际认为是可见的没有影响,但应该会影响元素或插入符号是否被视为已滚动到视图中(例如用于定位或聚焦操作),并减少分页操作(例如使用 PgUpPgDn 键或从滚动条触发等效操作)的滚动量,以便用户在滚动口的最佳观看区域内看到连续的内容流。

对于滚动吸附容器,此区域还定义了滚动吸附口——即在计算吸附位置时,用作滚动吸附区域对齐容器的滚动口区域。

在此示例中,使用 scroll-padding 将幻灯片图像置于滚动口中未被固定定位工具栏遮挡的部分内。
html {
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 500px 0 0;
}
.toolbar {
    position: fixed;
    height: 100%;
    width: 500px;
    right: 0;
}
img {
    scroll-snap-align: none center;
}

用户代理必须将根元素上设置的 scroll-padding 值应用于文档视口。(注意,与 overflow 不同,scroll-padding会从 HTML body 传播。)

5. 对齐滚动吸附区域:元素上的属性

5.1. 滚动吸附区域:scroll-margin 属性

名称scroll-margin
<length>{1,4}
初始值 0
应用于所有元素
可继承
百分比 不可用
计算值 每侧一个绝对长度
规范顺序按语法
动画类型 按计算值类型

此属性是一个简写属性,可以在一个声明中设置所有 scroll-margin-* 完整属性,并按照 margin 属性为其完整属性赋值的方式,为代表每一侧的完整属性分配值。

这些值表示定义用于将此盒子吸附到吸附口的滚动吸附区域的外延量。滚动吸附区域的确定方法是:获取变换后的边框盒,找到其矩形边界盒(在滚动容器的坐标空间中轴对齐),然后添加指定的外延量。

注:这确保了滚动吸附区域始终是矩形的,且与滚动容器的坐标空间轴对齐。

如果页面导航到一个定义了目标元素的片段(即可以被 :target 匹配,或者是 scrollIntoView() 的目标),UA 应使用该元素的滚动吸附区域,而不是仅仅使用其边框盒,来决定将可滚动溢出区域的哪个部分带入视图,即使在吸附功能关闭或未应用于此元素时也是如此

5.2. 滚动吸附对齐:scroll-snap-align 属性

名称scroll-snap-align
[ none | start | end | center ]{1,2}
初始值 none(无)
应用于所有元素
可继承
百分比 不可用
计算值 两个关键字
规范顺序按语法
动画类型 离散 (discrete)

scroll-snap-align 属性将盒子的吸附位置指定为,其吸附区域(作为对齐主体)在其吸附容器吸附口(作为对齐容器)内的对齐方式。两个值分别指定在块轴内联轴上的吸附对齐,具体由吸附容器书写模式决定。如果只指定一个值,第二个值默认为相同的值。

值定义如下

none
此盒子在指定轴上不定义吸附位置
start
此盒子滚动吸附区域滚动容器吸附口内的起始对齐,即为指定轴上的吸附位置
end
此盒子滚动吸附区域滚动容器吸附口内的结束对齐,即为指定轴上的吸附位置
center
此盒子滚动吸附区域滚动容器吸附口内的居中对齐,即为指定轴上的吸附位置

起始和结束对齐方式是根据吸附容器书写模式来解析的,除非滚动吸附区域大于吸附口,在这种情况下,它们根据盒子本身的书写模式来解析。(这允许容器中的项目在总体上具有一致的吸附对齐,同时确保 start 始终将项目对齐,以便从头开始阅读其内容。)

5.2.1. 将有效吸附位置的作用域限定于可见盒子

由于滚动吸附的目的是为了最佳观看效果而在滚动口内对齐内容,因此如果吸附到某个位置会导致贡献该位置的吸附区域完全处于吸附口之外,即使它以其他方式满足了该吸附区域所需的对齐方式,该滚动位置也不被视为有效的吸附位置

例如,如果一个吸附区域的顶部边缘与吸附口的顶部边缘重合,则该吸附区域顶部对齐于吸附口;如果该吸附区域至少有一部分在屏幕上,这将被视为该吸附区域块轴起始对齐吸附的有效吸附位置。然而,如果整个吸附区域都在吸附口之外,则该滚动容器不能被视为已吸附,因为所需的对齐方式虽然满足,但对观察者来说不相关。
╔════viewport════╗┈┈┈┈┈┈┈┈┌──────────────┐
║  ┌─────┐ ┌──┐  ║        │ top-snapping │
║  ├──┐  │ └──┘  ║        │   element    │
║  └──┴──┘       ║        │              │
╚════════════════╝        │              │
                          └──────────────┘
屏幕外元素的对齐不被视为吸附
为什么要将吸附限制在元素可见时?正如 WebKit 实现者指出的那样,在画布上无限延伸吸附边缘只允许吸附网格布局,并且当屏幕外元素与屏幕内元素不对齐时,会给用户产生奇怪的行为。(如果这对实现者来说太困难,我们可以默认为网格行为,以后再引入切换以获得更智能的行为。)

注:虽然 scroll-snap-type: both 独立评估每个轴上的吸附位置,但在一个轴上选择吸附位置可能会受到另一个轴上吸附位置的影响。例如,在一个轴上的吸附可能会将另一个轴本应吸附到的吸附区域推到屏幕外,使其吸附位置失效,从而无法选择。

5.2.2. 吸附溢出滚动口的盒子

如果吸附区域在特定轴上大于吸附口,则任何吸附区域覆盖吸附口,且该轴上几何意义上的前一个和后一个吸附位置之间的距离大于该轴上吸附口尺寸的滚动位置,在该轴上均是有效的吸附位置。UA 可以将指定的对齐方式用作某些滚动操作(例如显式分页)的更精确目标。

例如,以 § 2 激励性示例中的第一个示例为例,该示例将照片作为区域。作者希望在项目之间强制吸附,但如果项目恰好比你的滚动口大,你希望在覆盖它后能够环绕整个项目滚动。

由于吸附区域大于吸附口,而该区域完全填充了滚动口,因此容器可以任意滚动,并且不会尝试吸附回其对齐位置。然而,如果容器被滚动使得该区域在一个轴上不再完全填充滚动口,则该区域会抵抗向外滚动,直到它被滚动到足以触发吸附到不同的吸附位置为止。

再举一个例子,嵌套 section 元素上的强制顶部吸附可能会产生大的吸附区域(来自大的顶级部分),这些区域中可能填充了较小的吸附区域(来自小节)。当小节足够小时,它们正常吸附;当它们更长时,查看者可以在它们内部任意滚动,或者在顶级部分的某个大片段内滚动,该片段没有任何小节可供吸附。
┌─ top-level section ─┐ ━┓
│                     │ 1┃
│                     │  ┃
│                     │ ━┩
│                     │  ┆
│                     │  ┆
│┌─── sub-section ───┐│  ╯ ━┓
│└───────────────────┘│    2┃
│┌─── sub-section ───┐│ ━┓  ┃
││                   ││ 3┃ ━┛
│└───────────────────┘│  ┃
│┌─── sub-section ───┐│ ━┛ ━┓
│└───────────────────┘│    4┃
│┌─── sub-section ───┐│ ━┓  ┃
││                   ││ 5┃ ━┛
││                   ││  ┃
││                   ││ ━┩
││                   ││  ┆
││                   ││  ┆
││                   ││  ┆
│└───────────────────┘│  ┆
└─────────────────────┘  ╯
在上图中,五个编号的滚动口代表与顶级部分及其四个小节相关的五个吸附位置。因为第一个和最后一个吸附位置是比滚动口更高范围的一部分,所以允许查看者在每个范围的顶部和底部之间自由滚动。

注:如果作者改而在每个部分的标题(而不是部分本身)上设置强制吸附位置,那么第一和第五部分的内容将部分无法被用户访问,因为标题吸附区域没有延伸到覆盖整个部分。这就是为什么在可能间隔很远的元素上使用强制吸附位置是一个糟糕的想法。

5.2.3. 无法到达的吸附位置

如果一个吸附位置如上所述是无法到达的,即对齐到该位置需要将滚动容器的滚动口滚动到超出其可滚动溢出区域的边缘,则此吸附区域使用吸附位置是在每个相关轴上朝向期望的吸附位置滚动尽可能多后得到的位置。

5.3. 滚动吸附限制:scroll-snap-stop 属性

名称scroll-snap-stop
normal | always
初始值 normal
应用于所有元素
可继承
百分比 不可用
计算值 指定关键字
规范顺序按语法
动画类型 离散 (discrete)

当沿预期方向滚动时,滚动容器可以在到达滚动操作的自然终点并选择其最终滚动位置之前,“越过”多个可能的吸附位置(如果滚动操作使用了相同的方向但距离较短,这些位置本可以有效吸附)。scroll-snap-stop 属性允许这样一个可能的吸附位置“拦截”滚动操作,强制滚动容器在滚动操作自然结束前停止。

值定义如下

normal
滚动容器在滚动操作执行期间可以越过由该元素定义的吸附位置
always
滚动容器在滚动操作执行期间不得越过由该元素定义的吸附位置;它必须吸附到该元素第一个吸附位置

此属性对仅具有预期终点位置的滚动操作没有影响,因为它们在概念上不会“越过”任何吸附位置

6. 吸附机制

选择要吸附到的吸附位置的精确模型算法被刻意留为大部分未定义,以便用户代理可以考虑到对用户意图和交互的复杂建模,并随着时间的推移调整其响应方式,以最好地服务于用户。

本节定义了一些有用的概念来帮助讨论滚动吸附机制,并为有效的滚动吸附策略应该是什么样提供了一些指导原则。鼓励用户代理在定义自己的吸附行为时采用这些指导并运用自己的最佳判断。它还提供少量行为要求,以确保作者在考虑滚动吸附设计界面时可以依赖的最低限度的合理行为。

6.1. 滚动方法类型

当页面被滚动时,该动作以预期的终点位置和/或预期的方向执行。这两者的每一种组合都定义了一种独特的滚动类别,可以进行略有不同的处理:

预定结束位置
仅具有预期终点位置的滚动常见示例包括:
  • 平移手势,释放时无惯性

  • 显式操作滚动条“滑块”

  • 通过诸如 scrollTo() 等 API 以编程方式滚动

  • 通过文档的可聚焦元素进行 Tab 导航

  • 导航到页面内的锚点

  • 归位操作,如 Home/End

预定方向和结束位置
同时具有预期方向和终点位置的滚动常见示例包括:
  • “甩动”手势,带惯性解读

  • 通过诸如 scrollBy() 等 API 以编程方式滚动

  • 分页操作,如 PgUp/PgDn 键(或滚动条上的等效操作)

在吸附点等功能介入之前的滚动预期终点为其自然终点

预定方向
仅具有预期方向的滚动常见示例包括:
  • 按下键盘上的箭头键(或滚动条上的等效操作)

  • 被解读为固定(而非惯性)滚动的滑动行为

此外,因为页面布局通常在垂直和/或水平方向上对齐事物,所以 UA 有时会在滚动方向足够垂直或水平时对滚动进行轴锁定轴锁定滚动仅被绑定在该轴上滚动。这可以防止不太精确的输入机制在非主轴上产生漂移。

注:本规范仅适用于用户代理支持的滚动方法;它不要求用户代理支持任何特定的输入或滚动方法。

6.2. 选择吸附位置

滚动容器可以在其可滚动溢出区域内散布许多吸附区域。一种简单的选择吸附位置的算法可能会产生对用户来说不直观的行为,因此在设计选择算法时需要格外小心。以下是一些有助于选择过程的提示:

附录 A:完整属性

物理和逻辑完整属性(及其简写)的交互方式定义见 [CSS-LOGICAL-1]

scroll-padding 的物理完整属性

名称scroll-padding-top, scroll-padding-right, scroll-padding-bottom, scroll-padding-left
auto | <length-percentage>
初始值 auto
应用于滚动容器
可继承
百分比 相对于滚动容器滚动口
计算值 关键字 auto 或计算出的 <length-percentage>
规范顺序按语法
动画类型 按计算值类型

scroll-padding 的这些完整属性分别指定吸附口的顶部、右侧、底部和左侧边缘。负值无效。

scroll-padding 的流相关完整属性

名称scroll-padding-inline-start, scroll-padding-block-start, scroll-padding-inline-end, scroll-padding-block-end
auto | <length-percentage>
初始值 auto
应用于滚动容器
可继承
百分比 相对于滚动容器滚动口
计算值 关键字 auto 或计算出的 <length-percentage>
规范顺序按语法
动画类型 按计算值类型

scroll-padding 的这些完整属性分别指定吸附口的块起点、内联起点、块终点和内联终点边缘。负值无效。

名称scroll-padding-block, scroll-padding-inline
[ auto | <length-percentage> ]{1,2}
初始值 auto
应用于滚动容器
可继承
百分比 相对于滚动容器滚动口
计算值 见各个属性
动画类型 按计算值
规范顺序按语法

scroll-padding-block-start + scroll-padding-block-endscroll-padding-inline-start + scroll-padding-inline-end 的这些简写属性scroll-padding完整属性,并分别指定吸附口的块轴和内联轴边缘。

如果指定了两个值,第一个值给出起点值,第二个值给出终点值。

scroll-margin 的物理完整属性

名称scroll-margin-top, scroll-margin-right, scroll-margin-bottom, scroll-margin-left
<length>(长度)
初始值 0
应用于所有元素
可继承
百分比 不可用
计算值 绝对长度
规范顺序按语法
动画类型 按计算值类型

scroll-margin 的这些完整属性分别指定滚动吸附区域的顶部、右侧、底部和左侧边缘。

scroll-margin 的流相关完整属性

名称scroll-margin-block-start, scroll-margin-inline-start, scroll-margin-block-end, scroll-margin-inline-end
<length>(长度)
初始值 0
应用于所有元素
可继承
百分比 不可用
计算值 绝对长度
规范顺序按语法
动画类型 按计算值类型

scroll-margin 的这些完整属性分别指定滚动吸附区域的块起点、内联起点、块终点和内联终点边缘。

名称scroll-margin-block, scroll-margin-inline
<length>{1,2}
初始值 0
应用于所有元素
可继承
百分比 不可用
计算值 见各个属性
动画类型 按计算值类型
规范顺序按语法

scroll-margin-block-start + scroll-margin-block-endscroll-margin-inline-start + scroll-margin-inline-end 的这些简写属性scroll-margin完整属性,并分别指定滚动吸附区域的块轴和内联轴边缘。

如果指定了两个值,第一个值给出起点值,第二个值给出终点值。

7. 隐私与安全考虑

本规范未公开任何未直接向 DOM 公开的信息;它只是使滚动功能稍微强大了一些。没有任何新的隐私或安全考虑。

8. 致谢

非常感谢 David Baron、Simon Fraser、Håkon Wium Lie、Theresa O’Connor、François Remy、Majid Valpour,特别是 Robert O’Callahan 提出的建议和推荐,这些已合并到本文档中。

9. 变更记录

9.1. 自 2019 年 3 月 19 日 CR 以来的变更

2019 年 3 月 19 日候选推荐标准以来的变更包括:

提供了评论处理说明(Disposition of Comments)

9.2. 自 2019 年 1 月 31 日 CR 以来的变更

2019 年 1 月 31 日候选推荐标准以来的变更包括:

9.3. 自 2018 年 8 月 14 日候选推荐标准(CR)以来的变更

2018 年 8 月 14 日候选推荐标准以来的变更包括:

现提供一份 意见处理记录

9.4. 自 2017 年 12 月 14 日候选推荐标准(CR)以来的变更

2017 年 12 月 14 日候选推荐标准以来的变更包括:

现提供一份 意见处理记录

9.5. 自 2017 年 8 月 24 日候选推荐标准(CR)以来的变更

2017 年 8 月 24 日候选推荐标准以来的变更包括:

现提供一份 意见处理记录

9.6. 自 2016 年 10 月 20 日候选推荐标准(CR)以来的变更

2016 年 10 月 20 日候选推荐标准以来的变更包括:

现提供一份 意见处理记录

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语相结合来表达。本文档规范性部分中的关键词“MUST”(必须)、“MUST NOT”(不得)、“REQUIRED”(必需)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(推荐)、“SHOULD NOT”(不推荐)、“RECOMMENDED”(建议)、“MAY”(可以)和“OPTIONAL”(可选)应按照 RFC 2119 中的描述进行解释。然而,为了可读性,这些词在本文档中不以全大写形式出现。

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

本规范中的示例均以“例如”一词引入,或者通过 class="example" 与规范性文本隔开,如下所示

这是一个说明性示例。

说明性注释以“Note”一词开头,并使用 class="note" 与规范性文本隔开,如下所示

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

建议(Advisements)是规范性章节,旨在引起特别注意,并使用 <strong class="advisement"> 与其他规范性文本区分开来,如下所示: 用户代理必须提供可访问的替代方案。

一致性类别

本规范为三类一致性定义了一致性要求。

样式表
一份 CSS 样式表
渲染器
一种 用户代理 (UA),它解释样式表的语义并渲染使用它们的文档。
创作工具
一种 用户代理 (UA),用于编写样式表。

如果样式表包含的所有使用本模块定义语法的语句,根据通用 CSS 语法及本模块定义的各功能语法均有效,则该样式表符合本规范。

如果渲染器除了按相应规范解释样式表外,还通过正确解析本规范定义的所有功能并相应地渲染文档来支持这些功能,则该渲染器符合本规范。然而,由于设备限制导致 UA 无法正确渲染文档,并不意味着该 UA 不符合规范。(例如,UA 无需在单色显示器上渲染颜色。)

如果创作工具编写的样式表根据通用 CSS 语法及本模块中各功能的语法是句法正确的,并符合本模块中描述的所有其他样式表一致性要求,则该创作工具符合本规范。

部分实现

为了使作者能够利用前向兼容的解析规则来指定后备值,CSS 渲染器 **必须** 将其无法使用支持级别的任何 @规则、属性、属性值、关键字和其他语法结构视为无效(并 适当忽略)。特别地,用户代理 **不得** 在单一多值属性声明中选择性地忽略不支持的组件值而保留支持的值:如果任何值被视为无效(因为不支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有特性的实现

为了避免与未来稳定的 CSS 功能发生冲突,CSS 工作组建议在实施不稳定功能和私有扩展遵循最佳实践

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现即可成为可能,实现者应发布他们能够证明根据规范正确实现的任何 CR 级别特性的无前缀实现。

为建立并保持 CSS 在不同实现间的互操作性,CSS 工作组请求非实验性的 CSS 渲染器在发布任何 CSS 功能的无前缀实现之前,向 W3C 提交一份实现报告(并在必要时提交用于该实现报告的测试用例)。提交给 W3C 的测试用例需经 CSS 工作组审阅和修正。

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

候选推荐标准 (CR) 退出标准

为了使本规范能够推进到提案推荐标准 (PR),必须至少有两个独立的、可互操作的每个功能的实现。每个功能可以由不同组的产品实现,不要求所有功能都由单个产品实现。为了实现此标准,我们定义以下术语

independent
每个实现必须由不同的方开发,并且不能共享、重用或派生自另一个合格实现所使用的代码。对本规范实现无影响的代码段不受此要求限制。
可互操作
通过官方 CSS 测试套件中的相应测试用例,或者如果实现不是 Web 浏览器,则通过等效测试。如果此类用户代理 (UA) 用于声明互操作性,则测试套件中的每个相关测试都应创建等效测试。此外,如果此类 UA 用于声明互操作性,则必须有一个或多个额外的 UA,它们也可以以相同的方式通过这些等效测试,以实现互操作性的目的。等效测试必须公开,以供同行评审。
实现
用户代理,即
  1. 实现了该规范。
  2. 对公众可用。该实现可以是出货产品或其他公开可用的版本(即测试版、预览发布版或“每日构建版”)。非出货产品发布版必须已实现该功能至少一个月,以证明其稳定性。
  3. 不是实验性的(即,专门为通过测试套件设计且不打算用于正常使用的版本)。

该规范将保持候选推荐标准状态至少六个月。

索引

本规范定义的术语

通过引用定义的术语

引用

规范性引用

[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS 盒对齐模块 第3级. 2020年4月21日. WD. URL: https://w3org.cn/TR/css-align-3/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. 2020年4月21日. WD. URL: https://w3org.cn/TR/css-box-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承第 5 级. 2021 年 1 月 19 日. 工作草案(WD). URL: https://w3org.cn/TR/css-cascade-5/
[CSS-DISPLAY-3]
Tab Atkins Jr.; Elika Etemad. CSS 显示模块 第3级. 2020年12月18日. CR. URL: https://w3org.cn/TR/css-display-3/
[CSS-LOGICAL-1]
Rossen Atanassov; Elika Etemad. CSS 逻辑属性与值第 1 级. 2018 年 8 月 27 日. 工作草案(WD). URL: https://w3org.cn/TR/css-logical-1/
[CSS-OVERFLOW-3]
David Baron; Elika Etemad; Florian Rivoal. CSS 溢出模块 3 级. 2020 年 6 月 3 日. WD. URL: https://w3org.cn/TR/css-overflow-3/
[CSS-POSITION-3]
Elika Etemad; et al. CSS Positioned Layout Module Level 3. 2020年5月19日. WD. URL: https://w3org.cn/TR/css-position-3/
[CSS-PSEUDO-4]
Daniel Glazman; Elika Etemad; Alan Stearns. CSS 伪元素模块第 4 级. 2020 年 12 月 31 日. 工作草案(WD). URL: https://w3org.cn/TR/css-pseudo-4/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 3 级. 2019年6月6日. CR. URL: https://w3org.cn/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 4 级. 2020 年 11 月 11 日. 工作草案(WD). URL: https://w3org.cn/TR/css-values-4/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS 书写模式第 4 级. 2019年7月30日. CR. URL: https://w3org.cn/TR/css-writing-modes-4/
[CSS2]
Bert Bos; et al. 层叠样式表第 2 级修订版 1 (CSS 2.1) 规范. 2011年6月7日. REC. URL: https://w3org.cn/TR/CSS21/
[CSSOM-VIEW-1]
Simon Pieters. CSSOM View Module. 2016年3月17日. WD. URL: https://w3org.cn/TR/cssom-view-1/
[HTML]
Anne van Kesteren; et al. HTML 标准。现行标准。网址:https://html.whatwg.cn/multipage/
[RFC2119]
S. Bradner. RFC 中用于指示需求级别的关键词. 1997 年 3 月. 最佳当前实践. URL: https://tools.ietf.org/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器 4 级. 2018年11月21日. WD. URL: https://w3org.cn/TR/selectors-4/

属性索引

名称初始值应用于继承百分比动画类型 (Animation type)规范顺序计算值
scroll-margin <length>{1,4}0 所有元素不可用按计算值类型按语法每侧一个绝对长度
scroll-margin-block <length>{1,2}0 所有元素不可用按计算值类型按语法见各个属性
scroll-margin-block-end <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-block-start <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-bottom <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-inline <length>{1,2}0 所有元素不可用按计算值类型按语法见各个属性
scroll-margin-inline-end <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-inline-start <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-left <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-right <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-margin-top <length>(长度)0 所有元素不可用按计算值类型按语法绝对长度
scroll-padding [ auto | <length-percentage> ]{1,4}auto滚动容器相对于滚动容器滚动口的相应维度按计算值类型按语法每侧,为 auto 关键字或计算出的 <length-percentage> 值
scroll-padding-block [ auto | <length-percentage> ]{1,2}auto滚动容器相对于滚动容器滚动口按计算值按语法见各个属性
scroll-padding-block-end auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-block-start auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-bottom auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-inline [ auto | <length-percentage> ]{1,2}auto滚动容器相对于滚动容器滚动口按计算值按语法见各个属性
scroll-padding-inline-end auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-inline-start auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-left auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-right auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-padding-top auto | <length-percentage>auto滚动容器相对于滚动容器滚动口按计算值类型按语法关键字 auto 或已计算的 <length-percentage> 值
scroll-snap-align [ none | start | end | center ]{1,2}none(无)所有元素不可用离散 (discrete)按语法两个关键字
scroll-snap-stop normal | alwaysnormal所有元素不可用离散 (discrete)按语法指定关键字
scroll-snap-type none | [ x | y | block | inline | both ] [ mandatory | proximity ]?none(无)所有元素不可用离散 (discrete)按语法指定的关键字