CSS多行菜单占据整个宽度

3

可能已经有解决方案或示例了,但我找不到。

我想创建一个菜单,其中菜单项的数量不同,每个菜单项的宽度也不同(取决于其内容)。如果菜单项太多,我希望它们可以占用多行。

我的第一个解决方案是简单的浮动。这很好,但在行的末尾有一个不均匀的未占用空间:

The right end of the menu looks ugly

忽略项目上的“文本”具有相同的宽度。我只是不擅长绘画。想象一下,这些文本长度不同,但周围的填充相同。
通过巧妙的边框(仅在项目的左侧边框)我能够稍微隐藏这个问题,但可点击区域仍然与上图中的白色部分相同。悬停效果也会揭示这个技巧。

我做了一些关于text-align justify的研究,并找到了像这样的解决方案:"如何使行内块元素正确对齐:text-align: justify;"

乍一看,这正是我想要的。元素对齐得很好,在视觉上填满了可用空间。但是有一个根本性的缺陷:它们之间有间隙:

There are gaps

这是预期的,因为这将我的元素视为文本中的单词。我没有找到解决方法。

后来我开始在flexbox land四处寻找。这看起来很有前途,flexbox似乎是css的终极目标,但我还没有完全理解它。


基本上,我想要的是这个:

Perfect

按钮填满可用空间,菜单是多行的(当元素太多时为一行),整个菜单可点击(带有可见的悬停效果)。
有没有办法做到这一点?
我不确定是否要使用JavaScript解决方案(如计算和调整元素的宽度)。但如果有一个非常干净的解决方案,我可能会使用它。

编辑:

菜单这里看起来很不错,但只有当菜单是单行时才行。这通过将最后一个元素添加到另一个列表中,并使用不可见的:after { content ". . ." }元素添加大量空间来进行破解。


注释掉内联块元素之间的空格。 - Pete
@Pete,你是指inline-block对齐的解决方案吗?那样就不会被调整对齐了。 - vinczemarton
1
一直在尝试使用flex布局,这在Chrome和IE10中可以工作,但在其他浏览器中不行:jsfiddle.net/74AJD/6。我可能会选择使用JS解决方案 - 在flex box没有完全支持的情况下,这是最好的选择。 - Pete
如果它能在所有主要浏览器上运行,那就太棒了! - vinczemarton
@Pete 如果您将您的fiddle变成一个答案,我会很乐意接受它。 - vinczemarton
显示剩余2条评论
1个回答

3
如果您使用以下的flexbox样式,它将在IE10和Chrome中实现您想要的效果。但是我不认为这在所有浏览器中都得到了完全支持。 HTML
<ul>
    <li>test test</li>
    <li>test</li>
    <li>test testtest</li>
    <li>testtest</li>
    <li>test</li>
    <li>test test test</li>
    <li>test test</li>
    <li>test</li>
</ul>

Css

ul {
    list-style:none; margin:0; padding:0; 
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-direction: row;
    -ms-flex-direction: row;
    -moz-flex-direction: row;
    flex-direction: row;
    -webkit-flex-wrap: wrap;
    -ms-flex-wrap: wrap;
    -moz-flex-wrap: wrap;
    flex-wrap: wrap;
    width: 300px; 
}

li {
     white-space:nowrap;  
     border:1px solid #cccccc; 
     padding:5px; 
    -webkit-flex: auto;
    -moz-flex: auto;
    -ms-flex: auto ;
    flex: auto;
}

示例


由问题作者编辑:

我认为应该更新这个答案,因为我学到了一些关于 flexbox 的东西。

  1. 对于多行 flexboxes,厂商前缀几乎没有用。很难找到任何支持多行 flexbox 但带有厂商前缀的浏览器版本。通常,厂商前缀指的是一个旧版的 flexbox,在那里多行受到非常不同的处理方式。

  2. 除了 Firefox 外,所有主要浏览器都支持它,但一个实现已经合并到 alpha 中,所以它将出现在Firefox 28中。大多数桌面用户将看到您的设计(仍然重要的是实现可用的回退)。

  3. 使用Modernizr非常容易测试多行 flexbox 支持,因为 Flexible Box Model 测试专门测试flex-wrap属性,该属性仅存在于支持它的实现中。非常干净地为不支持它的每个浏览器实现基于float:left的回退。

我的最终实现采用基于 Modernizr 的后备方案,如下所示:

ul {
    /* general */
    list-style: none;
    margin: 0;
    padding: 0;
    width: 100%;
}
.flexbox ul {
    display: flex;
    flex-flow: row wrap;
}
li {
    /* general */
    white-space: nowrap;
    border: 1px solid #555555;

    /* fallback */
    float: left;
}
.flexbox li {
    flex: auto;
}
li:first-child {
    /* general */
    text-align: right;
    order: 1;

    /* fallback */
    float: right !important;
}

这应该在所有浏览器中都能正常工作,虽然回退实现不如 flexbox 那样漂亮。

请注意,li:first-child 是 flexbox 的最后一个元素,因为它有 order: 1 属性。所有其他元素都有默认的 order 值为 0。这是因为在回退中将其向右浮动变得更容易。


flex-wrap 在 Opera、Safari、Chrome 和 IE 中都有效。我还可以使用 Modernizr 来检查 flexbox 支持,并实现回退设计。我可能会编辑您的答案以添加更多关于这个主题的细节。 - vinczemarton
很酷,能看到如何在Opera和Safari中完成这个操作会很好。 - Pete

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