使用 CSS position: sticky 实现粘性定位效果

7,169 阅读3分钟

遇上很多需求都可以通过position: sticky轻松解决。比如页面滚动时,操作栏随页面滚动到视口顶端时,固定在顶部,不随着滚动消失。

是不是一直以为 position 的取值只有 static relative absolute fixed? 🙃🙂

各大浏览器陆续支持了一个新值 position: sticky。一起开始一场奇妙的探索之旅吧。

效果图

流盒

粘性定位中有一个“流盒”(flow box)的概念,指的是粘性定位元素最近的可滚动元素(overflow 属性值不是 visible 的元素)的尺寸盒子,如果没有可滚动元素,则表示浏览器视窗盒子。

此 Demo 处粘性定位元素的 top 偏移是 20px,因此,流盒矩形就是滚动窗口矩形再往下偏移 20px

粘性定位元素的包含块

此 Demo 处包含块是绿色边框的元素

粘性约束矩形

表示的是粘性定位元素的包含块在文档流中呈现的矩形区域和流盒的四个边缘在应用粘性定位元素的left、top、right、bottom属性的偏移计算值后的新矩形的交集。

即流盒矩形和包含块的重叠区域。

粘性定位元素不能超出粘性约束矩形的范围限制

几种粘性定位失效的情况

1、粘性定位元素父元素和自身高度计算值一样的时候

错误示例1:

2、粘性定位元素的某个祖先元素的 overflow 属性值不是 visible

错误示例2:

兼容性

代码

<div
  style={{
    height: '200px',
    width: '300px',
    overflow: 'auto',
    border: '3px solid #1890ff',
  }}
>
  {/* <div style={{ overflow: 'auto' }} > */}{/* 错误示例2注释 */}
  <p>粘性定位中有一个“流盒”(flow box)的概念,指的是粘性定位元素最近的可滚动元素(overflow属性值不是visible的元素)的尺寸盒子,如果没有可滚动元素,则表示浏览器视窗盒子。</p>
  <p>此处粘性定位元素的top偏移是20px,因此,流盒矩形就是滚动窗口矩形再往下偏移20px</p>
  <div
    style={{
      border: '5px solid #04cb94'
    }}
  >
    <p>粘性定位元素的包含块</p>
    <p>粘性约束矩形:表示的是粘性定位元素的包含块在文档流中呈现的矩形区域和流盒的四个边缘在应用粘性定位元素的left、top、right、bottom属性的偏移计算值后的新矩形的交集。即流盒矩形和包含块的重叠区域。粘性定位元素不能超出粘性约束矩形的范围限制</p>
    {/* <div> */}{/* 错误示例1注释 */}
    <div
      style={{
        background: '#fcc',
        padding: '5px',
        position: 'sticky',
        top: '20px',
        zIndex: 9,
        border: '1px solid #ccc'
      }}
    >
      粘性定位元素:需要被固定的顶部栏。
    </div>
    {/* </div> */}{/* 错误示例1注释 */}
    <div>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
    </div>
    <div
      style={{
        background: '#faa',
        padding: '5px',
        position: 'sticky',
        top: '20px',
        zIndex: 10,
        border: '1px solid #ccc'
      }}
    >
      堆叠粘性定位元素~
    </div>
    <div>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
      <p>内容</p>
    </div>
    <p>粘性约束矩形 end</p>
  </div>
  <div>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
  </div>
  {/* </div> */}{/* 错误示例2注释 */}
</div>

参考资料

深入理解position sticky粘性定位的计算规则