关于 position: sticky 那些不得不说的事

273 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

image.png

缘起

奇怪了,我的粘性定位为什么没有生效呢?

在这件灵异事件发生之前,我对 position: sticky 的认知始终停留在青铜阶段。在下班回家前的半个小时内,被通知需要给工具栏添加个吸顶功能,思绪稍一转动,so easy啊,谁也不能阻止我下班回家的脚步。

打开项目,找到对应的代码,position: sticky 一写,代码提交,构建部署,完事,关机回家。

第二天,测试疯狂call我,你昨天搞了啥,吸顶功能咋没实现呢?不可能呀,我明明添加了样式,为啥没生效呢?好一番安抚测试小姐姐之后,我开始查找问题。

成也 sticky,败也 sticky。原来一切都是我对 sticky 使用不正确导致的问题。

position: sticky 基本使用

我们先来看一下粘性定位的基本使用方式。

<div>
    <dl>
        <dt>A</dt>
        <dd>Andrew W.K.</dd>
        <dd>Apparat</dd>
        <dd>Arcade Fire</dd>
        <dd>At The Drive-In</dd>
        <dd>Aziz Ansari</dd>
    </dl>
    <dl>
        <dt>C</dt>
        <dd>Chromeo</dd>
        <dd>Common</dd>
        <dd>Converge</dd>
        <dd>Crystal Castles</dd>
        <dd>Cursive</dd>
    </dl>
</div>
dl { 
    margin: 0; 
    padding: 24px 0 0 0; 
}

dt { 
    background: #B8C1C8; 
    border-bottom: 1px solid #989EA4; 
    border-top: 1px solid #717D85; 
    color: #FFF; 
    font: bold 18px/21px Helvetica, Arial, sans-serif; 
    margin: 0; padding: 2px 0 0 12px; 
    position: -webkit-sticky; 
    position: sticky; top: -1px; 
} 

dd { 
    font: bold 20px/45px Helvetica, Arial, sans-serif; 
    margin: 0; 
    padding: 0 0 0 12px; 
    white-space: nowrap; 
}
    
dd + dd { 
    border-top: 1px solid #CCC 
}

一个简单的标题吸顶的代码,大致效果如下图:

image.png

image.png

image.png

本来录制了个小视频,结果发现上传不了,截图意思一下吧。献丑了哈,没有做成gif动图,还请各位贵客将就一下。

添油加醋

但是我的实际开发过程中,工具栏是这样的

image.png

代码大致上是这样的

<div className="toorbar-container">
    ...
    <div className="toorbar"></div>
    ...
</div>

我当时为了实现工具栏的吸顶,直接将粘性定位放置到了toorbar上面了,这其实也是最终导致 position: sticky 失效的真正原因。

一探究竟

这里我先借用一下 MDN 中对粘性定位的解释。

元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor) 和 containing block (最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于toprightbottom, 和 left的值进行偏移。偏移值不会影响任何其他元素的位置。

通过这里我们可以发现粘性定位的相位元素其实不是基于可视区域的,而是基于理他最近的滚动祖先或者块级祖先的。