position定位 响应式_position: sticky 不起作用?原理分析+爬坑笔记

众所周知,position: sticky 是一个非常好用的玩意儿。之前几次用得都很爽,但是这次我在某个项目使用过程中遇到了一个问题,它意外地没有起到我预期的作用,经过查阅标准文档后我搞懂了这个问题,特此记录。

假设有如下代码

CSS部分

#container {
    background-color: #eee;
    /* 祖先容器的 overflow 属性至关重要 */
    /* overflow: auto; */
    /* height: 500px; */
}
.sticky {
    position: sticky;
    top: 0;
    height: 100px;
}

HTML部分

<div id="container">
    <div class="sticky" style="background-color: red;">
        test sticky 1
    </div>
    <div>Lorem ipsum </div>
    <div class="sticky" style="background-color: green;">
        test sticky 2
    </div>
    <div>Lorem ipsum </div>
    <div class="sticky" style="background-color: blue;">
        test sticky 3
    </div>
    <div>Lorem ipsum </div>
    <div class="sticky" style="background-color: yellow;">
        test sticky 4
    </div>
    <div style="height: 900px;"></div>
</div>

一般来说,由于 position: sticky 的作用,随着页面的滚动,sticky 会吸附到页面顶部的固定位置。

但是在某种情况下,它失效了。我反复调试,发现当 sticky 元素(祖先)容器使用了 overflow: hidden 时,sticky 就失效了。这个 overflow: hidden 是我所使用的 UI 框架自带的效果。结构类似于:

body (带有滚动条的大容器)
    .wrapper (框架样式,自带overflow: hidden)
        .sticky (我写的 sticky 元素)

它在容器滚动时不再吸附到容器顶部显示,而是像作为 normal flow 的内容一样随着滚动条的滚动而消失……

我花了点是按查阅标准文档,截止至今天2020年02月16日,在现行标准 CSS 定位标准 CSS Positioned Layout Module Level 3, W3C Working Draft, 17 May 2016 中有如下解释:

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.

它明确了 sticky 元素在即将消失前会相对它最近的 scrolling box 去做定位。如果理解了它相对于 scrolling box 定位逻辑,就能理解我遇到的问题的内部原理。

然而 scrolling box 是什么?这是一个让人感觉既熟悉又陌生的概念。本着严谨治学的态度,我不敢随便望文生义,我脑海中理解的那个 scrolling box 和标准文档里说的是一回事吗?

继续翻阅文档,发现下方一个 ISSUE ,说的就是这个问题……

11bdb2942077c0ea39ff1857b59a25ec.png

原来 Positioned Layout Module Level 3 自己也没有定义什么是 scrolling box !坑啊……

所以加下来我要做的就是搞懂 Positioned Layout Module 中的 scrolling box 是什么。

众所周知,CSS 标准及其复杂,大概可以分割成一百多个大块,由于本定位模型标准只是其中之一。考虑它涉及滚动行为,且问题的出现和 overflow 相关,所以应当去查阅 Overflow Module 标准,现行标准是 CSS Overflow Module Level 3, W3C Working Draft, 31 July 2018。

在 overflow 的 hidden 部分,我看到了一个我眼熟的词,scroll container。

hidden
This value indicates that the box’s content is clipped to its padding box and that the UA must not provide any scrolling user interface to view the content outside the clipping region, nor allow scrolling by direct intervention of the user, such as dragging on a touch screen or using the scrolling wheel on a mouse. However, the content must still be scrollable programatically, for example using the mechanisms defined in [CSSOM-VIEW], and the box is therefore still a scroll container.

我感觉这里的 scroll container 就是我要找的 scrolling box。根据标准的规定,overflow: hidden 的元素不会出现滚动条,不会响应用户的滚动操作,但是它会被程序滚动,它也会创建 scroll container !

c5959b217814461a72b1c9e76a365e2e.png

而 clip 和 hidden 最大的不同就是它不会被任何方式所滚动,也就不会创建 scroll container 了。

OK,这样一来我的问题就有了答案。

再看一下出问题的结构:

body (带有滚动条的大容器)
    .wrapper (框架样式,自带overflow: hidden)
        .sticky (我写的 sticky 元素)

因为我所写的那个 sticky 元素受到框架样式影响,它去相对一个 overflow: hidden 的中间层容器 .wrapper 去做定位,然而这个容器不带滚动条,不可被用户交互所滚动,当 sticky 元素吸附于 .wrapper 顶部时,它随着 .wrapper 本身在 body 中的移动而移动。所以,所有的 sticky 元素都会被滚动出 body 的 scrollport 区域。

——2020年02月16日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值