Skip to content
文章目录

js与css实现粘性布局-吸顶效果

前置知识点

element.offsetParent 与 element.offsetTop

element.offsetParent 为包含 element 的祖先元素中,层级最近的定位元素。 也就是说,offsetParent 必须满足三个条件:

  • 是 element 的祖先元素
  • 最靠近 element
  • 是定位元素,即 position 属性不为 static

element.offsetTop 是当前元素顶部到 element.offsetParent 顶部的距离

详细介绍:offsetParent 与 offsetTop 和 offsetLeft

position: fixed/absolute/sticky/static

position: fixed

元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。特例:当元素祖先的 transform、perspective、filter 或 backdrop-filter 属性非 none 时,容器由视口改为该祖先。

position: absolute

元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

position: sticky

元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和 containing block(最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于 top、right、bottom 和 left 的值进行偏移。偏移值不会影响任何其他元素的位置。 该值总是创建一个新的层叠上下文(stacking context)。注意,一个 sticky 元素会“固定”在离它最近的一个拥有“滚动机制”的祖先上(当该祖先的 overflow 是 hidden、scroll、auto 或 overlay 时),即便这个祖先不是最近的真实可滚动祖先。这有效地抑制了任何“sticky”行为

sticky 基本只能兼容 2021 年开始版本的浏览器 can i use: sticky

sticky 不生效原因有:

  • 父元素设置了 overflow:hidden 或者 overflow:auto
  • 未指定 top、right、bottom、left4 个值中的任意一个
  • 父元素高度小于 sticky 定位的元素高度
  • sticky 属性依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。
  • 元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。

sticky 属性仅在以下几个条件都满足时有效:

  • 父元素不能 overflow:hidden 或者 overflow:auto 属性
  • 必须指定 top、bottom、left、right4 个值之一,否则只会处于相对定位
  • 父元素的高度不能低于 sticky 元素的高度

css 实现粘性布局

优点:

实现简便

缺点:

  1. 存在兼容性问题。sticky 基本只能兼容 2021 年开始版本的浏览器 can i use: sticky
  2. 吸顶元素与内容元素距离顶部有大概 1px 的间隙

js 实现粘性布局

版本一

要点

  • 最外层的JsStickyWrapper是相对定位, 为了让title元素能获取到距离滚动容器顶部的距离,用于在滚动的时候,能够判断当前应该让哪个title元素设置为绝对定位
  • JsSticky是滚动容器

优点:

兼容性强

缺点:

  1. 实现相对复杂
  2. 吸顶元素与同类未吸顶元素宽度不一致

版本二

简单修复吸顶元素与同类未吸顶元素宽度不一致问题(通过计算出滚动条宽度方式修复)

参考资料

使用 position:sticky 实现粘性布局

MDN: position

absolute 固定在滚动容器里面失效

offsetParent、offsetLeft/offsetTop 深度剖析