一 实现原理
根据当前页面滚动条的高度判断当前页面应当与导航栏中哪个导航相关联,并对相应的导航设置高亮样式。
二 代码解析
先简单写一个页面顶端的导航栏:
<nav>
<ul>
<li><a class="nav active" href="#nav1">导航1</a></li>
<li><a class="nav" href="#nav2">导航2</a></li>
<li><a class="nav" href="#nav3">导航3</a></li>
<li><a class="nav" href="#nav4">导航4</a></li>
</ul>
</nav>
注意这里第一个导航初始添加一个active类,表示首页默认对应导航1。
为每个导航写一个对应的正文页面:
<div id="nav1" class="section">这是页面1</div>
<div id="nav2" class="section">这是页面2</div>
<div id="nav3" class="section">这是页面3</div>
<div id="nav4" class="section">这是页面4</div>
然后添加导航的CSS:
*{margin:0px;} /*先清除浏览器默认外边距*/
nav{
position:fixed;
width:100%;
z-index:999;
margin-top:0px
} /*fixed固定导航,并设置为最高层,防止被后面的元素遮盖。*/
nav ul{
text-align:center;
height:45px;
line-height:45px;
background:#0B0B0B;
}
nav li,nav li a{
display:inline-block;
height:100%;
text-decoration:none;
color:#fff;
}
nav li a{padding:0 10px;}
nav li{margin:0 10px;}
a:hover, .active{color:#B6B6B6;} /*为鼠标悬浮的状态以及当前页面对应的导航设置不同的颜色*/
添加正文的CSS:
.section{height:660px;
width:100%;
margin:10px auto;
background:#F5F5F5;
padding-top:60px;
box-sizing:border-box;
border:1px solid red;
text-align:center;
} /*注意将box-sizing设为border-box,每个页面的整体高度即为原来设定的高度,后面用JS计算页面高度时免去计算content、padding、margin的麻烦*/
此时样式如图所示:
下一步通过JS实现导航状态的切换:
首先获取所有的导航:
var navs=document.getElementByClassName('nav');
定义导航的切换方法,即每次通过增加一个类名active来为其应用已经设定好的样式,这里有4个导航,所以需要给4个元素添加类名。
function reset(index){
for(var i=0;i<4;i++){
navs[i].className="nav"; //注意每次添加类名之前先清空之前设置的active,否则只要经过的页面,对应的导航都是高亮状态
}
navs[index].className += " active";
}
由于是根据当前页面和滚动条的高度关联,从而利用滚动条的当前高度来判断应该切换哪个导航,因此要获取两个值:当前页面距离文档顶部的高度,以及当前滚动条的高度。
写一个函数来根据id获取单个页面整体的高度height
function getHeight(id){
var elem=document.getElementById(id);
var height=parseInt(window.getComputedStyle(elem,null)['height']);
return height;
}
调用这个函数并累加得出每个页面距离文档顶部的距离(不是窗口)。由于总共4个导航对应4个页面,所以只需判断3个页面即可。
var t1=getHeight("nav1");
var t2=t1+getHeight("nav2");
var t3=t2+getHeight("nav3");
再写一个函数通过将当前滚轮高度和当前页面距离文档顶部的高度来作比较,判断应当切换到哪个导航。将页面的滚动事件绑定到这个函数,实时获取滚轮高度的值,实现导航样式的实时切换:
window.onscroll=function changeCss(){
var t=document.documentElement.scrollTop || document.body.scrollTop; //获取当前页面滚动条的高度
if (t<t1){
reset(0); //当页面还处于第一页时,第一个导航亮起
} else if (t<t2){
reset(1); //当页面滚动到第二页时,第一个导航熄灭,第二个导航亮起
} else if (t<t3){
reset(2);
} else{
reset(3);
}
}
三 完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>别踩白块</title>
<style>
*{margin:0px;}
nav{position:fixed;width:100%;z-index:999;} /*fixed固定导航,并设置为最高层,防止被后面的元素遮盖。*/
nav ul{margin-top:0px;text-align:center;height:45px;line-height:45px;background:#0B0B0B;}
nav li,nav li a{display:inline-block;height:100%; text-decoration:none;color:#fff;}
nav li a{padding:0 10px;}
nav li{margin:0 10px;}
a:hover, .active{color:#B6B6B6;} /*为鼠标悬浮的状态以及当前页面对应的导航设置不同的颜色*/
.section{height:660px;width:100%;margin:0px auto;background:#F5F5F5;padding-top:60px;box-sizing:border-box;border:1px solid red;text-align:center;}
</style>
</head>
<body>
<nav>
<ul>
<li><a class="nav active" href="#nav1">导航1</a></li>
<li><a class="nav" href="#nav2">导航2</a></li>
<li><a class="nav" href="#nav3">导航3</a></li>
<li><a class="nav" href="#nav4">导航4</a></li>
</ul>
</nav>
<div id="nav1" class="section">这是页面1</div>
<div id="nav2" class="section">这是页面2</div>
<div id="nav3" class="section">这是页面3</div>
<div id="nav4" class="section">这是页面4</div>
<script>
var navs=document.getElementsByClassName('nav');
function reset(index){
for(var i=0;i<4;i++){
navs[i].className="nav"; //注意每次添加类名之前先清空之前设置的active,否则只要经过的页面,对应的导航都是高亮状态
}
navs[index].className += " active";
}
function getHeight(id){
var elem=document.getElementById(id);
var height=parseInt(window.getComputedStyle(elem,null)['height']); //计算渲染后的style值
return height;
}
var t1=getHeight("nav1");
var t2=t1+getHeight("nav2");
var t3=t2+getHeight("nav3");
window.onscroll=function changeCss(){
var t=document.documentElement.scrollTop || document.body.scrollTop; //获取当前页面滚动条的高度
if (t<t1){
reset(0); //当页面还处于第一页时,第一个导航亮起
} else if (t<t2){
reset(1); //当页面滚动到第二页时,第一个导航熄灭,第二个导航亮起
} else if (t<t3){
reset(2);
} else{
reset(3);
}
}
</script>
</body>
</html>
这一次是自己设计自己写的,所以没有视频资源。实际上用JQuery实现起来会更方便,但是用原生代码能够了解底层原理,加深理解。导航高亮的实现方式还有别的方法,例如利用URL与页面的对应关系,根据URL的变化判断当前页面应该对应的导航栏,但是这种方法也有一定的局限性,并不能适用于所有场景。