首页 » 技术分享 » HTML二级下拉菜单常见样式以及常见问题

HTML二级下拉菜单常见样式以及常见问题

 

水平导航栏可以有两种实现方式:1、浮动;2、inline-block

  • 浮动实现的技术点有:
    1、浮动的技术原理
    2、 浮动溢出的解决(BCF原理)
    3、清除浮动的方法

  • inlind-block实现的技术点不过于把菜单项的display样式设置为inline-block即可,但是这时需要注意的是inline-block自带内间距和外间距,如果不希望这些间距影响排版的朋友,可以通过设置菜单项的{margin:0;padding:0;}得以解决。

现在介绍一下两种常见的菜单样式、实现方式和常见的问题。

  • 悬浮单列下拉

这里写图片描述

这种样式是通过鼠标悬浮显示单列菜单的情况,这种实现方式一般通过ul和li元素实现,实现步骤如下:
1、建立容器

      .top-container{
            background: #fbfbfb;
            height:30px;
            min-width: 1500px;
            border: 1px solid #e8e8e8;
            font-family: 'Tahoma','simsun' !important;
            color: #747d87;
            margin: 0;
        }
  <body style="margin:0;">
    <div class="top-container">

    </div>
  </body>

结果就是一个白色长条,就不截图了,这里需要注意就是各种浏览器对body的外边距实现不一,所以一般都要对body的样式里添加margin: 0;
2、建立导航栏容器

.top-wrapper {
    width: 1450px;
    height: 30px;
    border: 1px solid red;
    margin: auto;
}
  <body style="margin:0;">
    <div class="top-container">
         <div class="top-wrapper wrapper">
         </div>
    </div>
  </body>

结果就是居中的导航容器,其中margin:auto;用来水平居中,这个样式需要注意的是需要条件position:relative;和必须是块级元素
这里写图片描述
3、建立菜单项

  <body style="margin:0;">
        <!--导航栏一般需要一个容器,设置width:100%适应浏览器的大小变化-->
   <div  class="top-container container">
     <!--导航栏wrapper一般设置一个固定大小这样子可以通过margin:auto;实现导航栏水平居中
     由于顶层容器是适应浏览器变化宽度,所以可以保持水平导航栏自适应浏览器窗口宽度保持居中-->
    <div class="top-wrapper wrapper">
      <!--这个是普通导航栏的容器,就是除了"立即登陆"和"注册新账号"-->
      <div class="nav top-left-nav">
        <!--开始实现列表-->
       <ul>
        <li  class="first-nav"><span>站长之家</span></li>
        <li  class="first-nav"><span>站长论坛</span></li>
        <li class="dropdown first-nav"><span>站长工具<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">ALEXA排名查询</a></li>
          <li><a href="#">百度权重查询</a></li>
          <li><a href="#">SEO概况查询</a></li>
          <li><a href="#">友情链接查询</a></li>
          <li><a href="#">Google PR查询</a></li>
          <li><a href="#">Whois信息查询</a></li>
          <li><a href="#">域名备案查询</a></li>
         </ul> </li>
        <li class="dropdown  first-nav"><span>站长素材<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">字体下载</a></li>
          <li><a href="#">高清壁纸</a></li>
          <li><a href="#">简历模板</a></li>
          <li><a href="#">高清图片</a></li>
          <li><a href="#">矢量素材</a></li>
          <li><a href="#">PSD素材</a></li>
          <li><a href="#">PPT模板</a></li>
         </ul> </li>
        <li class="dropdown  first-nav"><span>网站排行<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">行业网站排名</a></li>
          <li><a href="#">地区网站排名</a></li>
         </ul> </li>
        <li  class="first-nav"><span>手机版</span>
         <ul class="sec-nav">
          <li><a href="#"><span><img src="2.jpg" /></span></a></li>
         </ul> </li>
        <li  class="first-nav"><span>工具旧版</span></li>
        <li class="new  first-nav"><span>SEO工具包<i class="icon icon-new"></i></span></li>
       </ul>
      </div>
       <div class="nav user-nav">
        <ul>
         <li class="first-nav"><a href="#">立即登录</a></li>
         <li class="first-nav"><a href="#">立即注册</a></li>
        </ul>
      </div>
    </div>
   </div>
.top-left-nav,.user-nav {
    display: inline-block;
    border: 1px solid red;
    height: 30px;
}

.nav {
    display: inline-block;
    margin: 0 auto;
    padding: 0;
    position: relative;
}

.nav:after {
    content: "";
    display: block;
    clear: both;
    visibility: hidden;
    width: 0px;
    height: 0px;
}

.nav ul ,.nav li {
    display: block;
    position: relative;
    margin: 0px;
    padding: 0px;
}

.nav a {
    text-decoration: none;
    display: block;
    text-align: center;
    margin: 0 auto;
}

.first-nav {
    text-align: center;
    display: block;
    margin: 0 auto;
}

.sec-nav {
    position: relative;
    display: block;
    text-align: center;
}

.top-left-nav .first-nav{
  /*显示具体布局*/
    width:130px;
    line-height:30px;
}

这时的结果是这样的:
这里写图片描述
很明显ul列表是垂直排列了,这时就是浮动作用体现的时候了,修改first-nav的样式

        .first-nav{
                float: left;
                text-align:center;
                display: block;
                margin:0 auto;
        }

导航栏的雏形渐渐出现,但是拖在一级菜单项的蓝字怎么办呢?
这里写图片描述
添加样式:

.top-left-nav  .sec-nav{
    margin:0px;
    display: none;
    padding:5px 3px;
    width: 130px;
    z-index:2;
}

结果很满意,其中diplay:none;就是实现隐藏效果的关键一环,说到隐藏,为何不用visibility:hidden;呢?其实使用display:none;时,元素是不占据任何空间的,相当于就是删除了这个元素;而visibility:hidden;元素依旧占据空间,只是变成不可见的状态,也无法接受事件,例如不能点击、不能鼠标悬浮等。隐藏是实现了,但是怎么让它重新出现,实现下拉效果呢?

这里写图片描述
既然我们设置display:none把元素隐藏了了,那就把display样式设置可见的样式就行了,添加样式

.top-left-nav .first-nav:hover .sec-nav {
    display: block;
    border: 1px solid #e8e8e8;
}

下拉样式已经实现,结果很不错,这里用到的是hover悬浮伪类,当鼠标悬浮元素之上时应用样式,刚才我们是利用display:none;隐藏元素的,所以可以直接通过display:block;使元素重新恢复。
这里写图片描述
代码到了这里,基本已经实现完成,全部代码如下:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>测试</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>
        .top-container{
            background: #fbfbfb;
            height:30px;
            min-width: 1500px;
            border: 1px solid #e8e8e8;
            font-family: 'Tahoma','simsun' !important;
            color: #747d87;
            margin: 0;
            z-index:2;
        }
        .top-wrapper{
            width:1450px;
            height: 30px;
            border: 1px solid red;
            margin: auto;
        }

        .top-left-nav,.user-nav{
            display: inline-block;
            border: 1px solid red;
            height: 30px;
        }

        .nav{
            display: inline-block;
            margin:0 auto;
            padding:0;
            position: relative;
        }

        .nav:after{
            content:"";
            display:block;
            clear:both;
            visibility: hidden;
            width:0px;
            height:0px;
        }

        .nav ul ,.nav li{
            display: block;
            position: relative;
            margin:0px;
            padding:0px;
        }

        .nav a{
            text-decoration: none;
            display: block;
            text-align: center;
            margin:0 auto;
        }

        .first-nav{
                float: left;
                text-align:center;
                display: block;
                margin:0 auto;
        }

        .sec-nav{
                position: relative;
                display: block;
                text-align:center;
        }
        .top-left-nav .first-nav{
          /*显示具体布局*/
            width:130px;
            line-height:30px;
        }
        .top-left-nav  .sec-nav{
            margin:0px;
            display: none;
            padding:5px 3px;
            width: 130px;
        }
        .top-left-nav .first-nav:hover .sec-nav{
            display: block;
            border: 1px solid #e8e8e8;
        }
    </style>
  </head>
  <body style="margin:0;">
        <!--导航栏一般需要一个容器,设置width:100%适应浏览器的大小变化-->
   <div  class="top-container container">
     <!--导航栏wrapper一般设置一个固定大小这样子可以通过margin:auto;实现导航栏水平居中
     由于顶层容器是适应浏览器变化宽度,所以可以保持水平导航栏自适应浏览器窗口宽度保持居中-->
    <div class="top-wrapper wrapper">
      <!--这个是普通导航栏的容器,就是除了"立即登陆"和"注册新账号"-->
      <div class="nav top-left-nav">
        <!--开始实现列表-->
       <ul>
        <li  class="first-nav"><span>站长之家</span></li>
        <li  class="first-nav"><span>站长论坛</span></li>
        <li class="dropdown first-nav"><span>站长工具<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">ALEXA排名查询</a></li>
          <li><a href="#">百度权重查询</a></li>
          <li><a href="#">SEO概况查询</a></li>
          <li><a href="#">友情链接查询</a></li>
          <li><a href="#">Google PR查询</a></li>
          <li><a href="#">Whois信息查询</a></li>
          <li><a href="#">域名备案查询</a></li>
         </ul> </li>
        <li class="dropdown  first-nav"><span>站长素材<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">字体下载</a></li>
          <li><a href="#">高清壁纸</a></li>
          <li><a href="#">简历模板</a></li>
          <li><a href="#">高清图片</a></li>
          <li><a href="#">矢量素材</a></li>
          <li><a href="#">PSD素材</a></li>
          <li><a href="#">PPT模板</a></li>
         </ul> </li>
        <li class="dropdown  first-nav"><span>网站排行<i class="icon icon-arrow"></i></span>
         <ul class="sec-nav">
          <li><a href="#">行业网站排名</a></li>
          <li><a href="#">地区网站排名</a></li>
         </ul> </li>
        <li  class="first-nav"><span>手机版</span>
         <ul class="sec-nav">
          <li><a href="#"><span><img src="2.jpg" /></span></a></li>
         </ul> </li>
        <li  class="first-nav"><span>工具旧版</span></li>
        <li class="new  first-nav"><span>SEO工具包<i class="icon icon-new"></i></span></li>
       </ul>
      </div>
       <div class="nav user-nav">
        <ul>
         <li class="first-nav"><a href="#">立即登录</a></li>
         <li class="first-nav"><a href="#">立即注册</a></li>
        </ul>
      </div>
    </div>
   </div>
  </body>
</html>
  • 悬浮全下拉
    这里写图片描述
    这种样式跟上一种样式不同的地方在于,悬浮的时候全部二级菜单都会下拉,在悬浮的在菜单项会出现深色强调样式,这个需要js实现。这种一般利用dt和dd实现,因为是成块出现的。
  <div class="nav-bar-wrapper">
    <div class="nav-bar-bg">
      <div class="nav-bar-bg-top">
        <div class="nav-bar-container">
          <dl id="dl1"  class="w102" onmouseover="setOn(1)" onmouseout="clearOn(6)">
            <dt>首页</dt>
            <dd>
              <a>历史上的今天</a>
              <a>百科冷知识</a>
              <a>图解百科</a>
            </dd>
          </dl>
          <dl id="dl2"  class="w104" onmouseover="setOn(2)" onmouseout="clearOn(6)">
            <dt>分类</dt>
            <dd class="cat">
              <a>艺术</a>
              <a>科学</a>
              <a>自然</a>
              <a>文化</a>
              <a>地理</a>
              <a>生活</a>
              <a>社会</a>
              <a>人物</a>
              <a>经济</a>
              <a>体育</a>
              <a>历史</a>
            </dd>
          </dl>
          <dl  id="dl3"  class="w138" onmouseover="setOn(3)"  onmouseout="clearOn(6)">
            <dt>特色百科</dt>
            <dd>
              <a>数字博物馆</a>
              <a>非遗百科</a>
              <a>多肉百科</a>
              <a>恐龙百科</a>
              <a>城市百科</a>
              <a>二战百科</a>
            </dd>
          </dl>
          <dl  id="dl4"  class="w102" onmouseover="setOn(4)"  onmouseout="clearOn(6)">
            <dt>用户</dt>
            <dd>
              <a>蝌蚪团</a>
              <a>燃梦计划</a>
              <a>百科任务</a>
              <a>百科商城</a>
            </dd>
          </dl>
          <dl  id="dl5" class="w138" onmouseover="setOn(5)" onmouseout="clearOn(6)">
            <dt>权威合作</dt>
            <dd>
              <a>合作模式</a>
              <a>常见问题</a>
              <a>联系方式</a>
            </dd>
          </dl>
          <dl  id="dl6" class="w138" onmouseover="setOn(6)" onmouseout="clearOn(6)">
            <dt>手机百科</dt>
            <dd><a>网页版</a></dd>
          </dl>
          <div class="user-center"><a><i class="icon icon-user"></i>个人中心</a></div>
          <div class="nav-separator">
          </div>
          <div class="clearfix"></div>
        </div>
      </div>
    </div>
  </div>

观察html代码前4层元素,我们发现多了两个:nav-bar-bg,nav-bar-bg-top,这两层是实现下拉背景蓝色块的。我们来看看这两个新添加的元素的作用,先去除nav-bar-bg-top元素,结果如下:
这里写图片描述

重新加上该元素,发现nav-bar-bg-top这个元素是实现遮挡nav-bar-bg元素的效果,从而实现导航栏一级菜单的蓝色背景。
这里写图片描述
上面提到这个样式悬浮下拉全部二级菜单项,并为其添加强调色的,这个实现方式需要借助js通过注册onmouseover鼠标悬浮事件实现。从html代码中我们可以看到,我们使用的是setOn函数,现在我们给出他的实现:

 function setOn(num){
  var e=document.getElementById("dl"+num);
  if (haveClass(e,"nav-on")){
    return;
  }
  for(var id = 1;id<=6;id++){
      e=document.getElementById("dl"+id);
      var c=e.children[0];
      if(id==num){
        e.className+=" nav-on";
        c.className="dt-on";
      }else{
        releaseOn(e,"nav-on");
        releaseOn(e.children[0],"dt-on")
      }
  }
  document.getElementsByClassName("nav-bar-wrapper")[0].style.overflow="visible";
}

function releaseOn(e,flag){
  var all=e.className.split(/\s+/);
  e.className="";
  for (var i in all){
    if (all[i]!=flag){
      e.className+=all[i]+" ";
    }
  }
}

function clearOn(num){
  for(var id = 1;id<=num;id++){
    var e=document.getElementById("dl"+id);
    releaseOn(e,"nav-on");
    releaseOn(e.children[0],"dt-on");
  }
  document.getElementsByClassName("nav-bar-wrapper")[0].style.overflow="hidden";
}

function haveClass(e,name){
  var all=e.className.split(' ');
  for (var c in all){
    if (all[c]==name){
      return true;
    }
  }
  return false;
}

从js代码中可以看出,主要对id为dl前缀的的元素进行操作,从html代码中可以看出,这些元素分别代表一个菜单,出现的两个类名”nav-on”、”dt-on”显然就是控制菜单强调色样式的,我们分析涉及这两个类选择器的css代码:

.nav-bar-wrapper dl dd{
  border-left: 1px solid #3a6fa2;
  margin: 0px auto;
  padding: 0px;
  height: 0px;
  display: none;
  transition:height 3s;
}
.nav-bar-wrapper .nav-bar-container:hover dd{
  display: block;
  height: 200px;
}
dl.nav-on dd{
  background: #19508b;
}

nav-on是对二级菜单项元素dd的操作,分析可知实现强调色就是通过添加类.nav-on从而使第三个样式dl.nav-on dd选择器成立。

.nav-bar-wrapper dl dt{
  font-size: 16px;
  color: #fff;
  display: block;
  height: 43px;
  line-height: 43px;
  text-align: center;
}

.dt-on{
  background: #338ce6;
}

顾名思义,dt-on是用来操作dt也就是一级菜单项的样式。我们分析js代码时会发现最后面还有一句代码

  document.getElementsByClassName("nav-bar-wrapper")[0].style.overflow="visible";

overflow样式是用来控制溢出部分的,overflow:visible;就是说明溢出部分可见,这句代码的作用为何呢?我们可以想到新添加的两个元素,其中nav-bar-bg,我们分析其CSS代码:

.nav-bar-wrapper{
  width:100%;
  position:relative;
  height: 43px;
  overflow: hidden;
  z-index: 2;
}
.nav-bar-bg{
  width:100%;
  height:245px;
  /***解决挤压问题**/
  position:absolute;
  background: rgb(46,97,158,.95);
}

其中height:245px;是远大于nav-bar-wrapper容器的43px的,而且开始设置overflow:hidden;显然就是影藏nav-bar-bg的溢出部分,当设置overflow:visible;时,溢出部分变成可见,就可以形成下拉背景块的效果
这里写图片描述

  • 制作导航栏的常见问题
    1、浮动溢出问题:由于水平导航栏涉及浮动,所以往往会与浮动溢出相关联,这就涉及到解决浮动溢出的问题,这方面参见我的另一篇文章
    2、下拉菜单被页面其他内容遮盖的问题:需要在顶层同级父元素设置position:relative;以及z-index,举个例子
<div class="first">
    <div class="first-content">
            ...
    </div>
    ...
</div>
<div class="sec">
    <div class="sec-content">
            ...
    </div>
    ...
</div>

如果first-content的内容被sec的内容遮盖,错误的做法

.first-content{
    position:relative;
    z-index:2;
}

.sec{
    position:relative;
    z-index:1;
}

其中first-content和.sec不是同级的元素,所以z-index无法起到作用,所以正确的做法应该是如下

.first
    position:relative;
    z-index:2;
}

.sec{
    position:relative;
    z-index:1;
}

3、下拉菜单挤压页面内容的问题
可以把下拉菜单设置position:absolute;因为此时元素不占文档流的空间,所以挤压页面内容的情况就可以避免,举个例子
这里写图片描述
这是第二种样式的导航栏,高仿百度百科的实现,这个发生了页面挤压的情况
这里写图片描述
我们可以从上图看到后面logo被挤到了右边,如果我们把nav-bar-bg的样式设置为position:absolute;,效果如下图,logo没有被挤压
这里写图片描述
也许有人会问,为什么要设置nav-bar-bg,不设置nav-bar-wrapper的position样式呢?正如前面所说,position:absolute;样式的元素不占用元素的空间,所以nav-bar-wrapper的空间会被占据,就会发生元素重叠的现象。

欢迎大家访问笔者的github:https://github.com/delin10/web-里面有一些笔者模仿制作的网页。笔者能力有限,如有纰漏还望指正。

转载自原文链接, 如需删除请联系管理员。

原文链接:HTML二级下拉菜单常见样式以及常见问题,转载请注明来源!

0