引子
最近碰到一个效果:页面滚动时,当指定元素超出可视区时,需要固定在可视区顶部。后来想到另外一种方式,在此统一记录一下。
思路一
这种思路比较常见,很早就有在使用,具体是监听滚动事件,在处理事件程序中计算指定元素到可视区顶部的位置,超出可视区时更改元素 position 属性脱离原来的文档流。
这里需要注意的点有:
- 元素脱离了文档流后,原本所占据的位置,需要处理,否则元素后面的内容会出现突然上移的现象。
- 滚动事件频繁触发的处理,离开页面时记得要解除事件绑定。
这是示例页面,移动端访问如下:

示例主要代码
<!doctype html> <html lang="en"> <head></head> <body> <div id="titleHolder"></div> <h2 class="title" id="title">需动态固定的元素</h2> <div>内容</div> </body> </html>
body { overflow-y: auto; -webkit-overflow-scrolling: touch; } .title-holder, .title { top: 0; margin: 0; width: 100%; height: 50px; line-height: 50px; text-align: center; background-color: #fff; }
var scrollObj = document.querySelector('body'); var targetHolderEle = document.querySelector('#titleHolder'); var targetEle = document.querySelector('#title'); var scrollMark = null; function dealScroll() { if (scrollMark) { clearTimeout(scrollMark); } scrollMark = setTimeout(() => { var topDistance = 0; // getBoundingClientRect 有些浏览器不支持 if (targetHolderEle.getBoundingClientRect) { var pos = targetHolderEle.getBoundingClientRect(); topDistance = pos.top; } else { var eleTop = targetHolderEle.offsetTop; topDistance = eleTop - scrollObj.scrollTop; } if (topDistance < 1) { targetHolderEle.setAttribute('class','title-holder'); targetEle.style.position = 'fixed'; } else { targetHolderEle.setAttribute('class',''); targetEle.style.position = 'static'; } }, 10); } function listenScroll() { scrollObj.addEventListener('scroll', dealScroll); }
思路二
使用新的 position
值 sticky
。想到这个,是因为想起曾写过 position 属性值 sticky 这篇总结。这种方式相对减少了很多代码,兼容性的问题,看实际应用场景的要求。
这是示例页面,移动端访问如下:

参考资料
- Perfectly smooth transition between fixed and variable positioning of HTML elements using CSS and Javascript
- 用Javascript获取页面元素的位置
来源:https://www.cnblogs.com/thyshare/p/12204113.html