可吸附到顶部的导航条的实现 | 天一阁

可吸附到顶部的导航条的实现

一直觉得可以吸附在顶部的导航条很神奇,今天仔细研究了一下,记录在此。其实主要用到的就是window.scroll 事件,当导航条移动到浏览器顶部时,就固定住,如果又下移到非顶部了,则恢复原来的样式。通过绑定scroll事件,调整DOM元素的postion样式,在static和fixed两个属性之间进行切换。

Position样式

整个网页在展现时,浏览器使用的是盒模型。

默认的布局模式叫文档流,我的理解就是,HTML里面的每个元素像在河上流动的物体一样,在页面上,从上到下一个个流出来。通过更改position的属性,可以实现一些特殊效果。

position选值包括static, relative, absolute, fixed, sticky

  • static 是默认的方式,按照盒模型的基本方式进行展示。对于基本的布局,position其实也用不上,用好float就可以了。可能flex的方式更加符合现在的布局特点。
  • relative 是在普通的static基础上,对元素的位置进行微调,通过设置top, right, bottom, left这四个值,可以让元素在原本应在的位置上,做偏移。原位置上会留下空白,后续的元素并不会受影响。
  • absolute 是把元素从文档流中取出,然后相对于最近的非static的父元素,进行偏移。这个元素的子元素,都会跟着他一起定位到新地方去。后续的兄弟元素在布局时,全当没看见过他,继续正常的盒模型。
  • fixed 也不为元素留空间,根据viewport进行偏移,相当于是无论网页怎么滚动变化,这个元素相对于浏览器窗口的位置是不变的(Top, left相对左上不变, Bottom, right,相对右下不变)

对于要动态置顶的元素块,就是让positioin从static到fixed之间切换,必要时,还需要一个placeholder,避免此元素从文档流中取出后,破坏后面元素的布局。和布局相关的样式还包括display、float、flex这几个都是布局相关的。

Scroll事件

当页面发生滚动事件时,就会调用绑定的事件处理函数

1
window.onscroll = funcRef;
  • funcRef 是个函数类型的对象引用或者匿名函数.

可以在页面DOM加载完成时,绑定onscroll函数,比如这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//当页面加载完毕时
window.onload=function(){
console.log("window.onload");
//获取要吸附的元素
var oDiv1=document.getElementById('div1');
//获取被吸附时,原位置占位的元素,以免影响其他元素布局(占位元素样式一致,背景透明,初始不可见)
var oDiv2=document.getElementById('div2');
//设置一个变量存储元素到顶部的距离
var divT=getPos(oDiv1).top;//调用json里的数据对应top的值
//当滚动条变化时,执行函数
window.onscroll=function(){
//定义一个变量,获取并存储滚动条纵向移动的距离
var scrollTop=document.documentElement.scrollTop || document.body.scrollTop;
//判断吸顶条效果产生时需要的条件是否成立(当滚动距离大于或者等于元素离顶部距离的时候,吸附效果呈现)
if(scrollTop >= divT){
//设置css样式产生吸附效果
oDiv1.style.position='fixed';
oDiv1.style.left=0;
oDiv1.style.top=0;
//并且让占位元素显示
oDiv2.style.display='block';
}
//当条件不成立时,物体返回原位(还原之前的的样式)
else{
//取消定位
oDiv1.style.position='';
//并且让占位元素隐藏
oDiv2.style.display='none';
}
};
};

立即执行函数表达式(IIFE)

总是不能明白IIFE的作用,实际上就是一个立即执行的代码段,因为所有的代码是在一个函数里面,所以这里面定义的变量不会污染全局环境。而且如果这段代码在HTML的最底部,他会有window.onload类似的效果,常用的语法形式就是

1
2
3
(function(){
。 。 。
})();

PS:一点感想,能把一个知识点清晰地有条理有层次的表达出来是件不容易的事情,需要经过一定的锻炼。这是第三篇了,我看看我写个100篇会怎么样?以前我也是因为忙,也是因为懒,很多问题没有深入,止步于看上去可以run了,既不去管背后的原理,也不去追求更好的解决方案,使得自己进步的不“实在”。看上去好像能够解决很多的问题,但实际上对于知识结构的升级,没有系统性。不仅仅是技术,对于其他知识也是如此,这应该是一种思维习惯的锻炼。之前能够拿出可以run的解决方案,但是只要一评审,总会有很多地方被人问到哑口无言,就是因为只看了表面的,而没有自己的理解。后面,时间也比较充裕,争取改进一下。

DEMO
参考文档

关于相关CSS

https://developer.mozilla.org/zh-CN/docs/Web/CSS/position

http://www.awaimai.com/447.html

http://www.jianshu.com/p/59e8924c0fd4

关于window.onload事件

http://www.cnblogs.com/lovesong/p/5641834.html

https://stackoverflow.com/questions/588040/window-onload-vs-document-onload

关于立即执行函数表达式(IIFE)

https://segmentfault.com/a/1190000003985390