如何真正证明HTML + CSS中的水平菜单?
我们可以在HTML的菜单栏上找到很多教程,但是对于这种特定的(尽管是恕我直言)通用案例,我还没有找到任何合适的解决方案:
# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE # # ^ ^ #
- 纯文本菜单项的数量不尽相同,页面布局也很流畅。
- 第一个菜单项应左对齐,最后一个菜单项应右对齐。
- 其余项目应在菜单栏上进行最佳分配。
- 数字是变化的,因此没有机会预先计算出最佳宽度。
请注意,TABLE在这里也无法正常工作:
- 如果将所有TD居中,则第一项和最后一项不会正确对齐。
- 如果左对齐,右对齐第一个。最后一项,间隔将不是最佳的。
难道没有明显的方法可以通过使用HTML和CSS以干净的方式实现此功能吗?
解决方案
回答
用text-align:justify
使其成为<p>
吗?
更新:没关系。就像我想的那样,那根本不起作用。
更新2:目前无法在IE以外的任何浏览器中使用,但是CSS3以text-align-last
的形式支持此功能
回答
对于基于Gecko的浏览器,我想出了这个解决方案。尽管此解决方案不适用于WebKit浏览器(例如Chromium,Midori,Epiphany),但它们在最后一项之后仍显示尾随空格。
我将菜单栏放在一个合理的段落中。问题是,出于明显的原因,有理由的段落的最后一行将不会被证明是有理由的。因此,我添加了一个宽的不可见元素(例如img),以保证该段至少有两行长。
现在,菜单栏由浏览器用于证明纯文本的算法相同。
代码:
<div style="width:500px; background:#eee;"> <p style="text-align:justify"> <a href="#">THE MENU ITEMS</a> <a href="#">SHOULD BE</a> <a href="#">JUSTIFIED</a> <a href="#">JUST AS</a> <a href="#">PLAIN TEXT</a> <a href="#">WOULD BE</a> <img src="/Content/Img/stackoverflow-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>
备注:你注意到我被骗了吗?要添加空格元素,我必须对菜单栏的宽度进行一些猜测。因此,这种解决方案并不完全符合规则。
回答
我知道最初的问题指定了HTML + CSS,但没有明确说没有javascript;)
试图保持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>
回答
最简单的方法是通过在行的末尾插入一个元素(该元素将占用比剩余的可用空间更多的内容),然后隐藏它来迫使行断开。我可以通过一个简单的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>
(据我发现)"#menu span"选择器中的所有垃圾都是使大多数浏览器满意的必需条件。它应该将" span"元素的宽度强制为100%,这会导致换行,因为由于" display:inline-block"规则,它被视为一个内联元素。 " inline-block"还使" span"成为块级样式规则(如" width")的可能,这会导致元素不适合菜单,从而使菜单换行。
当然,我们需要根据自己的用例和设计调整span
的宽度,但是希望我们能理解并适应它。
回答
有一个解决方案。适用于FF,IE6,IE7,Webkit等
确保在关闭span.inner
之前不要放置任何空格。 IE6会崩溃。
我们可以选择给.outer宽度
.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>
回答
是否使用可能的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>
和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>
和最后的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>