创建顶部导航,页面向下滚动的时候导航条闪动

大家好,我要创建一个顶部导航,因为一些原因必须使用绝对定位。但是当滚动条往下的时候,这个导航条会闪动的很累还。代码如下:
<!DOCTYPE html>
<html>
<head>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<style>
     body, html {
            padding:0;
            margin: 0;
            width: 100%;
            height: 100%;
            position: relative;
        }
  #top {
            position: absolute;
            left:0;
            top:0;
            height: 20px;
            width: 100%;
            background-color: red;
        }
        #body {
            width: 100%;
            height: 150%;
            background-color: yellow;
        }
</style>

</head>
<body>
<div id="top"></div>
<div id="body"></div>
</body>

<script>
var doc = document;
var Dtop = doc.getElementById('top');
var dBody = doc.getElementById('body');

function getScrollTop(){

var scrollTop=0;
if(document.documentElement&&document.documentElement.scrollTop)
{
    scrollTop=document.documentElement.scrollTop;
}
else if(document.body)
{
    scrollTop=document.body.scrollTop;
}
return scrollTop;

}

window.addEventListener('scroll', function(e){

var e = window.event || e;
var scrollTop = getScrollTop();
Dtop.style.top = scrollTop + 'px'

})

</script>
</html>

求解决方法,谢谢

阅读 3.1k
2 个回答

两种方案

  1. @XYShaoKang 所说,改 absolute 为 fixed,这是最简单直接的办法。至于你提到不得不用绝对定位的原因,方便的话,可以讲出来大家一起分析。
  2. 将滚动区移到 body 内部,比如这样
<body>
  <div id="top"></div>
  <div id="body">
    <main>body的内容移到这里</main>
  </div>
</body>
body {
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  position: relative;
}
#top {
  height: 20px;
  width: 100%;
  background-color: red;
}
#body {
  height: 400px;
  overflow-y: auto;
}
main {
  width: 100%;
  height: 500px;
  background-color: yellow;
}

两种做法都不需要 js 的参与。


和题主沟通,得知因为安卓手机支持 position fixed 有问题,所以才只使用 absolute。我翻到一篇关于这个的老文章,有兴趣的朋友看看。

Easy CSS fix for fixed positioning on Android 2.2 and 2.3

因为scroll的触发速度比渲染速度来的快,比如你向下滚动100,事件触发,改变 top 的值,页面渲染,然后你向下 100 的时候,这个速度超过渲染计算的速度,渲染还没有完成,出现的掉帧

解决办法就是直接用 css 来做.把 top 的position: absolute改成position: fixed,然后把绑定的事件去掉
这是一种解决办法,如果有其他的需求的话,在说.


补充

抱歉之前没注意到必须要使用绝对定位这个需求
如果一定要用绝对定位的话,可以试试requestAnimationFrame
掉帧的原因是scroll事件和渲染之间的不同步,那就不用scroll事件,用requestAnimationFrame
requestAnimationFrame方法会在每次重绘之前调用,这样就不会出现不同步的情况
性能的话我没实际测试过,你可以看看最后的参考文章
兼容性的查询也在后面的参考文章里面

function nextFrame() {
  requestAnimationFrame(function() {
    var e = window.event || e
    var scrollTop = getScrollTop()
    Dtop.style.top = scrollTop + 'px'
    nextFrame()
  })
}
nextFrame()

@驽马 提供的方法也是可以的,通过分层来解决,下面的滚动不会影响上面的定位,看你实际需要的效果和需求来决定


另外你这个排版呀,有空学学markdown的语法
把你的所有 html 代码放在下面的两个标签里面

图片描述

就能显示下面的效果

<html>
...
</html>

参考

【前端性能】高性能滚动 scroll 及页面渲染优化

补充

浏览器的 16ms 渲染帧
window.requestAnimationFrame
使用requestAnimationFrame获得更好的性能
requestAnimationFrame 兼容性

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