为什么在 `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
不会卡住。
除了第一个示例仅将 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
不会卡住。