javascript - que - Distribuye los elementos uniformemente usando CSS
obtener el texto de un elemento con javascript (13)
A pesar de que la respuesta de Colin Brogan proporciona una base sólida para abordar una resolución "casi" del problema, aún depende de la longitud del texto. Si el texto es demasiado largo, la "celda" será más ancha y, por lo tanto, tendrá más espacio a la izquierda. Intenté abordar el problema basándose en el código presentado en su respuesta, pero llegué a la conclusión de que el problema no tiene una solución real posible con tablas o tablas falsas (pantalla: tabla-celda).
Así que tendremos que esperar a que el modelo de caja flexible CSS3 sea más compatible (puede consultar el soporte actualizado here ). Mientras tanto, puede utilizar el polyfill Flexie para parchar los navegadores que no lo admiten. Si desea comprobar cómo se verá ahora en WebKit (sin necesidad de polyfill), puede probar el siguiente CSS:
#menu ul {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: justify;
width: 940px;
list-style: none;
padding: 0;
border: 1px solid gray;
}
#menu li {
border: 1px solid silver;
}
Note que solo usa prefijos de WebKit. También debe agregar prefijos para los otros navegadores si decide llevarlo al sitio web de producción.
Este enfoque acepta una cantidad desconocida de elementos y anchos de texto, sin ningún conocimiento de sus anchos reales , y los distribuye uniformemente en su contenedor (en este caso, #menu ul
).
Si decides ser conservador, el enfoque sugerido por Colin Brogan es el más aceptable dado que mantienes tus textos en la misma extensión aproximadamente. Si no, comenzarán a aparecer espacios más amplios.
Un método para distribuir elementos de manera uniforme en un contenedor utilizando CSS apareció hoy en la revista Smashing .
Hace poco tuve que usar Javascript para lograr el mismo efecto para elementos de ancho variable, pero el método presentado en SM me hizo preguntarme si era posible hacerlo sin Javascript.
Hay esta pregunta , donde dice la gargantaun :
En mi humilde opinión, y probablemente no quiera escuchar esto, pero el diseño es probablemente defectuoso. Es de conocimiento general que la distribución de elementos de manera uniforme en un diseño con CSS es una molestia, por lo que los diseñadores deben evitarlo.
Pero no puedo decirle al diseñador que cambie su diseño, y no estoy de acuerdo con que las limitaciones de CSS deban limitar a los diseñadores.
De todos modos, esto es lo que tengo en HTML (traducido y simplificado):
<div id="menu">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/news">News</a></li>
<li><a href="/theme">Theme</a></li>
<li><a href="/activities">Activities</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
en CSS (propiedades irrelevantes eliminadas y simplificadas):
#menu li { float: left; margin-right: 20px; }
#menu a { display: block; padding: 0 1em; }
y en Javascript:
function justifyMenu() {
var menuItems = $$("#menu li");
var menuWidth = $("menu").getWidth();
var totalWidth = 0;
menuItems.each(function(e) {
totalWidth += e.getWidth();
});
var margin = (menuWidth - 4 - totalWidth) / (menuItems.length - 1);
margin = parseInt(margin);
menuItems.each(function(e) {
e.setStyle({ marginRight: margin + ''px'' });
});
menuItems[menuItems.length - 1].setStyle({ marginRight: ''0'' });
}
Y aquí hay una captura de pantalla reducida (vea cómo el menú se alinea con la imagen del encabezado):
captura de pantalla http://i41.tinypic.com/2ntguf8.png
¿Alguna idea de cómo puedo lograr esto sin Javascript?
AFAIK no hay manera de lograr esto solo con CSS. Alguien me corrige si esto está mal, por favor.
Aquí está el código en formato jQuery para cualquier persona que lo encuentre útil
function justifyClients() {
var menuItems = $("#clients-wrapper ul li").get();
var menuWidth = $("#clients-wrapper ul").width();
var totalWidth = 0;
$("#clients-wrapper ul li").each(function(i,e)
{
totalWidth += $(e).width();
});
var margin = (menuWidth - 4 - totalWidth) / ($("#clients-wrapper ul li").length - 1);
margin = parseInt(margin);
$("#clients-wrapper ul li").each(function(i,e) {
if(i < $("#clients-wrapper ul li").length - 1)
{
alert(i + " " + $("#clients-wrapper ul li").length);
$(e).css(''margin-right'', margin);
}
});
}
$(document).ready(function() {
justifyClients();
});
Demostración: http://codepen.io/vsync/pen/tFwxu
todo lo que necesita si desea que la propia lista se text-align:justify
y luego agregue algunos pseudo elementos al final de la misma y hágala llenar todo el ancho, para engañar a la lista para que justifique todos sus elementos en todo su ancho.
Esto es lo que se debe lograr con la pantalla: table-cell - sin embargo, el IE simplemente no lo hace, y FF <3 también tiene problemas con él, creo.
Estos estilos funcionan en FF3, Chrome, Safari y (creo) Opera 9:
#menu ul {display:table;padding:0;}
#menu li {display:table-cell;text-align:center;}
Pero necesitará algunos trucos para que funcionen en el conjunto de navegadores comerciales habituales.
Gracias al módulo Flexbox de CSS3 , esto es posible con dos líneas de CSS.
Compruebe la tabla de compatibilidad del navegador para Flexbox
HTML
<div id="menu">
<ul>
<li><a href="/">Home</a>
</li>
<li><a href="/news">News</a>
</li>
<li><a href="/theme">Theme</a>
</li>
<li><a href="/activities">Activities</a>
</li>
<li><a href="/contact">Contact</a>
</li>
</ul>
</div>
CSS
ul {
display: flex;
}
li {
flex: 1; /* Short hand for flex-grow: 1 and flex-shrink: 1 */
}
Salida:
ul, li {
margin: 0;
padding: 0;
}
ul {
display: flex;
list-style: none;
}
li {
flex: 1;
text-align: center;
}
<div id="menu">
<ul>
<li><a href="/">Home</a>
</li>
<li><a href="/news">News</a>
</li>
<li><a href="/theme">Theme</a>
</li>
<li><a href="/activities">Activities</a>
</li>
<li><a href="/contact">Contact</a>
</li>
</ul>
</div>
Ha habido afirmaciones casuales de que las tablas son la solución obvia, sin embargo, no ha habido ninguna discusión real sobre cómo implementarla. Les mostraré que mostrar divs como una tabla es la forma correcta de hacerlo, pero no es tan fácil como centrar todas las celdas y establecer un ancho automático. El problema con esto es que no tiene control de los márgenes exteriores de los contenidos de celda más a la izquierda y a la derecha. Ambos están inserta de su caja contenedora una cantidad arbitraria que no puede controlar. Aquí hay un trabajo alrededor de:
Primero, una ligera modificación del html de Guder:
<div id="menu">
<ul>
<li class="left"><a href="/">Home</a></li>
<li><a href="/news">News</a></li>
<li><a href="/theme">Theme</a></li>
<li><a href="/activities">Activities</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
Ahora el css:
#menu {display:table; width:// some width in px //}
#menu ul {display:table-row; width: 100%}
#menu li.left {display: table-cell; text-align: left; width: 20px; white-space:nowrap;}
#menu li {display: table-cell; text-align: right; width: auto;}
Ahora, tenemos el control total de los lados más externos del menú, que se alinean con los lados del extremo izquierdo y del extremo derecho del cuadro que contiene, y la distancia entre cada elemento es constante. Notarás que usé un truco para obtener la celda izquierda más alejada para que tenga el ancho exacto de su contenido. Establecí la propiedad de ancho a un tamaño pequeño obviamente debajo de lo que normalmente sería su contenido. A continuación, configuro el espacio en blanco para no envolver, lo que estira la celda lo menos posible para que se ajuste al texto de la celda. Aquí puede ver una imagen que muestra el efecto de esto (utilizando diferentes elementos html):
La belleza de este código es que puede aceptar sin embargo muchas celdas y anchos de texto, sin ningún conocimiento de sus anchos reales, y distribuirlos uniformemente en toda la página. Mientras tanto, los elementos de la izquierda y la derecha alcanzan sus perímetros y, por supuesto, tenemos todos nuestros html en divs, ningún navegador o geek de Internet es engañoso para creer que estamos presentando datos tabulares. No hay compromisos conocidos aquí!
La respuesta principal no funcionó para mí, y la respuesta de GarciaWebDev no lo hará para mí todavía porque necesito admitir algunos otros navegadores, incluido IE8.
Este método funcionó para mí. La idea es hacer que un elemento que contiene el texto se alinee: justificar y hacer que los elementos para distribuir se muestren: bloque en línea.
HTML:
<div id="menu">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/news">News</a></li>
<li><a href="/theme">Theme</a></li>
<li><a href="/activities">Activities</a></li>
<li><a href="/contact">Contact</a></li>
<li class="filler"></li>
</ul>
</div>
CSS:
#menu {
text-align: justify;
}
ul {
margin: 0;
padding: 0;
}
#menu li {
display: inline-block;
}
.filler {
width: 100%;
height: 0;
}
Por supuesto, esto es exactamente para lo que sirve el elemento de tabla . Es triste e hilarante al mismo tiempo ver a las personas convertirse en un nudo gordiano con CSS, la mayoría de ellos ni siquiera saben por qué están evitando las mesas.
Cualquiera sea la razón por la que haya imaginado rechazar las tablas, no puede ser peor que depender de Javascript para diseñar su página.
Sí, ya sé que esta no es la respuesta que buscabas, pero claro, es tan obvia .
Sí, puede hacerlo, siempre que se conozcan de antemano los anchos de los elementos a distribuir. Pero es un poco desordenado.
El truco es que desea un espacio entre cada elemento de ''(Wp-sum (Wc)) / (Nc-1)'', que es el ancho del elemento padre menos el ancho total de todos los elementos secundarios, dividido igualmente entre los Número de huecos entre los elementos.
Debido a que CSS no tiene la capacidad de hacer expresiones, tenemos que hackearlo un poco. Primero, agregamos un margen al elemento principal del tamaño ''suma (Wc)'', el ancho total de todos los elementos secundarios. Así que ahora el padre tiene un ancho ''(Wp-sum (Wc))'', y podemos usar un valor de relleno en% relativo a ese ancho.
Así, por ejemplo, para cuatro imágenes de tamaños 10px, 20px, 40px y 80px respectivamente, nuestra ''suma (Wc)'' es de 150px. Establézcalo como el margen primario, entonces los hijos pueden tener un tercio de ese ancho como relleno entre ellos.
<style type="text/css">
#nava { width: 10px; height: 20px;}
#navb { width: 20px; height: 20px;}
#navc { width: 40px; height: 20px;}
#navd { width: 80px; height: 20px;}
#nav { margin-right: 150px; white-space: nowrap; }
#nava, #navb, #navc { padding-right: 33.3%; }
</style>
<div id="nav"
><img id="nava" src="nava.png" alt="a"
><img id="navb" src="navb.png" alt="b"
><img id="navc" src="navc.png" alt="c"
><img id="navd" src="navd.png" alt="d"
></div>
La sangría de la etiqueta divertida es evitar que haya espacios en blanco entre las imágenes. ''nowrap'' es necesario porque con el ancho principal establecido más estrecho que el ancho de la página, de lo contrario no sería posible ajustar todos los elementos en la fila. Finalmente, en IE es posible que necesite agregar una división de envoltura alrededor del lote con ''ancho: 100%; desbordamiento: oculto ''para evitar barras de desplazamiento no deseadas si abarca toda la página. Y ciertamente querrás estar en Modo Estándar.
Esto también puede funcionar con elementos textuales, si los hace bloques en línea para que pueda agregar relleno, y los dimensione explícitamente en ems. No funcionará si los tamaños de los elementos secundarios no se conocen de antemano (por ejemplo, contienen contenido dinámico), ya que no sabrá el valor de ''suma (Wc)'' que debe usar.
Para ser honesto, probablemente solo usaría una mesa. El algoritmo de diseño de tabla se adapta muy bien al cálculo de cómo distribuir el ancho de la tabla de repuesto. (Use ''diseño de tabla: fijo'' para obtener mejores resultados con celdas de ancho conocido, o ''automático'' para responder a los contenidos dinámicos.) De esta manera, tampoco tiene que preocuparse por los errores de redondeo de píxeles.
Si estuvieras usando tamaños basados en texto (ej. Ej.) Sería mucho más fácil. A continuación, puede tratar en letras en lugar de píxeles.
Ejemplo: Todo el asunto es de 30 mayúsculas de ancho. Luego puede usar el ancho de cada elemento de navegación (en función de su contenido textual) y hacer sus cálculos estáticos desde allí.
Si usas el Yahoo! Biblioteca de interfaz de usuario (YUI) grids.css , podría funcionar.
Variante mejorada de Trevor Dixon (sin extra <li>
)
HTML
<ul>
<li><a href="/">Home</a></li>
<li><a href="/news">News</a></li>
<li><a href="/theme">Theme</a></li>
<li><a href="/activities">Activities</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
CSS
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
text-align: justify;
}
ul:after{
display: inline-block;
content: '''';
width: 100%;
height: 0;
}