揭秘CSS(第 1 版)
6.3.6 下拉导航
阅读(

概述

CSS选择器

字体和文本

盒模型

元素的定位

链接和导航

链接的样式

列表的样式

创建导航

主导航

手风琴导航

垂直导航

分页导航

面包屑导航

下拉导航

下拉菜单仍然是Web上流行的界面元素,虽然有一些纯Javascript 解决方案,但在禁用Javascript 的浏览器下,它却无能为力。因此,纯CSS的下拉菜单才是最好的选择。

这种技术及其简单,只需把子导航嵌套在无序列表中,并让子导航默认隐藏,然后当鼠标悬停或点击父列表时,再让它显示出来。

本节,在上一节主导航的基础上,添加子导航,来演示下拉导航的制作方法。主导航的样式保持不变,这里只介绍子导航的样式。首先,创建多级导航列表。

<ul class = "mainnav">
   <li><a href="#">文件</a>
       <ul class = "submenu">
       <li><a href="#">新建</a></li>
       <li><a href="#">打开</a></li>
       <li><a href="#">保存</a></li>
       </ul>
   </li>
   <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>
</ul>

与主导航相同,首先需要重置列表的默认样式,将外边距、内边距设置为 0,并去掉默认的项目符号。

.submenu {
   margin: 0;
   padding: 0;
   list-style: none;
}

由于在主导航中让所有 li 向左浮动,子导航中,需要子导航垂直显示。因此,需要让子导航中的 li 样式不再浮动。

.submenu li {
   float: none;
}

接下来,把子导航中链接的 display 属性设置为 block,以便在链接区域的任何位置都能激活链接。再设置链接的宽度、默认属性、以及鼠标悬停时的属性。

.submenu li a {
   color: #000;
   padding: 4px 0;
   font-size: 13px;
   display: block;
}
.submenu li a:hover {
   color: #fff;
   background: #4899E0;
}

子导航样式设置完成后,就可以通过 display: none 把子导航隐藏起来。当鼠标悬停在主导航的 li 上时,再通过 display: block 把子导航显示出来。

.mainnav li:hover .submenu {
   display: block;
}

由于子导航在普通流中定位,会占用父元素的空间。因此,如果子导航使用绝对定位,它就会脱离文档流,不再占用父元素的空间。这样的话,在子导航被显示出来时,父元素的高度就不会被撑开。

.submenu {
   padding: 0;
   list-style: none;
   display: none;
   position: absolute;
}

至此,纯CSS的下拉菜单就制作完成了,快来看看效果吧!

二级下拉导航
图6-16 二级下拉导航

这里只是演示了二级下拉菜单的制作过程,当然,也可以制作三级、四级,甚至更多级的下拉菜单。假如在二级菜单下,又添加三级下拉菜单:

<li><a href="#">查看</a>
   <ul class = "submenu">
   <li><a href="#">工具栏</a></li>
   <li><a href="#">转到</a>
       <ul class = "drop">
       <li><a href="#">后退</a></li>
       <li><a href="#">前进</a></li>
       </ul>
   </li>
   </ul>
</li>

无论多少级菜单,其本质完全相同,制作方法也没什么差别。都是让子菜单使用绝对定位,并默认隐藏起来,当鼠标悬停在上一级菜单上时,再自动将下级菜单显示出来。

.drop {
   left: 100%;
   display: none;
   list-style: none;
   background: #ccc;
   position: absolute;
}
.submenu li:hover .drop {
   display: block;
   margin-top: -27px;
}

添加三级菜单后的运行结果如图 6‑17 所示:

三级下拉导航
图6-17 三级下拉导航

上述这种技术制作出来的下拉导航,可以适用于大多数现代浏览器,但在IE7及以下版本中,存在易用性问题。

一个问题是,在IE7及以下版本中,多级列表中,下级列表的位置会发生偏移,导致二级和三级菜单的位置不正确。可以通过 CSS hack 对二级和三级列表进行修正,偏移的距离,要根据实际情况确定,而IE6与IE7偏移的距离可能会不同,需要单独修正。

.mainnav li:hover .submenu {
   display: block;
   *margin-top: 38px;
   *margin-left: -88px;
   _margin-top: 40px;
   _margin-left: -84px;
}
.submenu li:hover .drop {
   display: block;
   margin-top: -27px;
   *margin-top: 0;
   *margin-left: 0;
}

另一个问题是,在IE6中,当鼠标悬停在主导航的 li 上时,子导航却不能正常显示出来,因为IE6不支持在非锚元素上使用 :hover 伪类选择器。因此,需要使用 Javascript 或 .htc 文件来启用这个功能。

.htc 文件实际上就是脚本文件,只有IE能够识别它。 在网上下载csshover.htc 文件,把它放在网站的某个位置,然后,在 body 选择器中通过 behavior 属性指向该文件即可。

body {
   behavior: url("http://XXX/csshover.htc");
}

还有一个问题,就是上述每个 li 后面有一个回车,在IE6中,当 li 中的内容是一个 a 元素,并且 a 元素或 a 元素的子元素(如,<img/>元素)设置了display: block 时,浏览器将不会忽略 li 之间的空白字符,表现为在 li 之间有一个额外的空行。

这个问题有两种解决办法:一种方法是避免为 li 中的 a 元素或 a 元素的子元素设置display: block,或去掉 li 后面的回车;另一种方法是就是让 a 元素或 a 元素的子元素触发布局,常用的就是通过 _zoom: 1 触发布局,因为它没有副作用。

我们使用第一种方法,让二级、三级等列表中的链接使用display: inline-block,这样既不影响链接的点击区域,又可以消除 li 之间的额外空行,可谓一举两得。

.submenu li a {
   color: #000;
   font-size: 13px;
   padding: 4px 0;
   display: inline-block;
}

至此,我们的三级下拉导航才算真正制作完成,它在所有的浏览器下都表现正常,并且表现完全一致。

关于作者

歪脖先生,十五年以上软件开发经验,酷爱Web开发,精通 HTML、CSS、JavaScript、jQuery、JSON、Python、Less、Bootstrap等,著有《HTML宝典》、《揭秘CSS》、《Less简明教程》、《JSON教程》、《Bootstrap2用户指南》、《Bootstrap3实用教程》,并全部在 GitHub 上开源。

如果本教程对您帮助很大,请随意打赏。您的支持,将鼓励我写出更好的教程!

← 键盘方向键翻页 →
返回顶部 手机访问 关注微信 返回底部

扫码访问歪脖网

随时随地,想看就看

关注歪脖网微信

分享 web 知识、交流 web 经验