65.9K
CodeProject 正在变化。 阅读更多。
Home

支持无限级水平和垂直菜单的纯 CSS 菜单

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2016 年 1 月 19 日

CPOL

5分钟阅读

viewsIcon

43353

downloadIcon

444

使用提供的带有类名 div 的 CSS 构建一个外观整洁的基于 Web 的菜单,该菜单不需要 JavaScript,并且支持无限级别的水平和垂直菜单。

引言

是的 - 又一个“纯 CSS 菜单”解决方案。不过,此版本有一些不错的特性

  • 支持所有菜单和子菜单的水平和垂直方向
  • 支持从菜单到子菜单移动时方向的所有组合(也就是说,无论父菜单是水平还是垂直方向,都可以很好地支持水平和垂直子菜单)
  • 支持无限级别的子菜单,无需特殊类(例如,每个级别的“level-1-menu”、“level-2-menu”)
  • 使用带类名的 DIV 而不是 UL/LI 或表格 - 这使结构保持简单
  • 我已经对 CSS 进行了全面记录,使其易于自定义,并且用于构建菜单的 HTML 结构非常简单。

这是使用此 CSS/HTML 构建的菜单的示例,显示了多个级别和方向

menu

在上述示例中未显示的示例代码中,还包含多个连接的水平菜单级别。要访问它,请导航至 [项目 1 -- 子项目 1 -- 子子项目 3],您将在那里找到它们。

Using the Code

使用此代码有两个主要步骤。第一步很简单 - 只需将 CSS 复制到 CSS 文件中并链接它,或者将其包含在 HTML 文件中的 <style type='text/css'>...</style> 标签内。

这是生成上述示例的CSS... CSS 的完全注释版本包含在 项目演示文件中,因此我只会做一些注释。

首先,以下大多数 CSS 都相对重要,但其中一些可以更改。我假设读者具有一般性地知道什么可以安全更改,什么不可以更改的知识。如果您决定自定义,只需进行少量更改,然后测试这些更改以确保没有重大问题。一些比较棘手的内容 - background-color 应在 div.menu 上指定,即使您希望菜单是透明的;否则,将出现一个讨厌的 Internet Explorer 错误,菜单有时会消失,即使鼠标仍在悬停在其上方。您可以使用 rgba(0,0,0,0) 来获得透明菜单,这似乎可以消除 Internet Explorer 错误,但“transparent”和根本不设置 background-color 似乎都会出现此错误,尽管它是间歇性的。Internet Explorer 的另一个小问题是子菜单定位有点偏差。如果您调整子菜单的边距设置,然后在 Internet Explorer 和其他浏览器中进行测试,您应该会看到我所指的内容,特别是如果您在子菜单周围放置边框。

div.menu {
    display: none;
    color: white;
    background-color: rgba(0,0,0,1);
}
div.top {
    display: inline-block;
}
div.top.hmb > div.item {
    display: inline-block;
}
div.menu > div.item {
    white-space: nowrap;
    cursor: pointer;
    padding: 5px 10px;
    margin: 0;
    border-top: 4px solid transparent;
}
div.menu > div.item:hover {
    background-color: #262626;
    border-top: 4px solid #009ac7;
}

/*  Adjust the exact display and positions of sub-menus  */
div.hmb > div.item:hover > div.vmb {      /* Horizontal menu w/ vertical sub-menu */
    position: absolute;
    display: block;
    margin-top: 5px;
    margin-left: -10px;
}

div.hmb > div.item:hover > div.hmb {      /* Horizontal menu w/ horizontal sub-menu */
    position: absolute;
    display: block;
    margin-top: 5px;
}

div.vmb > div.item:hover > div.vmb {      /* Vertical menu w/ vertical sub-menu */
    position: absolute;
    display: inline-block;
    margin-left: 6px;
}
    
div.vmb > div.item:hover > div.hmb {      /* Vertical menu w/ horizontal sub-menu */
    position: absolute;
    display: inline-block;
    margin-left: 6px;
}

div.item:hover > div.hmb > div.item {     /* Horizontal hovered menu items */
    display: inline-block;
}

div.menu > div.item > a {
    color: inherit;
    text-decoration: none;
}

使这些菜单工作原理的关键是上面描述子菜单继承的 CSS 块。 对于水平和垂直菜单之间过渡的四种组合中的每一种,positiondisplay 这两个属性控制子菜单的显示方式。 在所有情况下,我们都指定“position: absolute”,以便子菜单从 HTML 流中移除,从而允许子菜单显示在我们想要的确切位置。该 CSS 属性设置相当普通,但 display 属性更有趣。对于水平菜单,我们总是希望子菜单显示在菜单项下方;对于垂直菜单,我们总是希望子菜单显示在菜单项右侧。由于包含的 DIV 出现在菜单项文本之后(参见下面的 HTML),我们为水平菜单项指定“display: block”以强制子菜单出现在菜单项文本下方。类似地,对于垂直菜单项,我们指定“display: inline-block”以允许 div 出现在菜单项文本旁边。在所有情况下,都需要对确切位置进行一些微调。通常,这是通过使用 top/left CSS 属性和 position: relative 来实现的。但是,在这种情况下我们不能这样做,因为如前所述,我们需要 position: absolute 来确保子菜单不会影响页面上其余 HTML 的流动,因此设置 top/left 会将 DIV 移动到屏幕上的确切位置。 相反,我们通过设置子菜单 DIVmargin CSS 属性来完成位置调整。 请注意,负边距(许多人觉得奇怪的概念)可以用于将 DIV 向相反方向移动 - 即,正的 margin-top 会将 DIV 向下移动,但负的 margin-top 会将 DIV 向上移动。 

第二步是使用 DIV 和上述 CSS 中的一些类来构建您的 HTML 菜单。类是

  • menu - 应将其应用于包含菜单项的任何 div
  • hmb / vmb - 任何 <DIV class='menu'> 都应包含 hmb(水平菜单栏)或 vmb(垂直菜单栏)。只选择一个。
  • top - 这个类只是强制菜单在鼠标未悬停时显示。顾名思义,这通常只在菜单的“顶部”级别使用
  • item - 将此类应用于包含单个菜单项的 DIVs,无论该项是否包含子菜单

有许多方法可以与菜单进行交互。一些可能性是使用 <a> 标签,通过 DIVs 上的 onclick JavaScript 事件,或通过 JavaScript/jQuery 事件订阅。

这是生成示例图像的示例 HTML

<div class='menu top hmb'>
    <div class='item'>
        Item 1
        <div class='menu vmb'>
            <div class='item'>
                Sub Item 1
                <div class='menu hmb'>
                    <div class='item'>
                        Sub Sub Item 1
                        <div class='menu vmb'>
                            <div class='item'>
                                Level 4 - 1
                                <div class='menu vmb'>
                                    <div class='item'>
                                        Level 5 - 1
                                        <div class='menu vmb'>
                                            <div class='item'>Level 6 - 1</div>
                                            <div class='item'>
                                                Level 6 - 2
                                                <div class='menu hmb'>
                                                    <div class='item'>Level 9 - 1</div>
                                                    <div class='item'>Level 9 - 2</div>
                                                    <div class='item'>Level 9 - 3</div>
                                                </div>
                                            </div>
                                            <div class='item'>Level 6 - 3</div>
                                        </div>
                                    </div>
                                    <div class='item'>Level 5 - 2</div>
                                    <div class='item'>Level 5 - 2</div>
                                </div>
                            </div>
                            <div class='item'>Level 4 - 2</div>
                            <div class='item'>Level 4 - 3</div>
                        </div>
                    </div>
                    <div class='item'>Sub Sub Item 2</div>
                    <div class='item'>
                        Sub Sub Item 3
                        <div class='menu hmb'>
                            <div class='item'>Level 7 - 1</div>
                            <div class='item'>
                                Level 7 - 2
                                <div class='menu hmb'>
                                    <div class='item'>Level 8 - 1</div>
                                    <div class='item'>Level 8 - 2</div>
                                    <div class='item'>Level 8 - 3</div>
                                </div>
                            </div>
                            <div class='item'>Level 7 - 3</div>
                        </div>
                    </div>
                </div>
            </div>
            <div class='item'>Sub Item 2</div>
        </div>
    </div>
    <div class='item'>
        <a href='#'>Item 2</a>
    </div>
    <div class='item'>
        Item 3
    </div>
</div>

注意:尽管此 CSS/HTML 菜单确实支持“无限级别”,但我**不**建议过度使用。具有超过 2-3 个级别的菜单结构通常不被认为是良好的设计。

历史

  • 2016-01-19 - 初始发布
© . All rights reserved.