Você encontra muitos tutoriais sobre barras de menu em HTML, mas para este caso específico (embora genérico IMHO), não encontrei nenhuma solução decente:
# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE #
# ^ ^ #
- Há um número variável de itens de menu somente texto e o layout da página é fluido.
- O primeiro item de menu deve ser alinhado à esquerda, o último item de menu deve ser alinhado à direita.
- Os demais itens devem ser distribuídos de forma ideal na barra de menu.
- O número varia, então não há chance de pré-calcular as larguras ideais.
Observe que uma TABELA não funcionará aqui também:
- Se você centralizar todos os TDs, o primeiro e o último item não estão alinhados corretamente.
- Se você alinhar à esquerda e à direita o primeiro resp. nos últimos itens, o espaçamento será abaixo do ideal.
Não é estranho que não haja uma maneira óbvia de implementar isso de forma limpa usando HTML e CSS?
span
vez de umhr
! Não está funcionando bem, o RH está ocupando espaço visível - use#menu { border: solid 1px green; }
para confirmar. Além disso,display: inline-block;
não funciona no IE (... 7? CompatibilityView?) Para elementos que não são naturalmente elementos embutidos. HR é um elemento de bloco, então estou supondo que o bloco embutido não funciona para RH no IE. Enfim, span.Ok, esta solução não funciona no IE6 / 7, devido à falta de suporte de
:before
/:after
, mas: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>
A razão pela qual eu tenho a tag a
inline-block
é porque não quero que as palavras dentro sejam justificadas também, e também não quero usar espaços não separáveis.fonte
text-justify: distribute-all-lines;
aoul
seletor. Parece ser coisa proprietária do IE.width: 100%
vez demargin-left: 100%
:ul:after{content:""; margin-left:100%;}
Tenho uma solução. Funciona em FF, IE6, IE7, Webkit, etc.
Certifique-se de não colocar nenhum espaço em branco antes de fechar o
span.inner
. O IE6 será interrompido.Você pode opcionalmente dar
.outer
uma largura.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>
fonte
.outer
line-height: 0
forças a altura da lista a ser renderizada como se consistisse em uma linha.Funciona com Opera, Firefox, Chrome e 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; }
fonte
ainda outra solução. Eu não tive nenhuma opção para lidar com o html como adicionar classes distintas etc., então eu encontrei uma maneira pura de css.
Funciona no Chrome, Firefox, Safari ... não sei sobre o IE.
Teste: 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>
fonte
Fazer
<p>
comtext-align: justify
?Atualização : esquece. Isso não funciona como eu pensava.
Atualização 2 : não funciona em nenhum navegador diferente do IE no momento, mas o CSS3 tem suporte para isso na forma de
text-align-last
fonte
text-align-last
funciona em qualquer navegador diferente do Safari . Este deve ser o possível oponente da abordagem flexbox ou do hack do span .Para navegadores baseados no Gecko, eu vim com esta solução. Esta solução não funciona com navegadores WebKit, embora (por exemplo, Chromium, Midori, Epiphany), eles ainda exibam um espaço à direita após o último item.
Coloquei a barra de menu em um parágrafo justificado . O problema é que a última linha de um parágrafo justificado não será tornada justificada, por razões óbvias. Portanto, adiciono um amplo elemento invisível (por exemplo, um img) que garante que o parágrafo tenha pelo menos duas linhas.
Agora, a barra de menus é justificada pelo mesmo algoritmo que o navegador usa para justificar o texto simples.
Código:
<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>
Observação: Você percebeu que eu trapaceei? Para adicionar o elemento de preenchimento de espaço, preciso adivinhar a largura da barra de menu. Portanto, esta solução não depende totalmente das regras.
fonte
O texto só é justificado se a frase causar naturalmente uma quebra de linha. Portanto, tudo o que você precisa fazer é forçar naturalmente uma quebra de linha e ocultar o que está na segunda linha:
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:
<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"> </li> </ul>
O elemento li.break deve estar na mesma linha que o último item de menu e deve conter algum conteúdo (neste caso, um espaço sem quebra), caso contrário, em alguns navegadores, se não estiver na mesma linha, você verá alguns pequenos espaço extra no final de sua linha e, se não tiver conteúdo, será ignorado e a linha não será justificada.
Testado em IE7, IE8, IE9, Chrome, Firefox 4.
fonte
se usar javascript é possível (este script é baseado no 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>
e o 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>
e o último 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>
fonte
Marcação mais simples, testada em 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>
e 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; }
Exemplo ao vivo .
fonte
Isso pode ser alcançado perfeitamente por algumas medições cuidadosas e o seletor do último filho.
ul li { margin-right:20px; } ul li:last-child { margin-right:0; }
fonte
Eu sei que a pergunta original especificava HTML + CSS, mas não dizia especificamente sem javascript ;)
Tentando manter o css e a marcação o mais limpo possível e o mais semanticamente significativo possível (usando um UL para o menu), tive esta sugestão. Provavelmente não é o ideal, mas pode ser um bom ponto de partida:
<!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>
fonte