为什么在 `html` 上设置 `overflow-x: hidden` 会导致 child 的 `position: sticky` 元素表现不同?

Why does setting `overflow-x: hidden` on `html` cause a child's `position: sticky` element to behave differently?

除了第一个示例仅将 overflow-x: hidden 应用于 body,而第二个示例将其应用于两个 html, body.

之外,以下两个示例是相同的

为什么第一个示例按预期工作而第二个示例却没有?

这按预期工作:

body {
  margin: 0;
  overflow-x: hidden;
}

p.sticky {
  position: sticky;
  top: 0;
  color: red;
}
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p class="sticky">foo</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>

但是,这不是:

html, body {
  margin: 0;
  overflow-x: hidden;
}

p.sticky {
  position: sticky;
  top: 0;
  color: red;
}
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p class="sticky">foo</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eius magnam odio quidem nisi? Dolorum voluptatibus voluptas dignissimos cupiditate vel voluptates ducimus ullam, cumque vitae. Doloribus quasi eaque consequuntur voluptatibus sunt!</p>

以下是 CSS 定位规范对 position:sticky

的说明

6.2. Sticky positioning

A stickily positioned box is positioned similarly to a relatively positioned box, but the offset is computed with reference to the nearest ancestor with a scrolling box, or the viewport if no ancestor has a scrolling box.

所以这里的问题是:最近的带滚动框的祖先是什么,相对于垂直滚动条滚动的是什么框?

要理解这一点,我们需要考虑溢出传播。 CSS overflow spec 表示:

3.4. Overflow Viewport Propagation

UAs must apply the overflow-* values set on the root element to the viewport. However, when the root element is an [HTML] html element (including XML syntax for HTML) whose overflow value is visible (in both axes), and that element has a body element as a child, user agents must instead apply the overflow-* values of the first such child element to the viewport. The element from which the value is propagated must then have a used overflow value of visible.

所以,第一种情况

body {
  margin: 0;
  overflow-x: hidden;
}

body 元素的溢出属性传播到视口。由于这种传播,p.sticky 的祖先元素没有滚动框,因此粘性偏移量是相对于视口计算的。视口也是通过垂直滚动条滚动的框。

第二种情况,

html, body {
  margin: 0;
  overflow-x: hidden;
}

它是传播到视口的 html 元素的溢出属性,body 元素保留其指定的溢出属性,建立一个作为 p.sticky 祖先的滚动框。然后计算相对于 body 元素的偏移量。但垂直滚动条作用的不是 body 元素,它仍然是视口。

所以 p.sticky 不会相对于 body 元素移动,并且随着整个元素的移动,p.sticky 不会卡住。