网站首页 » 前端开发 » JavaScript » 纯 JavaScript 固定导航效果(fixed)
上一篇:
下一篇:

纯 JavaScript 固定导航效果(fixed)

前言

现在不少网站页面本身内容都会比较多,从而导致页面过长,当用户浏览页面时,如果要用户反手动拉滚动条回到顶部找导航那多少会有点不方便,或者说这样用户体验不怎么好。其实他个问题有很多种解决方案,如:给页面添加一个返回顶部的按钮,这样用户就可以快速地返回到顶部。那很多时候我们就是导航固定在页面的顶部,毕竟这个对于提高用户体验还是有帮助的。下面我们就来看看如何通过纯 JavaScript 实现导航固定效果。

效果示例: http://yunkus.com/demo/news-scroll/javascript-nav-fixed-demo.html

代码实现

先不多说,代码贴上。上完代码之后,我们再慢慢来分析下代码的前世今生,毕竟很多东西还是得讲个明明白白,才会有说服力,才能让你觉得没有白看,我最讨厌的就是网上很多资料都是烤来烤去的,甚至有些代码有什么作用,都不知道,但我还是相信还有很多和我一样的前端人在用心的记录自己的成长。

CSS 代码

*{padding: 0;margin: 0;border: 0}
body{height: 5000px}
a{text-decoration: none;}
li{list-style: none}
.oh{overflow: hidden;}
.nav-wrap{width: 100%;background: #33363b;border-top: 2px solid #ccc}
.main-nav{width: 980px;margin:0 auto; box-shadow: 0 3px 13px #000; margin-bottom: 0; background: #33363b;box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 -1px 0 rgba(0,0,0,0.2), inset 1px 0 0 rgba(0,0,0,0.2), inset -1px 0 0 rgba(0,0,0,0.2)}
.main-nav li{float: left;}
.main-nav a{display: block; padding: 15px 14px;font-size: 16px;line-height: 20px;color: #888;-webkit-transition:color 0.5s; transition:color 0.5s;}
.main-nav li a:hover{color: #fff;background: rgba(0,0,0,0.1);text-decoration: none;}

HTML 代码

<div style="margin-top:100px" class="s-wrap"></div>
 <div id="nav-contrl">
  <div class="nav-wrap">
   <ul class="main-nav oh">
    <li><a href="http://yunkus.com" title="首页"><span>网站首页</span></a></li>
    <li><a class="nav-link" href="http://yunkus.com/category/fewd/" title="前端开发">前端开发</a></li>
    <li><a class="nav-link" href="http://yunkus.com/category/cms/" title="CMS">CMS</a></li>
    <li><a class="nav-link" href="http://yunkus.com/category/operator/" title="网站运营">网站运营</a></li>
    <li><a href="http://zhaoxixiong.com" title="朝夕熊博客" target="_blank"><span>朝夕熊</span></a></li>
   </ul>
  </div>
</div>

JavaScript 代码

/*下面这几行代码你可以按需要修改*/
var navContrl = document.getElementById('nav-contrl');
var navWrap = navContrl.getElementsByTagName('div')[0];
navWrap.tempT = getOffsetTop(navWrap,true).top;
window.onscroll = function(){
 slideOpacity(navWrap,0);
}
/* 下面就是封装好的函数,你可以不用动它 */
function slideOpacity(target,initialValue){
 var scropT = GetPageScroll() + initialValue;
 if(scropT > target.tempT){
  target.style.position='fixed';
  target.style.top= 0 + initialValue +'px';
 }else{
  target.style.position='static';
 }
function GetPageScroll() {
var y;
if(window.pageYOffset) {
// Safari
y = window.pageYOffset;
} else if(document.documentElement
&& document.documentElement.scrollTop) {
// IE6、IE7、IE、IE8、IE9
y = document.documentElement.scrollTop;
} else if(document.body) {
// 非IE + IE10 + Edge
y = document.body.scrollTop;
}
return y;
}
}
function getOffsetTop(obj,flag) {
if(flag){
 var t = obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
 var l = obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
 while ( obj = obj.offsetParent ) {
 t += obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
 l += obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
}
}else{
 t = obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
 l = obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
}
return {top:t,left:l}
}
function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}
else{
return getComputedStyle(obj,false)[attr];
}
}

在实际的项目中,你只需要写几行代码就可以了。

var navContrl = document.getElementById('nav-contrl');
var navWrap = navContrl.getElementsByTagName('div')[0];
navWrap.tempT = getOffsetTop(navWrap,true).top;
window.onscroll = function(){
 slideOpacity(navWrap,0);
}

上面例子中后面其余代码你都不需要动他,复制到你的项目中就可以了。我想说的是slideOpacity(navWrap,0);这个方法中的第二个参数,它是一个数字,你可以按需要传入这个数值,这个数值是作用是,设置目标(如:本例导航),距离浏览器窗口顶部多高时开始固定。

案例剖析

样式细节

样式中有两个地方我觉得需要给大家说明下的,第一body{height:5000},这个相信你应该知道有什么作用了,就是让页面足够高,并且产生滚动条,实际的项目中这个是不需要的,在这里只是为了作测试之用。

第二个需要说明下的样式就是*{padding: 0;margin: 0;border: 0}、在说这个之前其实是有一段小小的插曲的。当我把这个效果整理出来后,在非IE浏览器中运行都没问题,但在IE中运行时却没有反应,导航竟然没有顶部固定效果了,关键是也没有报错,这是我最不想看到的。这个问题也花了我不少时间去排查,但后才发现原来我没有给元素重置border ,因为如果你没有给所有元素默认的border重置为0,那么在用getStyle()方法获取borderTopWidth;或者borderLeftWidth时,就会出现问题,非 IE浏览器是没问题的,还是万恶的IE,它没那么智能,当你通过getStyle()方法获取borderTopWidth或者borderLeftWidth时,就会给你返回一个元素默认值 – medium , 所以var t = obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));所得到的值就变成了NaN(not a number[不是数字]) 难怪会出现在实际运用中,和我自己在整理中时出现了不一样的结果。这也是我之前没有想到的。

下面我们就把JavaScript 代码分成一个功能块一个功能来讲解。我觉得这样更有助于你对整个代码的结构的理解。

获取样式函数

function getStyle(obj,attr){
 if(obj.currentStyle){
  return obj.currentStyle[attr];
 }else{
  return getComputedStyle(obj,false)[attr];
 }
}

这个其实就是一个获取元素属性值的函数,这个函数已经封装好,你可以直接拿来用到自己的项目中去。你只需要往这个函数里传两个参数(对像,属性)就可以了。如getStyle(navWrap,’width’);这样就可以得到对象的宽了。其实属性值同理。

离body距离函数

function getOffsetTop(obj,flag) {
 if(flag){
  var t = obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
  var l = obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
  while ( obj = obj.offsetParent ) {
   t += obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
   l += obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
  }
 }else{
  t = obj.offsetTop + parseInt(getStyle(obj,'borderTopWidth'));
  l = obj.offsetLeft + parseInt(getStyle(obj,'borderLeftWidth'));
 }
 return {top:t,left:l}
}

这个函数的作用就是获取指定元素距离页面最顶部的距离。这个函数你也是可以单独出来用到项目中的。getOffsetTop(obj,flag) 有两个参数,第一个是要目标元素对象,第二个参数就是一个布尔值(true | false),这个布尔值有什么用呢?这里分两种情况,第一种就是父元素没有设置定位(相对定位或者绝对定位)时第二个参数是true或者是false都没关系,但如果父元素被设置成了定位时,若值为 true 时,而所获取的这个距离是离 body 的高度,而如果这个值为 false 时那么getOffsetTop()方法只会获取目标元素离父元素的高度。如果你还是不明白,那么我们可以来看看一个例子。

HTML代码

<div style="margin-top:100px" class="s-wrap"></div>
<div style="padding-top: 10px;position: relative;">
<div id="nav-contrl">
<div class="nav-wrap">
<ul class="main-nav oh">
<li><a href="http://yunkus.com" title="首页"><span>网站首页</span></a></li>
<li><a class="nav-link" href="http://yunkus.com/category/fewd/" title="前端开发">前端开发</a></li>
<li><a class="nav-link" href="http://yunkus.com/category/cms/" title="CMS">CMS</a></li>
<li><a class="nav-link" href="http://yunkus.com/category/operator/" title="网站运营">网站运营</a></li>
<li><a href="http://zhaoxixiong.com" title="朝夕熊博客" target="_blank"><span>朝夕熊</span></a></li>
</ul>
</div>
</div>
</div>

JavaScript代码

var navContrl = document.getElementById('nav-contrl');
var navWrap = navContrl.getElementsByTagName('div')[0];
alert(getOffsetTop(navWrap,false).top);

当第二个参数为false时,会弹出一个10,也就是目标元素离父元素的高度。而如果第二个参数为true时,弹出的结果就变成了110。也就是目标元素离body的高度。

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/javascript-nav-fixed/

Leave a Reply

Your email address will not be published. Required fields are marked *

评论 END