Encontrará muchos tutoriales sobre barras de menú en HTML, pero para este caso específico (aunque en mi humilde opinión genérico), no he encontrado ninguna solución decente:
# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE #
# ^ ^ #
- Hay un número variable de elementos de menú de solo texto y el diseño de la página es fluido.
- El primer elemento del menú debe estar alineado a la izquierda, el último elemento del menú debe estar alineado a la derecha.
- Los elementos restantes deben distribuirse de manera óptima en la barra de menú.
- El número varía, por lo que no hay posibilidad de calcular previamente los anchos óptimos.
Tenga en cuenta que una TABLA no funcionará aquí también:
- Si centra todos los TD, el primero y el último elemento no están alineados correctamente.
- Si alinea a la izquierda y alinea a la derecha el primer resp. los últimos elementos, el espaciado será subóptimo.
¿No es extraño que no haya una forma obvia de implementar esto de una manera limpia usando HTML y CSS?
span
lugar de unhr
! Realmente no está funcionando, el HR está ocupando un espacio visible; use#menu { border: solid 1px green; }
para confirmar. Además,display: inline-block;
no funciona en IE (... 7? CompatibilityView?) Para elementos que no son naturalmente elementos en línea. HR es un elemento de bloque, por lo que supongo que el bloque en línea no funciona para HR en IE. De todos modos, span.Ok, esta solución no funciona en IE6 / 7, debido a la falta de soporte de
:before
/:after
, pero: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>
La razón por la que tengo la etiqueta a como una
inline-block
es porque no quiero que las palabras del interior también se justifiquen, y tampoco quiero usar espacios que no se rompan.fuente
text-justify: distribute-all-lines;
alul
selector. Parece ser propiedad de IE.width: 100%
lugar demargin-left: 100%
:ul:after{content:""; margin-left:100%;}
Tengo una solución. Funciona en FF, IE6, IE7, Webkit, etc.
Asegúrese de no dejar espacios en blanco antes de cerrar el archivo
span.inner
. IE6 se romperá.Opcionalmente puede dar
.outer
un ancho.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>
fuente
.outer
line-height: 0
fuerzas la altura de la lista para que se represente como si estuviera formada por una línea.Funciona con 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; }
fuente
otra solución más. No tenía ninguna opción para abordar el html como agregar una clase distinguida, etc., así que encontré una forma pura de CSS.
Funciona en Chrome, Firefox, Safari ... no sé sobre IE.
Prueba: 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>
fuente
¿Hacerlo
<p>
context-align: justify
?Actualización : No importa. Eso no funciona en absoluto como pensaba.
Actualización 2 : no funciona en ningún otro navegador que no sea IE en este momento, pero CSS3 tiene soporte para esto en forma de
text-align-last
fuente
text-align-last
funciona en cualquier navegador que no sea Safari . Este debería ser el posible oponente del enfoque de flexbox o el hack de span .Para los navegadores basados en Gecko, se me ocurrió esta solución. Esta solución no funciona con los navegadores WebKit, aunque (por ejemplo, Chromium, Midori, Epiphany), todavía muestran un espacio al final del último elemento.
Pongo la barra de menú en un párrafo justificado . El problema es que la última línea de un párrafo justificado no se justificará por razones obvias. Por lo tanto, agrego un elemento invisible ancho (por ejemplo, una imagen) que garantiza que el párrafo tiene al menos dos líneas de largo.
Ahora, la barra de menú está justificada por el mismo algoritmo que usa el navegador para justificar el texto sin formato.
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>
Observación: ¿Notas que hice trampa? Para agregar el elemento de relleno de espacio, tengo que adivinar el ancho de la barra de menú. Por tanto, esta solución no se basa completamente en las reglas.
fuente
El texto solo se justifica si la oración provoca naturalmente un salto de línea. Entonces, todo lo que necesita hacer es forzar naturalmente un salto de línea y ocultar lo que está en la segunda línea:
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>
El elemento li. espacio adicional al final de su línea, y si no contiene contenido, entonces se ignora y la línea no está justificada.
Probado en IE7, IE8, IE9, Chrome, Firefox 4.
fuente
si ir con javascript es posible (este script se basa en 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>
y el 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>
y el ultimo 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>
fuente
Marcado más simple, probado en 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>
y 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; }
Ejemplo vivo .
fuente
Esto se puede lograr perfectamente mediante algunas medidas cuidadosas y el selector de último hijo.
ul li { margin-right:20px; } ul li:last-child { margin-right:0; }
fuente
Sé que la pregunta original especificaba HTML + CSS, pero no decía específicamente no javascript ;)
Tratando de mantener el CSS y el marcado lo más limpio posible, y lo más semánticamente significativo posible (usando un UL para el menú), se me ocurrió esta sugerencia. Probablemente no sea lo ideal, pero puede ser un buen punto 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>
fuente