关于吸顶的问题想请教一下

新手上路,请多包涵

想实现吸顶的效果,搜索后发现可以使用getBoundingClientRect来实现。但我测试的时候发现当元素到达吸顶的条件后,继续往下滚动,吸顶元素会在static和fixed之间来回切换导致元素一直在闪烁。打印top值会发现一会是正常的top值,一会是0,想请问下是为什么?
以下是代码

  <style>
    p {
      margin: 0;
      height: 47px;
    }
    .fixed {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 9;
    }
  </style>
</head>
<body>
<div style="background-color: red; height: 200px;">12312321</div>
<div style="height: 47px">
  <p id="p">吸顶</p>
</div>
<div style="background-color: yellow; height: 2000px;">12312321</div>
<script>
window.addEventListener('scroll', function () {
  const p = document.querySelector('#p');
  const top = p.getBoundingClientRect().top;
  console.log(top)
  if (top < 0) {
    p.classList.add('fixed');
  } else {
    p.classList.remove('fixed');
  }
})
</script>
阅读 2.8k
3 个回答

getBoundingClientRect是相对视图窗口的.所以你应该获取父元素的top。

const top = p.parentElement.getBoundingClientRect().top;

其实也可以用offsetTop,

if (p.parentElement.offsetTop <= (document.documentElement.scrollTop || document.body.scrollTop)) {
    p.classList.add('fixed');
} else {
    p.classList.remove('fixed');
}

你不能用 #p 与窗口的位置参数来判断,不然往上滚动的时候就会出现:

  1. top 小于零,固定,使 top 变成 0
  2. 在第一步之后 top 变成了 00不小于 0,所以取消固定,任其滚动;
  3. 取消固定之后,top 小于零,固定,使 top 变成 0

……
这就陷入死循环了,表现出来就是你所说的“闪烁”。就算你解决了闪烁的问题,当你往下滚的时候,由于 #p 仍旧被固定在那里,它的 top 不会变化,不可能再回到文档流了,除非你再次干预。


解决问题之道:以 #p 的父元素的 top 来判断,小于某个阈值的时候固定 #p

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题