一 实现原理

根据当前页面滚动条的高度判断当前页面应当与导航栏中哪个导航相关联,并对相应的导航设置高亮样式。

二 代码解析

先简单写一个页面顶端的导航栏:
<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的变化判断当前页面应该对应的导航栏,但是这种方法也有一定的局限性,并不能适用于所有场景。

JS原生代码实现导航高亮的更多相关文章

  1. js原生代码实现轮播图案例

    一.轮播图是现在网站网页上最常见的效果之一,对于轮播图的功能,要求不同,效果也不同! 我们见过很多通过不同的方式,实现这一效果,但是有很多比较麻烦,而且不容易理解,兼容性也不好. 在这里分享一下,用j ...

  2. 仿jQuery的siblings效果的js原生代码

    仿jQuery的siblings效果的js原生代码 <previousSibling> 属性返回选定节点的上一个同级节点(在相同树层级中的前一个节点). <nextSibling&g ...

  3. 用Node.js原生代码实现静态服务器

    ---恢复内容开始--- 后端中服务器类型有两种 1. web服务器[ 静态服务器 ] - 举例: wamp里面www目录 - 目的是为了展示页面内容 - 前端: nginx 2. 应用级服务器[ a ...

  4. 基于面向对象的图片轮播(js原生代码)

    无论你想走多远,你都需要不断地走下去.前端最精华的便是原生的js,这也是我们前端工程师的技术分层的重要指标,也提现这你的代码能力,开发的水平.废话不多说,进入今天的主要分享————基于面向对象思想的图 ...

  5. JS原生代码之倒计时抢购

    学到了原声js改变input的disabled的属性值,因为想让倒计时结束的同时,抢购按钮可以被点击.代码为:document.getElementById("buy").disa ...

  6. day28(ajax之js原生代码实现)

    ajax ajax:异步页面无刷新技术 AJAX:异步的 JavaScript And XML. * 使用的是老的技术,用的是新的思想. AJAX的功能:完成页面的局部刷新,不中断用户的体验. XML ...

  7. js原生代码实现鼠标拖拽(超简单)

    首先先来看这一张图 在这种图中,盒子的大小为512px,并且margin-left:-250px margin-top:140px;并通过一些样式让其在中部显示 这些样式都不是重要的,这里加个marg ...

  8. js原生代码编写一个鼠标在页面移动坐标的检测功能,兼容各大浏览器

    function mousePosition(e) {     //IE9以上的浏览器获取     if (e.pageX || e.pageY) {         return {         ...

  9. 高效的js原生代码

    1.遍历元素 //不推荐 var element = document.getElementsByTagName('div'); for(var i=0; i<element.length; i ...

随机推荐

  1. mvn mybatis-generator:generate postgresql

    postgresql 配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE genera ...

  2. BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]

    1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...

  3. 面向对象编程总结--Python

    万物皆为对象.自然环境赋予人类无尽的遐想,而面向对象编程之思想就是来自于大自然.自然界,类和对象比比皆是,比如:鸟类和麻雀,鱼和鲤鱼......其中鸟类就是各种鸟的总称,而麻雀只不过是其中之一(对象) ...

  4. python爬虫(6)——正则表达式(三)

    下面,我再写一个例子,加强对正则表达式的理解.还是回到我们下载的那个二手房网页,在实际中,我们并不需要整个网页的内容,因此我们来改进这个程序,对网页上的信息进行过滤筛选,并保存我们需要的内容.打开ch ...

  5. python通过一个语句分析几个常用函数和概念

    前言 过年也没完全闲着,每天用一点点时间学点东西,本文为大家介绍几个python操作的细节,包含all.any.for in等操作,以及介绍我解决问题的思路. 一.开篇 先从我看到的一个简单的语句开始 ...

  6. [CQOI2006]凸多边形

    很明显是一道半平面交的题. 先说一下半平面交的步骤: 1.用点向法(点+向量)表示直线 2.极角排序,若极角相同,按相对位置排序. 3.去重,极角相同的保留更优的 4.枚举边维护双端队列 5.求答案 ...

  7. 平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。

    题目:平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小. 源码如下: #include <iostream> #include <string.h> #incl ...

  8. Date 类

    一.Date类型的初始化 1. Date(int year, int month, int date); 直接写入年份是得不到正确的结果的. 因为java中Date是从1900年开始算的,所以前面的第 ...

  9. 使用FFMPeg对视频进行处理

    FFMPeg处理视频的核心操作方式是命令,无论是在Windows上还是Linux上.那么下边就简单介绍下,常见的处理命令. 示例1:截取一张352×240尺寸大小的,格式为jpg的图片: ffmpeg ...

  10. 项目中AppDelegate详解

    1.AppDelegate.h //模板默认引入程序需要使用“类”的框架,即UIKit.h头文件,使它包含在程序中 #import <UIKit/UIKit.h> //此处@class声明 ...