para - menu horizontal html sin css
¿Cómo justifico*realmente*un menú horizontal en HTML+CSS? (13)
Enfoque moderno - ¡ Flexboxes !
Ahora que las Flexboxes tienen una mejor compatibilidad con el navegador , algunos de nosotros finalmente podemos comenzar a utilizarlas. Simplemente agregue prefijos de proveedor adicionales para obtener más cobertura del navegador .
En este caso, simplemente establecería la display
del elemento principal en flex
y luego cambiaría la propiedad justify justify-content
a space-between
o space-around
para agregar espacio entre los elementos de los niños FlexBox.
Usando justify-content: space-between
- space-between :
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>
Usando justify-content: space-around
- space-around :
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>
Encontrará muchos tutoriales sobre las barras de menú en HTML, pero para este caso específico (aunque en mi humilde opinión genérico), no encontré ninguna solución decente:
# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE #
# ^ ^ #
- Hay una cantidad 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 se deben distribuir de manera óptima en la barra de menú.
- El número varía, por lo que no hay posibilidad de precalcular 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 alineó a la izquierda y alineó a la derecha el primer resp. los últimos elementos, el espaciado será subóptimo.
¿No es extraño que no haya una manera obvia de implementar esto de una manera limpia mediante el uso de HTML y CSS?
Conviértalo en <p>
con text-align: justify
?
Actualización : No importa. Eso no funciona en absoluto como pensé.
Actualización 2 : no funciona en ningún navegador que no sea IE en este momento, pero CSS3 tiene soporte para esto en la forma de text-align-last
El texto solo se justifica si la oración provoca naturalmente un salto de línea. Entonces, todo lo que tiene que hacer es forzar 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.break debe estar en la misma línea que el último elemento del menú y debe contener algo de contenido (en este caso, un espacio sin interrupción), de lo contrario, en algunos navegadores, si no está en la misma línea, verá algunos pequeños espacio extra al final de la línea, y si no contiene contenido, se ignora y la línea no está justificada.
Probado en IE7, IE8, IE9, Chrome, Firefox 4.
Esto se puede lograr perfectamente con algunas medidas cuidadosas y el selector de último hijo.
ul li {
margin-right:20px;
}
ul li:last-child {
margin-right:0;
}
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;
}
Lo más sencillo es forzar la línea para que se rompa al insertar un elemento al final de la línea que ocupará más que el espacio disponible de la izquierda y luego lo ocultará. Lo he logrado con bastante facilidad con un simple elemento span
como ese:
#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>
Toda la basura dentro del selector de #menu span
es (hasta donde he encontrado) requerida para la mayoría de los buscadores. Debería forzar el ancho del elemento span
al 100%, lo que debería causar un salto de línea ya que se considera un elemento en línea debido a la display: inline-block
regla de display: inline-block
. inline-block
también hace que el span
sea posible para las reglas de estilo de nivel de bloque, como el width
que hace que el elemento no encaje en línea con el menú y, por lo tanto, el menú al salto de línea.
Por supuesto, necesita ajustar el ancho del span
a su caso de uso y diseño, pero espero que tenga la idea general y pueda adaptarlo.
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;
}
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 un inline-block
es porque no quiero que las palabras adentro también estén justificadas, y tampoco quiero usar espacios sin separación.
Para los navegadores basados en Gecko, se me ocurrió esta solución. Sin embargo, esta solución no funciona con los navegadores WebKit (p. Ej., Chromium, Midori, Epiphany), aún muestran el espacio final después del último elemento.
Puse 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 amplio elemento invisible (por ejemplo, un img) que garantiza que el párrafo tiene al menos dos líneas de longitud.
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/-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: ¿Notaste que hice trampa? Para agregar el elemento de relleno de espacio, tengo que adivinar el ancho de la barra de menú. Entonces esta solución no depende completamente de las reglas.
Sé que la pregunta original especificaba HTML + CSS, pero no decía específicamente que no había javascript ;)
Tratando de mantener el CSS y el marcado lo más limpios posible, y lo más semánticamente posible (utilizando un UL para el menú), se me ocurrió esta sugerencia. Probablemente no sea 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>
Tengo una solución. Funciona en FF, IE6, IE7, Webkit, etc.
Asegúrese de no poner espacios en blanco antes de cerrar el span.inner
. IE6 se romperá.
Opcionalmente, puede otorgar .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>
otra solución más No tenía ninguna opción para abordar el html como agregar clase distinguida, etc., así que encontré un camino de CSS puro.
Funciona en Chrome, Firefox, Safari ... no sé acerca de 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>
si ir con javascript que es posible (este script está basado 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 ú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>