CSS全页宽水平菜单和水平子菜单

4

我正在尝试为我正在工作的网站创建一个解决方案,其中菜单和子菜单水平居中,但div却要占据整个页面宽度。

首先,这是一个示例HTML:

<div id="menu-container" class="full-width">
    <nav id="nav1" class="normal-width">
        <ul class="main-menu">
            <li id="item1">
                <a href="#">item 1</a>

                <ul class="sub-menu">
                    <li id="item11">
                        <a href="#">item 1.1</a>
                    </li>

                    <li id="item12">
                        <a href="#">item 1.2</a>
                    </li>

                    <li id="item13">
                        <a href="#">item 1.3</a>
                    </li>

                </ul>
            </li>

            <li id="item2">
                <a href="#">item 2</a>

                <ul class="sub-menu">
                    <li id="item21">
                        <a href="#">item 2.1</a>
                    </li>

                    <li id="item22">
                        <a href="#">item 2.2</a>
                    </li>
                </ul>
            </li>

            <li id="item3">
                <a href="#">item 3</a>
            </li>

        </ul>
    </nav>
</div>

这个菜单的CSS如下:
.full-width {
    width: 100%;
}

.normal-width {
    width: 1024px;
    margin: 0 auto 0 auto;
}

a {
    color: black;
    text-decoration: none;
}

.clear {
    clear: both;
}

.main-menu {
    list-style-type: none;
    margin: 0;
    padding: 0;

    position: relative;
    background-color: red;
}

.main-menu > li {
    float:left;
    margin-right:2em;
}

.sub-menu {
    list-style-type: none;
    margin: 0;
    padding: 0;

    display:none;
    background-color: orange;
}

.sub-menu li {
    float:left;
    margin-right:2em;
}

.main-menu > li.selected {
    background-color:orange;
}

.main-menu > li.selected .sub-menu {
    display:block;
    position:absolute;
    left:0;
    right:0;
}

对应的jQuery代码如下:

// Add a clear div to allow adding background color to main-menu
$(".main-menu").append("<div class='clear'></div>");

// Make the first class selected
$(".main-menu > li:first").addClass("selected");

// Switch the selected class
$(".main-menu > li").click(function() {
    $(".selected").removeClass("selected");
    $(this).addClass("selected");
});

// Disable menu links
$(".main-menu > li > a").click(function(e) {
    e.preventDefault();
});

所有的东西看起来都很好,一个适当的水平菜单被创建了。但是我现在遇到的问题是无法创建下面图片中所示的效果: enter image description here 请注意以下图片内容:
1. 黑色粗边框是网页的完整大小和宽度(即浏览器窗口的边框)。 2. 中间的细紫色线条是不可见的,它们在图片中只是为了向您展示内容所在的位置,即没有内容会超出紫色线条的最左侧或最右侧。 3. 顶级菜单项具有红色背景。 4. 子菜单将显示在橙色背景区域内。
现在,问题来了:
请注意,红色和黄色背景延伸到网页边缘,但这些页面的项目却出现在紫色线条内的内容区域中。这就是我想要实现但无法实现的效果。我无法将背景扩展到浏览器窗口的边缘(即全屏宽度)。我的解决方案是将红色和橙色背景居中。

当您将菜单的宽度设置为1024px时,您希望菜单如何延伸到页面的边缘?此外,请附上您现有的CSS或一个Fiddle。 - Danield
我刚刚修复了这个问题并添加了一个包装div。然而,这可能会影响子菜单,因此可能需要在主div之后再添加另一个div来模拟容器,但这只是一个想法。 - Greeso
你不必使用jQuery,简单的JavaScript就可以完美地工作。 - Zach Saucier
问题已经被编辑过,完全重构以反映对问题的理解。我认为这个问题最初的措辞不正确。 - Greeso
我的前公司曾经这样做。全宽度的框架包含一个单一的背景图像,页面加载时只能看到顶部部分。一旦用户点击菜单项以显示子菜单项,则始终存在子菜单;子菜单的存在自然增加了全宽度框的高度,显示更多的背景图像(在您的情况下将是两种颜色)。如果您需要灵活性,可以使用CSS渐变,并基于%高度进行严格的分割。因此,在激活菜单项后,先显示50%的红色,然后是50%的黄色。 - stommepoes
显示剩余3条评论
5个回答

4
我提供的解决方案如下。
编辑:我将我的答案复制到了帖子中,而不是链接到 jsfiddle……抱歉管理员 :/
CSS:
html, body, div, ul, li, a {margin: 0; padding: 0; border: 0;}
body {
    background-color: #000;
}
nav {
    background-color: #fff;
    position: relative;
    width: 100%;
}
ul {
    list-style: none;
    width: 100%;
}
li {
    display: inline-block;
}
a {
    display: block;
    padding: 0.25em 1em;
}
nav > ul {
    margin: 0 auto;
    width: 1024px;
}
nav ul li div { /* nested div (containing the sub nav) will be hidden by default */
    background-color: #ccc;
    width: 100%;
    position: absolute;
    left: -9999px;
}
nav ul li div ul {
    margin: 0 auto;
    width: 1024px;
}
nav > ul > li:hover > a {  /* swap ":hover" with ".active" to allow this to work as a class */
    background-color: #ccc;
}
nav > ul > li:hover > div { /* swap ":hover" with ".active" to allow this to work as a class */
    left: 0;
}

HTML:

<nav>
        <ul class="nav">
            <li>
                <a href="#">item 1</a>
                <div>
                    <ul>
                        <li>
                            <a href="#">item 1.1</a>
                        </li>

                        <li>
                            <a href="#">item 1.2</a>
                        </li>

                        <li>
                            <a href="#">item 1.3</a>
                        </li>
                    </ul>
                </div>
            </li>

            <li>
                <a href="#">item 2</a>
                <div>
                    <ul>
                        <li>
                            <a href="#">item 2.1</a>
                        </li>

                        <li>
                            <a href="#">item 2.2</a>
                        </li>
                    </ul>
                </div>
            </li>

            <li class="active">
                <a href="#">item 3</a>
                <div>
                    <ul>
                        <li>
                            <a href="#">item 3.1</a>
                        </li>

                        <li>
                            <a href="#">item 3.2</a>
                        </li>
                    </ul>
                </div>
            </li>

            <li>
                <a href="#">item 4</a>
                <div>
                    <ul>
                        <li>
                            <a href="#">item 4.1</a>
                        </li>

                        <li>
                            <a href="#">item 4.2</a>
                        </li>

                        <li>
                            <a href="#">item 4.3</a>
                        </li>
                    </ul>
                </div>
            </li>
        </ul>
    </nav>

看一下,自己测试一下,看看它是否能解决你的问题。

注意:

  • 我在CSS中使用了:hover,这样你就可以看到变化正在发生。
  • 要按照您想要的方式实现此操作,您将需要将类“active”硬编码到顶级列表项中...或者...您可以使用一些JavaScript来更加动态地完成此操作。
  • 您将看到我留下的最后两行css的评论...只需用.active替换:hover
  • 我需要添加到HTML中的唯一内容是一些容器
    ,以包装每个子菜单。这是我能找到的唯一一种方法,可以在允许跨越页面的彩带的同时,将您的子导航居中在页面上。

我的CSS可能有点混乱,但那只是因为我把它扔在一起。您需要根据自己的喜好进行样式设置。

希望您喜欢!如果您需要任何澄清,请告诉我。

编辑:哦,忘了提到...我取消了您所拥有的所有ID和类,因为它们对功能没有必要性...但是,如果您想将特定颜色与特定子菜单相关联,则需要重新添加一些ID。


7
请在实际答案中发布您的代码。当您这样做时,我会取消投反对票。 - tckmn
这个解决方案是否可以在内部的<ul>标签周围不添加<div>的情况下完成? - Greeso
从技术上讲,是有办法的...但这并不容易...你需要为子菜单中的每个<li>创建非常具体的宽度和边距...如果所有的子菜单链接数量都不同,你将不得不为每个子菜单创建特定的样式...这会带来更多的麻烦,相信我。这是我能找到的最好的方法,可以使你的菜单居中,并且不依赖于个别样式。 - Grapho

3

为了确保每个人都能看到我选择的答案(即为了更大的好处),我在此添加最终答案。

这个答案是受到GraphicO的启发,并进行了修改:

HTML代码:

<nav>
    <ul class="main-menu" >
        <li id="item1">
            <a href="#">item 1</a>

            <div>
                <ul class="sub-menu">
                    <li id="item11">
                        <a href="#">item 1.1</a>
                    </li>

                    <li id="item12">
                        <a href="#">item 1.2</a>
                    </li>

                    <li id="item13">
                        <a href="#">item 1.3</a>
                    </li>

                </ul>
            </div>
        </li>

        <li id="item2">
            <a href="#">item 2</a>

            <div>
                <ul class="sub-menu">
                    <li id="item21">
                        <a href="#">item 2.1</a>
                    </li>

                    <li id="item22">
                        <a href="#">item 2.2</a>
                    </li>
                </ul>
            </div>
        </li>

        <li id="item3">
            <a href="#">item 3</a>
        </li>

    </ul>
</nav>

接下来是 CSS 部分:
a {
    color: black;
    text-decoration: none;
}

nav {
    position: relative;
    width: 100%;

    background-color: red;
}

.main-menu {
    margin: 0 auto;
    width: 1024px;

    list-style: none;
}

.main-menu > li {
    display: inline-block;
    margin-right: 2em;
}

.main-menu > li.selected {
    background-color: yellow;
}

.main-menu > li > div { /* nested div (containing the sub nav) will be hidden by default */
    width: 100%;

    position: absolute;
    left: 0;

    background-color: yellow;
    display:none;
}

.main-menu > li.selected > div {
    display: inline;
}

.sub-menu {
    list-style: none;

    margin: 0 auto;
    width: 1024px;
}

.sub-menu > li {
    display: inline-block;
    margin-right: 2em;
}

最后是jQuery:

// Make the first class selected
$(".main-menu > li:first").addClass("selected");

// Switch the selected class
$(".main-menu > li").click(function() {
    $(".selected").removeClass("selected");
    $(this).addClass("selected");
});

// Disable menu links
$(".main-menu > li > a").click(function(e) {
    e.preventDefault();
});

感谢您。

1
如果我理解您的问题,这应该可以帮助您:

http://jsfiddle.net/X7T94/

需要在您希望作为活动项目的主菜单li上放置class="active"。您的其余HTML保持不变。CSS:

.full-width {
    width: 100%;
}

.normal-width {
    width: 1024px;
    margin: 0 auto 0 auto;
}
.main-menu > li {
    float:left;
    list-style-type:none;
    padding-right:30px;
}
.sub-menu {
    display:none;
}
.sub-menu li {
    float:left;
    padding-right:30px;
}
.main-menu li.active {
    background-color:blue;
}
.main-menu > li.active .sub-menu {
    display:block;
    position:absolute;
    left:0;
    right:0;
    background-color:blue;
}

显然,它并不完美或美丽,但它应该能帮助你一步步地前进。

谢谢。所以你的意思是说,应该在点击时将“.active”作为jQuery/JavaScript操作添加进去? - Greeso
好吧,我想我的想法是菜单大部分是静态的,就像你引用的网站一样,所以可以在页面加载时通过编程方式添加 .active。我想你也可以在点击时添加 .active。我写了一点 jQuery 来帮助。http://jsfiddle.net/X7T94/1/ - Tim Wasson
然而,只有一个问题,这也是我发布这个问题的主要原因,即子菜单没有考虑不同的屏幕宽度。正如您所注意到的,主菜单在任何屏幕上都是居中的,但是子菜单始终会因其位置而移动,但不是居中的,这可能无法适用于不同的宽度! - Greeso
努力理解中...所以你想将子菜单居中吗?只需将li显示为inlineul 设为 text-align:center即可。http://jsfiddle.net/X7T94/2/ - Tim Wasson
不要居中子菜单,而是应该相对于页面进行排列(即第一个子菜单项在第一个菜单项下方),但是子菜单的背景应该延伸到页面边缘。 - Greeso
我更新了描述,向您展示了页面设计链接的图片。谢谢。 - Greeso

1
使用稍作修改的HTML和javascript,以下菜单可以正常工作(已在IE7-10、Chrome、Firefox、Opera和Safari中进行了测试):
HTML
<div id="menu-container" class="full-width">
    <div class="full-width-bg"></div>  <!-- this additional div makes red background -->
    <ul class="main-menu normal-width">
        ... etc ...
    </ul>
</div>

CSS

.full-width {
    width: 100%;
    background: orange;
    border:1px solid green;
    position:relative;
    z-index:1;
    height:3em;
    font-size:21px;
}
.full-width-bg {
    width:100%;
    background: red;
    height:50%;
    position:absolute;
    left:0;
    top:0;
    z-index:2;
}
.normal-width {
    width: 1024px;
    margin: 0 auto;
    z-index:3;
    position:relative;
}
.full-width, .full-width-bg {
    min-width: 1024px;
}
ul.main-menu li {
    float:left;
    padding:0;
    margin:0;
    height:100%;
    position:static;
    text-align:center;
}
ul.main-menu, ul.main-menu ul {
    list-style-type:none;
    height: 1.5em;
    margin: 0 auto;
    padding: 0;
}
ul.main-menu a {
    text-decoration:none;
    display:inline-block;
    *display:inline; zoom:1; /* IE7 fix */
    width:100%;
    padding:0;
    max-height: 1.5em;
}
ul.main-menu > li {
    background-color:red;
}
ul.main-menu > li > ul > li {
    background-color:orange;
}
ul.main-menu > li > ul > li:hover {
    background-color:yellow;
}
ul.main-menu > li > ul > li:hover > a {
    color:red;
}
ul.main-menu > li > ul {
    position:absolute;
    top:100%;
    left:0px;
    width:100%;
}
.main-menu > li.selected,
ul.main-menu > li:hover > a {
    background-color:#d00;
    color:white;
}
ul.main-menu > li > ul {
    display:none;
    z-index:4;
}
ul.main-menu > li:hover > ul {
    display:block;
    z-index:5;
}

jQuery

$(function () {
    var items = $('.main-menu>li');
    var maxitems = 5; //items.length;
    var current = items[0];
    $('.main-menu li').css('width', (100 / maxitems | 0) + '%');
    items.mouseenter(function(e) {
        $(current).removeClass('selected').children('ul').hide();
        current = this;
        $(current).addClass('selected').children('ul').show();
    });
    items.children('ul').show().end().eq(0).trigger('mouseenter');
});

JSFiddle: http://jsfiddle.net/X7T94/12/ - 这个主菜单保留了5个菜单链接的位置(请参见javascript)


谢谢,但是我想将主菜单(您的示例中颜色为#dfd的背景)和子菜单(您的示例中颜色为#ddf的背景)的背景扩展到页面的相同宽度。我开始觉得用菜单结构无法实现这个目标。 - Greeso
抱歉,还不太对。我更新了问题,并附上了一张图片的链接,这样你就可以看到我想要它如何完成了。 - Greeso

0

您的类 .normal-width(定义宽度为1024px)需要在内容上而不是菜单上使用(您希望菜单具有100%的宽度)

所以只需从菜单中删除它,并将其添加到您的内容中即可 - 就像这样:

<div id="menu-container" class="full-width">
   <nav id="nav1">
      ...
   </nav>   
</div>
<div class="content normal-width">Content goes here</div>

代码片段


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接