我如何才能真正地证明HTML+CSS中的水平菜单是合理的?

时间:2021-10-03 10:50:34

You find plenty of tutorials on menu bars in HTML, but for this specific (though IMHO generic) case, I haven't found any decent solution:

您可以在HTML的菜单栏中找到大量的教程,但是对于这个特定的(尽管是IMHO通用的)案例,我还没有找到合适的解决方案:

#  THE MENU ITEMS    SHOULD BE    JUSTIFIED     JUST AS    PLAIN TEXT     WOULD BE  #
#  ^                                                                             ^  #
  • There's an varying number of text-only menu items and the page layout is fluid.
  • 只有不同数量的纯文本菜单项,页面布局是流畅的。
  • The first menu item should be left-aligned, the last menu item should be right-aligned.
  • 第一个菜单项应该是左对齐的,最后一个菜单项应该是右对齐的。
  • The remaining items should be spread optimally on the menu bar.
  • 剩下的项目应该在菜单栏上最优地展开。
  • The number is varying,so there's no chance to pre-calculate the optimal widths.
  • 数字是变化的,所以没有机会预先计算最优宽度。

Note that a TABLE won't work here as well:

请注意,这里的表也不能正常工作:

  • If you center all TDs, the first and the last item aren’t aligned correctly.
  • 如果你把所有TDs都集中在一起,那么第一个和最后一个项就不能正确对齐。
  • If you left-align and right-align the first resp. the last items, the spacing will be sub-optimal.
  • 如果你左对齐右对齐第一个resp。最后一项,间距将是次优的。

Isn’t it strange that there is no obvious way to implement this in a clean way by using HTML and CSS?

很奇怪,用HTML和CSS以一种干净的方式来实现这一点不是很奇怪吗?

13 个解决方案

#1


39  

Modern Approach - Flexboxes!

Now that CSS3 flexboxes have better browser support, some of us can finally start using them. Just add additional vendor prefixes for more browser coverage.

既然CSS3 flexbox有更好的浏览器支持,我们中的一些人终于可以开始使用它们了。只需添加额外的供应商前缀以获得更多的浏览器覆盖率。

In this instance, you would just set the parent element's display to flex and then change the justify-content property to either space-between or space-around in order to add space between or around the children flexbox items.

在此实例中,您只需将父元素的显示设置为flex,然后将适当的内容属性更改为空间或空间之间的空间,以便在孩子之间或周围添加空间。

Using justify-content: space-between - (example here):

使用合理内容:空格-(在这里):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-between;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>


Using justify-content: space-around - (example here):

使用合理内容:空间-(例如此处):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-around;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>

#2


83  

The simplest thing to do is to is to force the line to break by inserting an element at the end of the line that will occupy more than the left available space and then hiding it. I've accomplished this quite easily with a simple span element like so:

最简单的做法是,在一行的末尾插入一个元素,它会占用比左边更多的空间,然后隐藏它。我用一个简单的span元素很容易做到这一点:

#menu {
  text-align: justify;
}

#menu * {
  display: inline;
}

#menu li {
  display: inline-block;
}

#menu span {
  display: inline-block;
  position: relative;
  width: 100%;
  height: 0;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 2</a></li>
  </ul>
  <span></span>
</div>

All the junk inside the #menu span selector is (as far as I've found) required to please most browsers. It should force the width of the span element to 100%, which should cause a line break since it is considered an inline element due to the display: inline-block rule. inline-block also makes the span possible to block-level style rules like width which causes the element to not fit in line with the menu and thus the menu to line-break.

#菜单span选择器内的所有垃圾都是(据我所知)要求大多数浏览器。它应该将span元素的宽度设置为100%,这应该会导致换行符,因为它被认为是一个内联元素,因为显示:inline-block规则。inline-block还可以使块级样式规则(比如宽度)成为可能,从而导致元素不能与菜单相匹配,从而使菜单变为行中断。

You of course need to adjust the width of the span to your use case and design, but I hope you get the general idea and can adapt it.

当然,你需要调整跨度的宽度到你的用例和设计,但我希望你能得到一般的想法并能适应它。

#3


12  

Ok, this solution doesn't work on IE6/7, because of the lack of support of :before/:after, but:

好的,这个解决方案在IE6/7上不起作用,因为缺少支持:before/:after,但是:

ul {
  text-align: justify;
  list-style: none;
  list-style-image: none;
  margin: 0;
  padding: 0;
}
ul:after {
  content: "";
  margin-left: 100%;
}
li {
  display: inline;
}
a {
  display: inline-block;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 2</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 4</a></li>
    <li><a href="#">Menu item 5</a></li>
  </ul>
</div>

The reason why I have the a tag as an inline-block is because I don't want the words inside to be justified as well, and I don't want to use non-breaking spaces either.

我之所以有一个标签作为inline-block的原因是因为我不希望里面的文字也有道理,而且我也不想使用非破坏空间。

#4


8  

Got a solution. Works in FF, IE6, IE7, Webkit, etc.

有一个解决方案。工作在FF, IE6, IE7, Webkit等。

Make sure you don't put any whitespace before closing the span.inner. IE6 will break.

在关闭扳手之前,请确保不要放置任何空格。IE6将打破。

You can optionally give .outer a width

你可以随意给出。外宽。

.outer {
  text-align: justify;
}
.outer span.finish {
  display: inline-block;
  width: 100%;
}
.outer span.inner {
  display: inline-block;
  white-space: nowrap;
}
<div class="outer">
  <span class="inner">THE MENU ITEMS</span>
  <span class="inner">SHOULD BE</span>
  <span class="inner">JUSTIFIED</span>
  <span class="inner">JUST AS</span>
  <span class="inner">PLAIN TEXT</span>
  <span class="inner">WOULD BE</span>
  <span class="finish"></span>
</div>

#5


4  

Works with Opera , Firefox, Chrome and IE

适用于Opera, Firefox, Chrome和IE。

ul {
   display: table;
   margin: 1em auto 0;
   padding: 0;
   text-align: center;
   width: 90%;
}

li {
   display: table-cell;
   border: 1px solid black;
   padding: 0 5px;
}

#6


3  

yet another solution. I had no option to tackle the html like adding distinguished class etc., so I found a pure css way.

另一个解决方案。我没有办法去处理html,比如添加不同的类等等,所以我找到了一个纯css的方法。

Works in Chrome, Firefox, Safari..don't know about IE.

在Chrome, Firefox, Safari中工作。不知道IE。

Test: http://jsfiddle.net/c2crP/1

测试:http://jsfiddle.net/c2crP/1

ul {
  margin: 0; 
  padding: 0; 
  list-style: none; 
  width: 200px; 
  text-align: justify; 
  list-style-type: none;
}
ul > li {
  display: inline; 
  text-align: justify; 
}

/* declaration below will add a whitespace after every li. This is for one line codes where no whitespace (of breaks) are present and the browser wouldn't know where to make a break. */
ul > li:after {
  content: ' '; 
  display: inline;
}

/* notice the 'inline-block'! Otherwise won't work for webkit which puts after pseudo el inside of it's parent instead of after thus shifting also the parent on next line! */
ul > li:last-child:after {
  display: inline-block;
  margin-left: 100%; 
  content: ' ';
}
<ul>
  <li><a href="#">home</a></li>
  <li><a href="#">exposities</a></li>
  <li><a href="#">werk</a></li>
  <li><a href="#">statement</a></li>
  <li><a href="#">contact</a></li>
</ul>

#7


2  

Make it a <p> with text-align: justify ?

用文本对齐方式将其设置为

:合理吗?

Update: Nevermind. That doesn't work at all as I'd thought.

更新:无所谓。这一点也不像我想的那样。

Update 2: Doesn't work in any browsers other than IE right now, but CSS3 has support for this in the form of text-align-last

更新2:在IE之外的任何浏览器中都不能工作,但是CSS3支持这种形式的文本- aligni -last。

#8


1  

For Gecko-based browsers, I came up with this solution. This solution doesn't work with WebKit browsers, though (e.g. Chromium, Midori, Epiphany), they still show trailing space after the last item.

对于基于geck的浏览器,我提出了这个解决方案。这个解决方案与WebKit浏览器不兼容,尽管(例如,Chromium, Midori, Epiphany),在最后一项之后仍然显示尾随空间。

I put the menu bar in a justified paragraph. Problem is that the last line of a justified paragraph won't be rendered justified, for obvious reasons. Therefore I add a wide invisible element (e.g. an img) which warrants that the paragraph is at least two lines long.

我把菜单栏放在一个合理的段落。问题是,合理段落的最后一行不会被证明是合理的,原因很明显。因此,我添加了一个广泛的不可见元素(例如img),它保证该段落至少有两行。

Now the menu bar is justified by the same algorithm the browser uses for justifying plain text.

现在,菜单栏用浏览器用来证明纯文本的相同算法来证明。

Code:

代码:

<div style="width:500px; background:#eee;">
 <p style="text-align:justify">
  <a href="#">THE&nbsp;MENU&nbsp;ITEMS</a>
  <a href="#">SHOULD&nbsp;BE</a>
  <a href="#">JUSTIFIED</a>
  <a href="#">JUST&nbsp;AS</a>
  <a href="#">PLAIN&nbsp;TEXT</a>
  <a href="#">WOULD&nbsp;BE</a>
  <img src="/Content/Img/*-logo-250.png" width="400" height="0"/>
 </p>
 <p>There's an varying number of text-only menu items and the page layout is fluid.</p>
 <p>The first menu item should be left-aligned, the last menu item should be right-aligned. The remaining items should be spread optimal on the menu bar.</p>
 <p>The number is varying,so there's no chance to pre-calculate the optimal widths.</p>
 <p>Note that a TABLE won't work here as well:</p>
 <ul>
  <li>If you center all TDs, the first and the last item aren't aligned correctly.</li>
  <li>If you left-align and right-align the first resp. the last items, the spacing will be sub-optimal.</li>
 </ul>
</div>

Remark: Do you notice I cheated? To add the space filler element, I have to make some guess about the width of the menu bar. So this solution is not completely down to the rules.

注:你注意到我作弊了吗?为了添加空间填充元素,我需要猜测一下菜单栏的宽度。所以这个解决方案并不完全符合规则。

#9


1  

Text is only justified if the sentence naturally causes a line break. So all you need to do is naturally force a line break, and hide whats on the second line:

只有当句子自然地导致断线时,文字才有意义。所以你所需要做的就是自然地强制换行,并在第二行隐藏什么:

CSS:

CSS:

ul {
  text-align: justify;
  width: 400px;
  margin: 0;
  padding: 0;
  height: 1.2em;
  /* forces the height of the ul to one line */
  overflow: hidden;
  /* enforces the single line height */
  list-style-type: none;
  background-color: yellow;
}

ul li {
  display: inline;
}

ul li.break {
  margin-left: 100%;
  /* use e.g. 1000px if your ul has no width */
}

HTML:

HTML:

<ul>
  <li><a href="/">The</a></li>
  <li><a href="/">quick</a></li>
  <li><a href="/">brown</a></li>
  <li><a href="/">fox</a></li>
  <li class="break">&nbsp;</li>
</ul>

The li.break element must be on the same line as the last menu item and must contain some content (in this case a non breaking space), otherwise in some browsers, if it's not on the same line then you'll see some small extra space on the end of your line, and if it contains no content then it's ignored and the line is not justified.

李。打破元素必须在同一行最后一个菜单项,必须包含一些内容(在本例中是一个非打破空间),否则在某些浏览器,如果它不是在同一行,那么你就会看到一些额外的空间在你的,如果它不包含任何内容的忽视和线是不合理的。

Tested in IE7, IE8, IE9, Chrome, Firefox 4.

测试在IE7, IE8, IE9, Chrome, Firefox 4。

#10


0  

if to go with javascript that is possible (this script is base on mootools)

如果要使用可能的javascript(这个脚本是基于mootools的)

<script type="text/javascript">//<![CDATA[
    window.addEvent('load', function(){
        var mncontainer = $('main-menu');
        var mncw = mncontainer.getSize().size.x;
        var mnul = mncontainer.getFirst();//UL
        var mnuw = mnul.getSize().size.x;
        var wdif = mncw - mnuw;
        var list = mnul.getChildren(); //get all list items
        //get the remained width (which can be positive or negative)
        //and devided by number of list item and also take out the precision
        var liwd = Math.floor(wdif/list.length);
        var selw, mwd=mncw, tliw=0;
        list.each(function(el){
            var elw = el.getSize().size.x;
            if(elw < mwd){ mwd = elw; selw = el;}
            el.setStyle('width', elw+liwd);
            tliw += el.getSize().size.x;
        });
        var rwidth = mncw-tliw;//get the remain width and set it to item which has smallest width
        if(rwidth>0){
            elw = selw.getSize().size.x;
            selw.setStyle('width', elw+rwidth);
        }
    });
    //]]>
</script>

and the css

和css

<style type="text/css">
    #main-menu{
        padding-top:41px;
        width:100%;
        overflow:hidden;
        position:relative;
    }
    ul.menu_tab{
        padding-top:1px;
        height:38px;
        clear:left;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        left:50%;
        text-align:center;
    }
    ul.menu_tab li{
        display:block;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        right:50%;
    }
    ul.menu_tab li.item7{
        margin-right:0;
    }
    ul.menu_tab li a, ul.menu_tab li a:visited{
        display:block;
        color:#006A71;
        font-weight:700;
        text-decoration:none;
        padding:0 0 0 10px;
    }
    ul.menu_tab li a span{
        display:block;
        padding:12px 10px 8px 0;
    }
    ul.menu_tab li.active a, ul.menu_tab li a:hover{
        background:url("../images/bg-menutab.gif") repeat-x left top;
        color:#999999;
    }
    ul.menu_tab li.active a span,ul.menu_tab li.active a.visited span, ul.menu_tab li a:hover span{
        background:url("../images/bg-menutab.gif") repeat-x right top;
        color:#999999;
    }
</style>

and the last html

最后一个html

<div id="main-menu">
    <ul class="menu_tab">
        <li class="item1"><a href="#"><span>Home</span></a></li>
        <li class="item2"><a href="#"><span>The Project</span></a></li>
        <li class="item3"><a href="#"><span>About Grants</span></a></li>
        <li class="item4"><a href="#"><span>Partners</span></a></li>
        <li class="item5"><a href="#"><span>Resources</span></a></li>
        <li class="item6"><a href="#"><span>News</span></a></li>
        <li class="item7"><a href="#"><span>Contact</span></a></li>
    </ul>
</div>

#11


0  

Simpler markup, tested in Opera, FF, Chrome, IE7, IE8:

更简单的标记,在Opera, FF, Chrome, IE7, IE8中测试:

<div class="nav">
  <a href="#" class="nav_item">nav item1</a>
  <a href="#" class="nav_item">nav item2</a>
  <a href="#" class="nav_item">nav item3</a>
  <a href="#" class="nav_item">nav item4</a>
  <a href="#" class="nav_item">nav item5</a>
  <a href="#" class="nav_item">nav item6</a>
  <span class="empty"></span>
</div>

and css:

和css:

.nav {
  width: 500px;
  height: 1em;
  line-height: 1em;
  text-align: justify;
  overflow: hidden;
  border: 1px dotted gray;
}
.nav_item {
  display: inline-block;
}
.empty {
  display: inline-block;
  width: 100%;
  height: 0;
}

Live example.

生活的例子。

#12


-1  

This can be achieved perfectly by some careful measurements and the last-child selector.

这可以通过一些仔细的测量和最后的选择器来实现。

ul li {
margin-right:20px;
}
ul li:last-child {
margin-right:0;
}

#13


-2  

I know the original question specified HTML + CSS, but it didn't specifically say no javascript ;)

我知道最初的问题是HTML + CSS,但它并没有明确地说没有javascript;)

Trying to keep the css and markup as clean as possible, and as semantically meaningful as possible to (using a UL for the menu) I came up with this suggestion. Probably not ideal, but it may be a good starting point:

尽量保持css和标记尽可能的干净,并且尽可能地有意义(使用一个UL作为菜单),我提出了这个建议。也许并不理想,但这可能是一个很好的起点:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

    <head>
        <title>Kind-of-justified horizontal menu</title>

        <style type="text/css">
        ul {
            list-style: none;
            margin: 0;
            padding: 0;
            width: 100%;
        }

        ul li {
            display: block;
            float: left;
            text-align: center;
        }
        </style>

        <script type="text/javascript">
            setMenu = function() {
                var items = document.getElementById("nav").getElementsByTagName("li");
                var newwidth = 100 / items.length;

                for(var i = 0; i < items.length; i++) {
                    items[i].style.width = newwidth + "%";
                }
            }
        </script>

    </head>

    <body>

        <ul id="nav">
            <li><a href="#">first item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
            <li><a href="#">last item</a></li>
        </ul>

        <script type="text/javascript">
            setMenu();
        </script>

    </body>

</html>

#1


39  

Modern Approach - Flexboxes!

Now that CSS3 flexboxes have better browser support, some of us can finally start using them. Just add additional vendor prefixes for more browser coverage.

既然CSS3 flexbox有更好的浏览器支持,我们中的一些人终于可以开始使用它们了。只需添加额外的供应商前缀以获得更多的浏览器覆盖率。

In this instance, you would just set the parent element's display to flex and then change the justify-content property to either space-between or space-around in order to add space between or around the children flexbox items.

在此实例中,您只需将父元素的显示设置为flex,然后将适当的内容属性更改为空间或空间之间的空间,以便在孩子之间或周围添加空间。

Using justify-content: space-between - (example here):

使用合理内容:空格-(在这里):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-between;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>


Using justify-content: space-around - (example here):

使用合理内容:空间-(例如此处):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-around;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>

#2


83  

The simplest thing to do is to is to force the line to break by inserting an element at the end of the line that will occupy more than the left available space and then hiding it. I've accomplished this quite easily with a simple span element like so:

最简单的做法是,在一行的末尾插入一个元素,它会占用比左边更多的空间,然后隐藏它。我用一个简单的span元素很容易做到这一点:

#menu {
  text-align: justify;
}

#menu * {
  display: inline;
}

#menu li {
  display: inline-block;
}

#menu span {
  display: inline-block;
  position: relative;
  width: 100%;
  height: 0;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 2</a></li>
  </ul>
  <span></span>
</div>

All the junk inside the #menu span selector is (as far as I've found) required to please most browsers. It should force the width of the span element to 100%, which should cause a line break since it is considered an inline element due to the display: inline-block rule. inline-block also makes the span possible to block-level style rules like width which causes the element to not fit in line with the menu and thus the menu to line-break.

#菜单span选择器内的所有垃圾都是(据我所知)要求大多数浏览器。它应该将span元素的宽度设置为100%,这应该会导致换行符,因为它被认为是一个内联元素,因为显示:inline-block规则。inline-block还可以使块级样式规则(比如宽度)成为可能,从而导致元素不能与菜单相匹配,从而使菜单变为行中断。

You of course need to adjust the width of the span to your use case and design, but I hope you get the general idea and can adapt it.

当然,你需要调整跨度的宽度到你的用例和设计,但我希望你能得到一般的想法并能适应它。

#3


12  

Ok, this solution doesn't work on IE6/7, because of the lack of support of :before/:after, but:

好的,这个解决方案在IE6/7上不起作用,因为缺少支持:before/:after,但是:

ul {
  text-align: justify;
  list-style: none;
  list-style-image: none;
  margin: 0;
  padding: 0;
}
ul:after {
  content: "";
  margin-left: 100%;
}
li {
  display: inline;
}
a {
  display: inline-block;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 2</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 4</a></li>
    <li><a href="#">Menu item 5</a></li>
  </ul>
</div>

The reason why I have the a tag as an inline-block is because I don't want the words inside to be justified as well, and I don't want to use non-breaking spaces either.

我之所以有一个标签作为inline-block的原因是因为我不希望里面的文字也有道理,而且我也不想使用非破坏空间。

#4


8  

Got a solution. Works in FF, IE6, IE7, Webkit, etc.

有一个解决方案。工作在FF, IE6, IE7, Webkit等。

Make sure you don't put any whitespace before closing the span.inner. IE6 will break.

在关闭扳手之前,请确保不要放置任何空格。IE6将打破。

You can optionally give .outer a width

你可以随意给出。外宽。

.outer {
  text-align: justify;
}
.outer span.finish {
  display: inline-block;
  width: 100%;
}
.outer span.inner {
  display: inline-block;
  white-space: nowrap;
}
<div class="outer">
  <span class="inner">THE MENU ITEMS</span>
  <span class="inner">SHOULD BE</span>
  <span class="inner">JUSTIFIED</span>
  <span class="inner">JUST AS</span>
  <span class="inner">PLAIN TEXT</span>
  <span class="inner">WOULD BE</span>
  <span class="finish"></span>
</div>

#5


4  

Works with Opera , Firefox, Chrome and IE

适用于Opera, Firefox, Chrome和IE。

ul {
   display: table;
   margin: 1em auto 0;
   padding: 0;
   text-align: center;
   width: 90%;
}

li {
   display: table-cell;
   border: 1px solid black;
   padding: 0 5px;
}

#6


3  

yet another solution. I had no option to tackle the html like adding distinguished class etc., so I found a pure css way.

另一个解决方案。我没有办法去处理html,比如添加不同的类等等,所以我找到了一个纯css的方法。

Works in Chrome, Firefox, Safari..don't know about IE.

在Chrome, Firefox, Safari中工作。不知道IE。

Test: http://jsfiddle.net/c2crP/1

测试:http://jsfiddle.net/c2crP/1

ul {
  margin: 0; 
  padding: 0; 
  list-style: none; 
  width: 200px; 
  text-align: justify; 
  list-style-type: none;
}
ul > li {
  display: inline; 
  text-align: justify; 
}

/* declaration below will add a whitespace after every li. This is for one line codes where no whitespace (of breaks) are present and the browser wouldn't know where to make a break. */
ul > li:after {
  content: ' '; 
  display: inline;
}

/* notice the 'inline-block'! Otherwise won't work for webkit which puts after pseudo el inside of it's parent instead of after thus shifting also the parent on next line! */
ul > li:last-child:after {
  display: inline-block;
  margin-left: 100%; 
  content: ' ';
}
<ul>
  <li><a href="#">home</a></li>
  <li><a href="#">exposities</a></li>
  <li><a href="#">werk</a></li>
  <li><a href="#">statement</a></li>
  <li><a href="#">contact</a></li>
</ul>

#7


2  

Make it a <p> with text-align: justify ?

用文本对齐方式将其设置为

:合理吗?

Update: Nevermind. That doesn't work at all as I'd thought.

更新:无所谓。这一点也不像我想的那样。

Update 2: Doesn't work in any browsers other than IE right now, but CSS3 has support for this in the form of text-align-last

更新2:在IE之外的任何浏览器中都不能工作,但是CSS3支持这种形式的文本- aligni -last。

#8


1  

For Gecko-based browsers, I came up with this solution. This solution doesn't work with WebKit browsers, though (e.g. Chromium, Midori, Epiphany), they still show trailing space after the last item.

对于基于geck的浏览器,我提出了这个解决方案。这个解决方案与WebKit浏览器不兼容,尽管(例如,Chromium, Midori, Epiphany),在最后一项之后仍然显示尾随空间。

I put the menu bar in a justified paragraph. Problem is that the last line of a justified paragraph won't be rendered justified, for obvious reasons. Therefore I add a wide invisible element (e.g. an img) which warrants that the paragraph is at least two lines long.

我把菜单栏放在一个合理的段落。问题是,合理段落的最后一行不会被证明是合理的,原因很明显。因此,我添加了一个广泛的不可见元素(例如img),它保证该段落至少有两行。

Now the menu bar is justified by the same algorithm the browser uses for justifying plain text.

现在,菜单栏用浏览器用来证明纯文本的相同算法来证明。

Code:

代码:

<div style="width:500px; background:#eee;">
 <p style="text-align:justify">
  <a href="#">THE&nbsp;MENU&nbsp;ITEMS</a>
  <a href="#">SHOULD&nbsp;BE</a>
  <a href="#">JUSTIFIED</a>
  <a href="#">JUST&nbsp;AS</a>
  <a href="#">PLAIN&nbsp;TEXT</a>
  <a href="#">WOULD&nbsp;BE</a>
  <img src="/Content/Img/*-logo-250.png" width="400" height="0"/>
 </p>
 <p>There's an varying number of text-only menu items and the page layout is fluid.</p>
 <p>The first menu item should be left-aligned, the last menu item should be right-aligned. The remaining items should be spread optimal on the menu bar.</p>
 <p>The number is varying,so there's no chance to pre-calculate the optimal widths.</p>
 <p>Note that a TABLE won't work here as well:</p>
 <ul>
  <li>If you center all TDs, the first and the last item aren't aligned correctly.</li>
  <li>If you left-align and right-align the first resp. the last items, the spacing will be sub-optimal.</li>
 </ul>
</div>

Remark: Do you notice I cheated? To add the space filler element, I have to make some guess about the width of the menu bar. So this solution is not completely down to the rules.

注:你注意到我作弊了吗?为了添加空间填充元素,我需要猜测一下菜单栏的宽度。所以这个解决方案并不完全符合规则。

#9


1  

Text is only justified if the sentence naturally causes a line break. So all you need to do is naturally force a line break, and hide whats on the second line:

只有当句子自然地导致断线时,文字才有意义。所以你所需要做的就是自然地强制换行,并在第二行隐藏什么:

CSS:

CSS:

ul {
  text-align: justify;
  width: 400px;
  margin: 0;
  padding: 0;
  height: 1.2em;
  /* forces the height of the ul to one line */
  overflow: hidden;
  /* enforces the single line height */
  list-style-type: none;
  background-color: yellow;
}

ul li {
  display: inline;
}

ul li.break {
  margin-left: 100%;
  /* use e.g. 1000px if your ul has no width */
}

HTML:

HTML:

<ul>
  <li><a href="/">The</a></li>
  <li><a href="/">quick</a></li>
  <li><a href="/">brown</a></li>
  <li><a href="/">fox</a></li>
  <li class="break">&nbsp;</li>
</ul>

The li.break element must be on the same line as the last menu item and must contain some content (in this case a non breaking space), otherwise in some browsers, if it's not on the same line then you'll see some small extra space on the end of your line, and if it contains no content then it's ignored and the line is not justified.

李。打破元素必须在同一行最后一个菜单项,必须包含一些内容(在本例中是一个非打破空间),否则在某些浏览器,如果它不是在同一行,那么你就会看到一些额外的空间在你的,如果它不包含任何内容的忽视和线是不合理的。

Tested in IE7, IE8, IE9, Chrome, Firefox 4.

测试在IE7, IE8, IE9, Chrome, Firefox 4。

#10


0  

if to go with javascript that is possible (this script is base on mootools)

如果要使用可能的javascript(这个脚本是基于mootools的)

<script type="text/javascript">//<![CDATA[
    window.addEvent('load', function(){
        var mncontainer = $('main-menu');
        var mncw = mncontainer.getSize().size.x;
        var mnul = mncontainer.getFirst();//UL
        var mnuw = mnul.getSize().size.x;
        var wdif = mncw - mnuw;
        var list = mnul.getChildren(); //get all list items
        //get the remained width (which can be positive or negative)
        //and devided by number of list item and also take out the precision
        var liwd = Math.floor(wdif/list.length);
        var selw, mwd=mncw, tliw=0;
        list.each(function(el){
            var elw = el.getSize().size.x;
            if(elw < mwd){ mwd = elw; selw = el;}
            el.setStyle('width', elw+liwd);
            tliw += el.getSize().size.x;
        });
        var rwidth = mncw-tliw;//get the remain width and set it to item which has smallest width
        if(rwidth>0){
            elw = selw.getSize().size.x;
            selw.setStyle('width', elw+rwidth);
        }
    });
    //]]>
</script>

and the css

和css

<style type="text/css">
    #main-menu{
        padding-top:41px;
        width:100%;
        overflow:hidden;
        position:relative;
    }
    ul.menu_tab{
        padding-top:1px;
        height:38px;
        clear:left;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        left:50%;
        text-align:center;
    }
    ul.menu_tab li{
        display:block;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        right:50%;
    }
    ul.menu_tab li.item7{
        margin-right:0;
    }
    ul.menu_tab li a, ul.menu_tab li a:visited{
        display:block;
        color:#006A71;
        font-weight:700;
        text-decoration:none;
        padding:0 0 0 10px;
    }
    ul.menu_tab li a span{
        display:block;
        padding:12px 10px 8px 0;
    }
    ul.menu_tab li.active a, ul.menu_tab li a:hover{
        background:url("../images/bg-menutab.gif") repeat-x left top;
        color:#999999;
    }
    ul.menu_tab li.active a span,ul.menu_tab li.active a.visited span, ul.menu_tab li a:hover span{
        background:url("../images/bg-menutab.gif") repeat-x right top;
        color:#999999;
    }
</style>

and the last html

最后一个html

<div id="main-menu">
    <ul class="menu_tab">
        <li class="item1"><a href="#"><span>Home</span></a></li>
        <li class="item2"><a href="#"><span>The Project</span></a></li>
        <li class="item3"><a href="#"><span>About Grants</span></a></li>
        <li class="item4"><a href="#"><span>Partners</span></a></li>
        <li class="item5"><a href="#"><span>Resources</span></a></li>
        <li class="item6"><a href="#"><span>News</span></a></li>
        <li class="item7"><a href="#"><span>Contact</span></a></li>
    </ul>
</div>

#11


0  

Simpler markup, tested in Opera, FF, Chrome, IE7, IE8:

更简单的标记,在Opera, FF, Chrome, IE7, IE8中测试:

<div class="nav">
  <a href="#" class="nav_item">nav item1</a>
  <a href="#" class="nav_item">nav item2</a>
  <a href="#" class="nav_item">nav item3</a>
  <a href="#" class="nav_item">nav item4</a>
  <a href="#" class="nav_item">nav item5</a>
  <a href="#" class="nav_item">nav item6</a>
  <span class="empty"></span>
</div>

and css:

和css:

.nav {
  width: 500px;
  height: 1em;
  line-height: 1em;
  text-align: justify;
  overflow: hidden;
  border: 1px dotted gray;
}
.nav_item {
  display: inline-block;
}
.empty {
  display: inline-block;
  width: 100%;
  height: 0;
}

Live example.

生活的例子。

#12


-1  

This can be achieved perfectly by some careful measurements and the last-child selector.

这可以通过一些仔细的测量和最后的选择器来实现。

ul li {
margin-right:20px;
}
ul li:last-child {
margin-right:0;
}

#13


-2  

I know the original question specified HTML + CSS, but it didn't specifically say no javascript ;)

我知道最初的问题是HTML + CSS,但它并没有明确地说没有javascript;)

Trying to keep the css and markup as clean as possible, and as semantically meaningful as possible to (using a UL for the menu) I came up with this suggestion. Probably not ideal, but it may be a good starting point:

尽量保持css和标记尽可能的干净,并且尽可能地有意义(使用一个UL作为菜单),我提出了这个建议。也许并不理想,但这可能是一个很好的起点:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

    <head>
        <title>Kind-of-justified horizontal menu</title>

        <style type="text/css">
        ul {
            list-style: none;
            margin: 0;
            padding: 0;
            width: 100%;
        }

        ul li {
            display: block;
            float: left;
            text-align: center;
        }
        </style>

        <script type="text/javascript">
            setMenu = function() {
                var items = document.getElementById("nav").getElementsByTagName("li");
                var newwidth = 100 / items.length;

                for(var i = 0; i < items.length; i++) {
                    items[i].style.width = newwidth + "%";
                }
            }
        </script>

    </head>

    <body>

        <ul id="nav">
            <li><a href="#">first item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
            <li><a href="#">last item</a></li>
        </ul>

        <script type="text/javascript">
            setMenu();
        </script>

    </body>

</html>