菜单由一组链接组成。用 HTML 中的列表元素(
ul
或ol
)来分组链接不仅符合逻辑,而且即使没有额外的 CSS 也能适当显示链接的层次。默认情况下,由于列表(li
)是块级元素,因此它们会上下堆叠。
1.纵向菜单
html 标记:
<nav class="list">
<ul>
<li><a href="#">apple</a></li>
<li><a href="#">banana</a></li>
<li><a href="#">cat</a></li>
<li><a href="#">dog</a></li>
</ul>
</nav>
css 规则:
*{
margin: 0;
padding: 0;
}
nav{
margin: 50px;width:150px;
}
.list ul{
border: 1px solid #6a6b6c;
border-radius: 3px;
padding:5px 10px 3px;
}
.list li{
list-style: none;
/*padding: 3px 10px;*/
}
.list li + li a{ /* 注意这里! */
border-top: 1px solid #6a6b6c;
}
.list a{
display: block; /* 这里! */
padding:3px 10px; /* 还有这里! */
text-decoration: none;
padding: 3px 10px;
}
.list a:hover{
color:#069;
}
效果图:
说明:
相对于
div
,使用 HTML5 新增的nav
元素作为导航菜单的容器在语义上更恰当。使用 非首位子元素 选择符。
li + li
选择符意思为:任何跟在li
之后的li
。在上面表示给除第一个li
之外的所有列表项上方加一条边框。这种选择符就称为 非首位子元素选择符。它在选择列表时非常使用。其它实现该效果的方法:
/*给所有 li 上方添加一条边框*/
li {
border-top:1px solid #f00;
}
/*去掉第一个 li 上方的边框*/
li:first-child {
border-top:none;
}
- 让列表可点击。为了不让只有文本可以点击(因为链接
a
是行内元素,它会收缩并包住其中的文本。),为了提高用户体验,我们需要 让列表项所在的整行都能点击。方法就是首先把内边距从li
元素转移到链接内部,然后让链接完全填满整个列表项。如下所示:
.list a{
display:block;
padding:3px 10px;
}
然后就是把选择符 li + li
变成li + li a
,就可以把上边框添加到列表后面的列表项所包含的链接元素上。
2.横向菜单
html 标记:
<nav class="list">
<ul>
<li><a href="#">Shirts</a></li>
<li><a href="#">Pants</a></li>
<li><a href="#">Dresses</a></li>
<li><a href="#">Shoes</a></li>
<li><a href="#">Accessories</a></li>
</ul>
</nav>
CSS 规则:
.list ul{
overflow: hidden; /*强制 ul 包围浮动的 li 元素*/
}
.list li{
float: left; /*让 li 元素水平排列*/
list-style: none;
}
.list a{
display: block; /*让链接变成块级元素*/
padding: 0 16px;
text-decoration: none;
color:#999;
}
.list li + li a{
border-left:1px solid #aaa;
}
.list a:hover{
color:#555;
}
效果图:
说明:
浮动可以让
li
元素从垂直变成水平。display:block
让链接从收缩变成扩张,从而整个li
元素都变成了可点击。选择符
li + li a
为除第一个链接之外的每个链接左侧都加了一条竖线,作为视觉分割线。
3.下拉菜单
相对于前面两种菜单,这个实现起来有点复杂。
下面,我们分几个步骤来实现。
第1步-实现顶级菜单
HTMl 标记:
<nav class="multi_drop_menu verticle">
<ul><!-- 一级开始 -->
<li><a href="#">Power</a></li>
<li><a href="#">Money</a></li>
<li><a href="#">Love</a></li>
<li><a href="#">Fame</a>
<ul><!-- 二级开始 -->
<li><a href="#">Sports Star</a></li>
<li><a href="#">Movie Star</a></li>
<li><a href="#">Rock Star</a>
<ul><!-- 三级开始 -->
<li><a href="#">Bruce Springsteen</a></li>
<li><a href="#">Bono</a></li>
<li><a href="#">Mick Jagger</a></li>
<li><a href="#">Bob Dylan</a></li> </ul><!-- 三级结束 -->
</li>
</ul><!-- 二级结束 -->
</li>
</ul><!-- 一级结束 -->
</nav>
CSS 规则:
/* ***************添加视觉样式************ */
.multi_drop_menu {
font: 1em helvetica, arial, sans-serif;
}
.multi_drop_menu a{
/*让链接充满列表项*/
display: block;
/*文本颜色*/
color:#555;
/*背景颜色*/
background-color:#eee;
/*链接的内边距*/
padding: .2em 1em;
/*分隔线宽度*/
border-width:3px;
/*可以有颜色,也可以透明*/
border-color: transparent;
}
/*显示选择路径*/
.multi_drop_menu li:hover > a{ /*注意这里的选择符,使用了冒泡机制,后面会用到*/
/*悬停时的文本颜色*/
color:#fff;
/*悬停时的背景颜色*/
background-color: #aaa;
}
/* ***************添加功能样式************* */
.multi_drop_menu *{
margin:0;
padding:0;
}
/*强制ul包围li*/
.multi_drop_menu ul{
float: left;
}
.multi_drop_menu li{
/*水平排列菜单项*/
float: left;
/*去掉默认的项目符合*/
list-style: none;
/*为子菜单提供定位上下文*/
position: relative;
}
.multi_drop_menu li a{
/*让链接填充列表项*/
display: block;
/*给每个链接添加一个右边框*/
border-right-style: solid;
/*背景只出现在内边距区域后面*/
background-clip: padding-box;
/*去掉链接的下划线*/
text-decoration: none;
}
效果图:
说明:
-
分离菜单的 视觉样式 和 功能样式。有利于代码维护。
视觉样式:控制字体大小、边框和文本的颜色。
功能样式:控制布局和行为。 通过 浮动 将
li
由垂直堆叠变成水平排列。为了让
ul
包围列表项,没有使用overflow:hide
,而是使用了float:left
,是因为前者会导致后来添加到下拉菜单中的子菜单无法显示——它们最终会显示在父元素ul
的外面,结果会导致 溢出(overflow) 而被 隐藏(hide)。为了提高用户体验,要让 热区(可点击区域) 最大化——所有视觉样式(内边距、背景、边框等)都应用给链接
a
,而不要应用给ul
或li
。使用
background-clip:padding-box
阻止链接的背景延伸到边框后面。接着,border-color:transparent;
让边框透明 ,在链接之间产生间隙,让后面的页面能够透过边框被看到。这样一来,不用外边距也能分隔链接,本质上是紧挨在一起,视觉上却是分开的。
第2步-实现菜单的下拉部分
CSS 规则:
/*二级菜单宽度*/
.multi_drop_menu li ul{
width: 9em;
}
.multi_drop_menu li li a{
/*去掉继承的右边框*/
border-right-style: none;
/*添加上边框*/
border-top-style: solid;
}
/* 添加的功能样式 */
.multi_drop_menu li ul {
/*临时显示二级下拉菜单*/
display:block;
/*相对于父菜单项定位*/
position:absolute;
/*左边与父菜单项对齐*/
left:0;
/*顶边与父菜单项底边对齐*/
top:100%;
}
.multi_drop_menu li li {
/*停止浮动,恢复堆叠*/
float:none;
}
.multi_drop_menu li li ul {
/*继续隐藏三级下拉菜单*/
display:none;
}
效果图:
说明:
- 通过将二级菜单的顶边位置(top)设定为
100%
(相对于其相对定位的父元素li
),其顶边会与父元素底边恰好对齐。它与父元素之间的间隙,实际上下拉菜单中第一个链接的边框。
第3步-让下拉菜单响应鼠标事件
CSS 规则:
.multi_drop_menu li ul {
/*隐藏二级下拉菜单*/
display:none;
/*相对于父菜单项定位*/
position:absolute;
/*左边与父菜单项对齐*/
left:0;
/*顶边与父菜单项底边对齐*/
top:100%;
}
.multi_drop_menu li:hover > ul {
/*父元素悬停时显示*/
display:block;
}
/*隐藏二级菜单*/
li ul {
display:none;
}
/*显示二级菜单*/
li:hover > ul {
display:block;
}
说明:
先把下一级的菜单隐藏,再在父元素鼠标悬停时把它显示出来。
:hover
触发器是设定在li
元素而非链接身上。因为我们想要显示的是li
的子元素ul
。悬停列表项与子列表之间还有一个子选择符
>
,如果没有这个选择符,当顶级菜单项处于悬停状态时,会同时显示二级和三级菜单。
第4步-调整三级菜单的位置
CSS 规则:
.multi_drop_menu li li ul {
/*相对于父菜单定位*/
position:absolute;
/*与父菜单右侧对齐*/
left:100%;
/*与父菜单项顶边对齐*/
top:0;
}
效果图:
说明:
- 由于三级菜单跟二级菜单一样垂直堆叠,因而会被二级菜单遮住,所以我们需要把三级菜单放到二级菜单右侧,让它的顶边与鼠标所在的菜单项的底边对齐。
其它-突出显示选择路径
CSS 规则:
.multi_drop_menu li:hover > a {
/*悬停时的文本颜色*/
color:#fff;
/*悬停时的背景颜色*/
background-color:#aaa
}
效果图:
其它-垂直的三级菜单
HTML 标记:
<!-- 添加一个类 vertical -->
<nav class="multi_drop_menu vertical">
CSS 规则:
/*顶级垂直菜单宽度*/
.multi_drop_menu.vertical {
width:8em;
}
.multi_drop_menu.vertical li a {
border-right-style:none;
border-top-style:solid;
}
.multi_drop_menu.vertical li li a {
border-left-style:solid;
}
.multi_drop_menu.vertical ul,.multi_drop_menu.vertical li {
/*让顶级菜单垂直显示*/
float:none;
}
.multi_drop_menu.vertical li ul {
/*子菜单左边与上一级菜单右边对齐*/
left:100%;
/*子菜单顶边与上一级菜单项顶边对齐*/
top:0;
}
效果图:
源码下载
参考资料
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。