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 实现粘性布局
优点:
实现简便
缺点:
- 存在兼容性问题。sticky 基本只能兼容 2021 年开始版本的浏览器 can i use: sticky
- 吸顶元素与内容元素距离顶部有大概 1px 的间隙
js 实现粘性布局
版本一
要点:
- 最外层的
JsStickyWrapper是相对定位, 为了让title元素能获取到距离滚动容器顶部的距离,用于在滚动的时候,能够判断当前应该让哪个title元素设置为绝对定位 JsSticky是滚动容器
优点:
兼容性强
缺点:
- 实现相对复杂
- 吸顶元素与同类未吸顶元素宽度不一致
版本二
简单修复吸顶元素与同类未吸顶元素宽度不一致问题(通过计算出滚动条宽度方式修复)