水平导航栏可以有两种实现方式: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-里面有一些笔者模仿制作的网页。笔者能力有限,如有纰漏还望指正。