3

菜单由一组链接组成。用 HTML 中的列表元素(ulol)来分组链接不仅符合逻辑,而且即使没有额外的 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,而不要应用给 ulli

  • 使用 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;
}

效果图:

图片描述


源码下载


参考资料


omgdog
2.4k 声望332 粉丝

科科。