粘性布局之粘底效果(position sticky, bottom 0)

粘性布局之粘底效果(position sticky, bottom 0)

经常在查资料时访问各种 CSDN 博客会发现,当 屏幕高度 < 左边栏的高度 < 内容的高度 时,滚动屏幕,左边栏会随着内容一同滚动,当滚动到左边栏底部时,左边栏会停止滚动,而内容会继续滚动。

这种设计的优势在于,用户既能够滚动左边栏,又不会在左边栏不够长时,造成页面左侧大片空白的尴尬,这种布局模式,叫做 粘性布局(sticky)

粘性布局在元素满足显示条件时,表现与普通布局没什么不同,但当元素随着页面滚动而无法显示时,会转为 fixed 布局效果,主流浏览器已经全部支持粘性布局(IE不支持)。

通俗一点讲,类似于 Excel 中的“冻结窗格”。

绝大多数网上的教程材料都用 position: sticky; top: 0; 这样的组合来举例,但为了实现 CSDN 左边栏效果,position: sticky; bottom: 0; 似乎不能和想象一样的起作用。

先说结论吧

  1. sticky 的确是无法直接粘底的……
  2. CSDN 使用 JS 动态计算实现,当计算到左边栏底部即将滚上屏幕时,立即对左边栏添加 position: fixed; bottom: 0; 样式,把左边栏定死,延时较为明显,快速上下滚动时能看到闪烁
  3. 我使用 position: sticky; 实现,通过 JS 计算 屏幕高度 - 左边栏高度 得到 top 的值,快速滚动时没有闪烁

发现的过程

  1. 发现 position: sticky; bottom: 0; 不起作用后,上网搜索也并未查到结果。
  2. F12 研究 CSDN 的实现方式,发现其依赖于滚动事件,如此实现避免不了延迟和过度计算的问题,决定再找方法。
  3. 既然 bottom 起不了效果,就尝试设置 top 为负值,果然能够控制元素向上移动,
  4. 但 top 的取值依赖于左边栏自身的高度,CSS 怎么拿到自身的高度呢?
  5. 想到 calc,就写出了 top: calc(100vh - height) 这样的句子…… 不管用。
  6. 摸索了半天 calc 的用法,发现确实是用不成了,calc 拿不到元素自身高度,只能写 JS 了。
  7. 最终通过 JS 完成了这样的需求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 仿 CSDN 左侧栏吸底效果,设置 position 为 sticky,top 为屏幕高度减去左侧栏高度,比 CSDN 的实现更简洁。
var columnLeft = $('.column-left')[0];
function fixLeftColumnTop() {
// 小屏忽略,因为小屏没有左边栏
if ($(window).width() < 769) {
columnLeft.style.top = null;
} else {
if (columnLeft) {
// 屏幕高度 - 左边栏高度 - 左边栏距离底部的保留距离
columnLeft.style.top = $(window).height() - columnLeft.scrollHeight - 10 + 'px';
} else {
// 左边栏还没加载出来,等 500 毫秒再找
setTimeout(function () {
columnLeft = $('.column-left')[0];
fixLeftColumnTop();
}, 500);
}
}
}
fixLeftColumnTop();
$(window).resize(fixLeftColumnTop);

如果你也想用这段代码,别忘了把 .column-left 替换成你的粘性元素的选择器,并在那个元素上添加 position: sticky; 样式~

另外一个小发现

Windows 环境,缩放 100% 下,当 top 的值为非整数像素值时,Chrome 会有元素内字体模糊的情况,Firefox 和 Edge 没有问题,所以有必要对 top 取整确保字体清晰。

粘性布局之粘底效果(position sticky, bottom 0)

https://www.imaegoo.com/2019/position-sticky-bottom/

作者

iMaeGoo

发布于

2019-11-17

更新于

2019-11-17

许可协议

CC BY 4.0

评论