【前端】sticky粘性定位

时间:2021-2-20 作者:admin

基本效果

来自mdn的例子:position: sticky;top: 20px;

特性描述

看了下MDN和大佬们的讲解,通俗的总结如下:

  • 常规情况下同position:static;
  • 显示不超出其父元素的前提条件下,尽可能与 最近滚动祖先 保持指定的最小距离
  • 使用了 position:sticky; 的元素会为其子元素创建新的层叠上下文(stacking context)

最近滚动祖先 :以position:sticky;元素为起点往上找,遇到的第一个overflow-xoverflow-y不为visible的祖先节点。如果不存在,那么直接取 viewport (即浏览器视窗)。一个简略的查找算法如下:

function getStickyParent(node) {
  const parent = node.parentElement;
  if (!parent) return null;
  const style = window.getComputedStyle(parent);
  const overflows = style.overflow.split(" ");
  if (overflows.some((o) => o !== "visible")) {
    return parent;
  }
  return getStickyParent(parent);
}

常见误区

后面可看可不看,个人踩坑经验。

对“最近滚动祖先”理解有误

学习的时候有看到说sticky元素的任意祖先元素都不要设置overflow:hidden;,实际上应该是表述有误。

详细描述应该为:如果你想让一个元素sticky到一个祖先元素,那么这个祖先元素要设置overflow为非visible的值,而且要保证它们之间的任意元素都不能有overflow为非visible的值,否则这个元素就会成为你意料之外的“最近滚动祖先”。仅当你需要对 viewport 进行sticky,才需要确保任意祖先元素都没有该值。

没有触发效果

先来搞个demo:

<div style={{ width: 400, height: 400, overflow: "auto" }}>
  <div style={{ height: 400, background: "green" }}>
    <div style={{ height: 20, width: 20, background: "pink", position: "sticky", top: 0 }} />
  </div>
  <div style={{ height: 400, background: "red" }} />
</div>

这个很合理,一开始粉色块在没有超出绿色块的前提下,与最外面的“最近滚动祖先”尽可能保持顶部0px。但滚到最后时红色块就把绿色块完全顶开了,此时粉色块就不满足“在显示不超出其父元素的前提条件下”了,所以粉色块只能贴着绿色块的底部被一起往上顶了。

我们给粉色块再套个div#1:

<div style={{ width: 400, height: 400, overflow: "auto" }}>
  <div style={{ height: 400, background: "green" }}>
    <div id="1">
      <div style={{ height: 20, width: 20, background: "pink", position: "sticky", top: 0 }} />
    </div>
  </div>
  <div style={{ height: 400, background: "red" }} />
</div>

这个就是常见的无效了。因为粉色块的父元素变成了div#1,而div#1的高度默认就是粉色块的高度,所以粉色块没啥操作空间,只能从头到尾跟着它的父元素div#1一起被滚动

关于这个条件的原理部分:深入理解position sticky粘性定位的计算规则

最后

原来码了2000多字,不过后面一看发现又长又臭,删减下来发现一天的时间就快没了,难受。求个老司机传授下快速写作的经验,感觉因为用时太长已经没有以前的热情了/(ㄒoㄒ)/~~

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。