原生JS实现导航下拉菜单效果

这个导航下拉菜单需要实现的功能是:下拉菜单的宽度与浏览器视口的宽度一样宽;一级导航只有两项,当鼠标移到一级导航上的导航项时,相应的二级导航出现。在本案例中通过改变二级导航的高度来实现二级导航的显示和消失。为了便于理解我画了一个图,如下:

在这个案例主要用到的知识有:设置定时器,清除定时器,mouseout和mouseover事件,另外还有css中position相关知识。本案例分为两部分讲解。第一部分html和css,第二部分js。

一. html和css

将导航这个导航条包裹在一个div中,这个div的position值为relative,高度为50px(导航条的高度为50px),宽度为100%,将最外层的div的position属性设置为relative是因为二级导航要根据这个div来定位。这个导航条的结构是二级嵌套无序列表。每一个一级导航项li都嵌套了它对应的无序列表。需要将嵌套的无序列表移除文档流。所以嵌套的无序列表的position值为absolute,top:50px(导航条的高度)。left:0;right:0;通过设置这些值可以使嵌套的无序列表宽度为浏览器视口的宽度。通过将li的display值设置inline-block并且将外层div的text-align设置为center使得导航项居中显示。

注:在这个案例中一定要将嵌套的无序列表的position的值设置为absolute,使它移除文档流。

html和css代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>下拉菜单</title>
  <link rel="stylesheet" type="text/css" href="index.css" rel="external nofollow" >
</head>
<body>
  <div class='header'>
    <ul class='outer' id='outer'>
      <li class='outerList' id='outerList1'><a href='#' id='link1' class='link'>产品<span></span></a>
        <ul class='inter' id='inter1'>
          <li>
            <a href='#'>
              <img src='img/01fea55541ed73000001714a430253.jpg'>
              <strong>纳斯</strong>
            </a>
          </li>
          <li>
            <a href='#'>
              <img src='img/thumb_image3.jpg'>
              <strong>纯色</strong>
            </a>
          </li>
          <li>
            <a href='#'>
              <img src='img/白胡子.jpg'>
              <strong>保温杯</strong>
            </a>
          </li>
          <li>
            <a href='#'>
              <img src='img/宠物.jpg'>
              <strong>设计周边</strong>
            </a>
          </li>
        </ul>
      </li>
      <li class='outerList' id='outerList2'><a href='#' id='link2' class='link'>服务<span></span></a>
        <ul class='inter' id = 'inter2'>
          <li>
            <a href='#'>
              <img src='img/狮子座.jpg'>
              <strong>售后服务</strong>
            </a>
          </li>
          <li>
            <a href='#'>
              <img src='img/莲花禅.jpg'>
              <strong>设计师</strong>
            </a>
          </li>
        </ul>
      </li>
    </ul>
  </div>
  <script type="text/javascript" src='index.js'></script>
</body>
</html>

css代码如下:

*{
  padding: 0;
  margin: 0;
}
.header{
  position: relative;
  width: 100%;
  height: 50px;
  background-color: #000000;
  text-align: center;
  z-index: 2;
}
.header .outer li{
  display: inline-block;
  list-style: none;
}
.outerList{
  height: 50px;
  line-height: 50px;

}
.outerList a{
  display: block;
  padding: 0 15px;
  color: #fff;
  text-decoration: none;
}
.outerList:hover a{
  color: #EDECEC;

}
.outerList .link span{
  display: block;
  height: 0;
  width: 100%;
  position: relative;
  top: -10px;
  left: 0;
  background-color: #fff;

}
.outerList:hover .link span{
  height: 1px;
}
.outerList .inter{
  position: absolute;
  left: 0;
  height: 0;
  overflow: hidden;
  top: 50px;
  right: 0;
  background-color:rgba(0,0,0,0.5);
}
.outerList .inter li{
  margin-top: 30px;
}
.outerList .inter strong{
  display:block;
  height: 25px;
  line-height: 25px;
  text-align: center;
}

二. js部分

在js部分涉及到的知识主要有:设置定时器,清除定时器,mouseout和mouseover事件。

mouseout事件当鼠标从一个元素上移入另一个元素的上时,会在失去鼠标的那个元素上触发mouseout事件。获得鼠标的那个元素可能是失去鼠标的元素的父元素或子元素,获得鼠标的那个元素也可能位于失去鼠标元素的外部。当在一级导航项上触发mouseout事件时,我们需要判断获得鼠标的元素是不是一级导航项的子孙元素。当一个元素触发了mouseout事件时,去鼠标的元素为目标元素(target),获得鼠标的元素为相关元素(relatedTarget)。所以需要判断相关元素是否为一级导航项的子孙元素,如果是子孙元素,则相应的导航项的二级导航项高度不变。如果不是子孙元素,则相应的二级导航项消失。判断是否为子孙元素的代码如下:

var flag1 = false,flag2 = false;

if(relatedTarget !== null){
    var parented = relatedTarget.parentNode;
    do{
      if(parented === outerList1 || relatedTarget === outerList1){
        flag1 = true;
        break;
      }else if(parented === outerList2 || relatedTarget === outerList2){
        flag2 = true;
        break;
      }else{
        parented = parented.parentNode;
      }
    }while(parented !== null);
  }

注:通过判断flag1和flag2的值来确定是否该把二级菜单的高度变为0,如果flag1的值为false则让outerList1对应的二级菜单消失,如果flag2为false则将outerList2对应的二级菜单消失。

mouseover事件当鼠标移入一个元素内部时,获得鼠标的元素上触发这个事件,获得鼠标的元素可能位于失去鼠标的外部,也可能位于失去鼠标元素的内部。获得鼠标的元素是目标元素,失去鼠标的元素为相关元素。在这个案例中我们只需要判断mouseover的目标元素,但是对于mouseout事件我们需要判断相关元素。

注:在支持DOM的浏览器中,mouseout和mouseover的相关元素都保存在事件对象(event)的relatedTagrget属性中,但是在IE浏览器中,对于mouseout事件而言,相关事件保持在事件对象(event)的toElement属性中,对于mouseover事件而言,相关事件保存在事件对象(event)的fromElement属性中。

设置定时器和清除定时器在这个案例中嵌套无序列表的消失和出现是通过改变它的高度实现的,它的高度是逐渐变化,所以我使用的setTimeout这个定时器,为了能够清除定时器还要将定时器标识保存在一个变量中。清除定时器的目的是为了防止当快速移动鼠标时嵌套无序列表的高度抖动(即:一个定时器里的回调函数让高度增加,另一个定时器的回调函数让高度减小)。

js代码如下:

var untilEvent = {
  addEvent:function(element,type,hander){
    if(element.addEventListener){
      element.addEventListener(type,hander,false);
    }else if(element.attachEvent){
      element.attachEvent('on'+type,hander);
    }else{
      element['on'+type] = hander;
    }
  },
  getEvent:function(event){
    return event?event:window.event;
  },
  getTarget:function(event){
    return event.target||event.srcElement;
  },
  getRelated:function(event){
    if(event.relatedTarget){
      //兼容DOM的浏览器将相关元素保持在relatedTarget属性中
      return event.relatedTarget;
    }else if(event.toElement){
      //在IE浏览器中mouseout事件的相关元素保存在toElement属性中
      return event.toElement;
    }else if(event.fromElement){
      //在IE浏览器中mouseover事件的相关元素保持在fromElement属性中
      return event.fromElement;
    }else{
      return null;
    }
  }

};
//下面这四个元素用于表示四个定时器的标识,最开始我只使用两个定时器,当快速移动时
//动画会乱。
var timeDec1,timeAdd1,timeAdd2,timeDec2;//定时器标识
function getOuter(){
  var outer = document.getElementById('outer');
  untilEvent.addEvent(outer,'mouseover',callBackOver);
  untilEvent.addEvent(outer,'mouseout',callBackOut);
}
//mouseout事件:当鼠标从一个元素移入另一个元素时在鼠标离开的那个元素
//上触发,获得鼠标的元素可能在失去鼠标元素的外部也可能在失去鼠标元素的
//内部.所以需要判断mouseout事件的相关元素是否为外部li(即id为outerList或id为outerList2)元素
//的子孙元素,如果是子孙元素,则内部无序列表无须收起。
function callBackOut(event){
  var event = untilEvent.getEvent(event);
  var relatedTarget = untilEvent.getRelated(event);
  var outerList1 = document.getElementById('outerList1');
  var inter1 = document.getElementById('inter1');
  var outerList2 = document.getElementById('outerList2');
  var inter2 = document.getElementById('inter2');
  var flag1 = false,flag2 = false;
  if(relatedTarget !== null){
    var parented = relatedTarget.parentNode;
    do{
      if(parented === outerList1 || relatedTarget === outerList1){
        flag1 = true;
        break;
      }else if(parented === outerList2 || relatedTarget === outerList2){
        flag2 = true;
        break;
      }else{
        parented = parented.parentNode;
      }
    }while(parented !== null);
  }
  if(!flag1){
    var str1 = 'flag1';
    changeHeightDec(inter1,timeAdd1,str1);
  }
  if(!flag2){
    var str2 = 'flag2';
    changeHeightDec(inter2,timeAdd2,str2);
  }
}
function changeHeightDec(element,timer,flag){
  var offHeight = 70;
  var inverTimer = 10;
  clearTimeout(timer);
  change();
  function change(){
    var height = parseInt(element.style.height);
    if(!height)height = 0;
    if(height > 0){
      if(height - offHeight > 0){
      element.style.height = height - offHeight +'px';
      }else{
        element.style.height = 0+'px';
      }
      if(flag === 'flag1'){
       timeDec1= setTimeout(change,inverTimer);
      }else{
        timeDec2 = setTimeout(change,inverTimer);
      }
    }
  }
}
function callBackOver(event){
  var event = untilEvent.getEvent(event);
  var target = untilEvent.getTarget(event);
  var inter1 = document.getElementById('inter1');
  var inter2 = document.getElementById('inter2');
  if(target.id == 'outerList1' || target.id == "link1"){
    var str1 = "flag1";
    changeHeight(inter1,timeDec1,str1);
  }
  if(target.id == 'outerList2' || target.id == 'link2'){
    var str2 = "flag2";
    changeHeight(inter2,timeDec2,str2);
  }
}
function changeHeight(element,timer,flag){
  var totalHeight = 160;
  var inverHeight = 10;
  var inverTimer = 10;
  clearTimeout(timer);
  //当鼠标移入时清除让内部ul长度减小的定时器,保证鼠标移入后
  //内部ul长度立即增加
  change();
  function change(){
    var height = parseInt(element.style.height);
    if(!height) height = 0;
    if(height < totalHeight){
      if(height + inverHeight > totalHeight){
        element.style.height = totalHeight + "px";
      }else{
        element.style.height = height + inverHeight +'px';
      }
      if(flag === 'flag1'){
        timeAdd1 = setTimeout(change,inverTimer);
        }else{
          timeAdd2 = setTimeout(change,inverTimer);
        }
    }
  }
}
untilEvent.addEvent(window,'load',getOuter);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2017-03-21

顶部缓冲下拉菜单导航特效的JS代码

复制代码 代码如下: <script type="text/javascript">            $(function() {                var d=300;                $('#navigation a').each(function(){                    $(this).stop().animate({                        'marginTop':'-80px'       

jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果

在网站建设中,特别是做商城和产品网站,通常会用到导航弹出菜单,像是jquery写的仿京东导航菜单,一个经典的左侧多级导航菜单,学会了可以任意改变布局.京东菜单已经有不少JS前端爱好者仿写过,今天蚂蚁网络重新与大家分享一款仿京东商城的商品多级分类菜单,精简版代码 先看下jquery仿京东导航效果: 前端html代码如下: 复制代码 代码如下: <ul> <li><a href="#">baidu</a></li> <div

jQuery实现的简洁下拉菜单导航效果代码

本文实例讲述了jQuery实现的简洁下拉菜单导航效果.分享给大家供大家参考.具体如下: 这里使用jQuery实现简洁下拉菜单导航效果,代码规范,兼容性方面:支持 IE6+, Firefox 1.5+, Opera 8+, Safari 3+, Chrome 0.2+.简洁明快的jquery网站菜单,请参阅代码. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-simple-down-show-menu-nav-codes/ 具体代码

JS实现快速的导航下拉菜单动画效果附源码下载

这是一个带变形动画特效的下拉导航菜单特效.该导航菜单在菜单项之间切换时,下拉菜单会快速的根据菜单内容的大小来动态变形,显示合适的下拉菜单大小,效果非常棒. 查看演示     下载源码 HTML 该导航菜单的HTML结构如下: <header class="cd-morph-dropdown"> <a href="#0" class="nav-trigger">Open Nav<span aria-hidden=&qu

js实现兼容性好的微软官网导航下拉菜单效果

本文实例讲述了js实现兼容性好的微软官网导航下拉菜单效果.分享给大家供大家参考.具体如下: 这是一款微软官网导航菜单,兼容好的下拉菜单,微软官网导航效果,在IE6下没有动画效果,顺便也把IE6的效果给加上,兼容IE6.现在微软的官方网站正在使用,我觉得非常不错. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-microsoft-web-nav-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-/

javascript仿京东导航左侧分类导航下拉菜单效果

本文实例为大家分享了类似于京东.淘宝商城左侧分类导航下拉菜单,供大家参考,具体内容如下 效果图: 实现代码: <!DOCTYPE html> <html> <head> <meta charset="gb2312"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <

JS中用三种方式实现导航菜单中的二级下拉菜单

我们在淘宝.搜狐等大型网站上都可以看到使用的一些二级下拉菜单,比如下面这张图片.那么如何实现导航菜单栏中的二级下拉菜单?下面小编给大家分享实现思路. 但是如何实现类似的图片呢?实际上,我们有至少三种方式来实现,下面,我附上代码供大家参考. 1.仅使用html和css <meta charset="UTF-8"> <title>Document</title> <style> *{margin:0;padding: 0;list-style

基于JS快速实现导航下拉菜单动画效果附源码下载

这是一个带变形动画特效的下拉导航菜单特效.该导航菜单在菜单项之间切换时,下拉菜单会快速的根据菜单内容的大小来动态变形,显示合适的下拉菜单大小,效果非常棒. 快速的导航下拉菜单动画效果如下所示: 效果演示         源码下载 HTML 该导航菜单的HTML结构如下: <header class="cd-morph-dropdown"> <a href="#0" class="nav-trigger">Open Nav&

jquery实现简单的二级导航下拉菜单效果

本文实例讲述了jquery实现简单的二级导航下拉菜单效果.分享给大家供大家参考.具体如下: jQuery代码实现的二级导航菜单效果,非常简洁,喜欢简洁风格的朋友您可以下载哦.菜单最多支持两级,CSS的配合也是挺重要的,不多说了,要代码的就直接复制吧. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-2jxl-menu-codes/ 具体代码如下: <title>jquery二级导航菜单</title> <styl

JS 实现导航菜单中的二级下拉菜单的几种方式

最近整理了, JS 实现导航菜单中的二级下拉菜单的三种方式,便于项目中应用. 如何实现导航菜单栏中的二级下拉菜单? 我们在淘宝.搜狐等大型网站上都可以看到使用的一些二级下拉菜单,比如下面这张图片. 但是如何实现类似的图片呢?实际上,我们有至少三种方式来实现,下面,我附上代码供大家参考. 1.仅使用html和css <meta charset="UTF-8"> <title>Document</title> <style> *{margin

js实现简洁大方的二级下拉菜单效果代码

本文实例讲述了js实现简洁大方的二级下拉菜单效果代码.分享给大家供大家参考.具体如下: 这是一款简洁大方的二级下拉菜单,菜单的颜色自己根据需要重新定义吧,这里仅给大家提供一种制作二级菜单的思路,整体效果看上去相当实用,下拉导航菜单也是大家比较常用的. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-simple-2level-show-down-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-/

js+css实现超简洁的二级下拉菜单效果代码

本文实例讲述了js+css实现超简洁的二级下拉菜单效果代码.分享给大家供大家参考.具体如下: 这是一个很简洁的CSS+JavaScript二级菜单,没有使用过多的修饰素材,尽量不调用外部图片,简洁大方,而且便于二级开发完善,最初是一个政府网站上的菜单. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-css-simple-2jxl-menu-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//

Bootstrap中的Dropdown下拉菜单更改为悬停(hover)触发

在使用bootstrap制作后台时用到了响应式导航条,其中dropdown组件更是用的比较多,用的多需要点击的就多,dropdown默认鼠标左键单击才展开,如果使用鼠标放上去(hover)就展开则会省去点击时间,这样能提高效率. 原本的改造思路是:给dropdown元素绑定hover事件,hover上去的时候,执行该元素的click事件--即把hover同步为click,hover即为click. 但想到与其自己来改造,不如先在网上搜索搜索看看有没有现成的插件,果不其然就搜索到了,托管在gith

jquery实现平滑的二级下拉菜单效果

本文实例讲述了jquery实现平滑的二级下拉菜单效果.分享给大家供大家参考.具体如下: 这是一款使用了jQuery实现的二级菜单特效,灰色风格,颜色自己不喜欢的就自己动动手吧,CSS代码经过了优化,水平高的自己拿出修改吧,这是一个在国外前端设计网站找到的导航菜单效果,希望大家喜欢. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-soft-2level-menu-nav-codes/ 具体代码如下: <!DOCTYPE html>

jquery实现漂亮的二级下拉菜单代码

本文实例讲述了jquery实现漂亮的二级下拉菜单代码.分享给大家供大家参考.具体如下: 这里介绍一款基于jquery实现的网站下拉菜单,黑色风格,很漂亮,本菜单需要点击主菜单后的小三角符号才下拉出二级菜单,并不是有些菜单,是鼠标移上主菜单的时候就滑过,至于哪一种,就看个人的喜好了 先来看看运行效果: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-bg-2-level-down-show-menu-codes/ 具体代码如下: <!DOCTYPE ht

jQuery实现的精美平滑二级下拉菜单效果代码

本文实例讲述了jQuery实现的精美平滑二级下拉菜单效果.分享给大家供大家参考,具体如下: 这是一款jQurey实现的向下二级导航菜单效果.效果非常不错,由上到下平滑延伸,给人的感觉协调唯美!js与html代码结构简单明了,便于使用与修改! 运行效果截图如下: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xh

jquery实现鼠标滑过显示二级下拉菜单效果

本文实例讲述了jquery实现鼠标滑过显示二级下拉菜单效果.分享给大家供大家参考.具体如下: 这是一款jquery实现的下拉菜单,当鼠标移在主菜单上的时候,向下滑出二级子菜单,采用UL LI结构,便于修改完善,我觉得是很实用的菜单,希望大家平时能用得上. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-mouse-over-show-menu-codes/ 具体代码如下: <!DOCTYPE html> <head>

jQuery实现灰蓝风格标准二级下拉菜单效果代码

本文实例讲述了jQuery实现灰蓝风格标准二级下拉菜单效果代码.分享给大家供大家参考.具体如下: 这是一款基于jQuery实现的标准型二级菜单,是漂亮的灰-蓝风格下拉级联菜单,代码经过了完美修正,目前兼容性已经很不错了,甚至不用修改,拷贝代码你就可以用了. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-blue-color-style-nav-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC &quo