2011-02-25 16 views
17

Supongamos que necesita presentar una lista de colores para el usuario. Los colores se deben mostrar en una lista con una altura fija, con cada color ocupando una fracción igual de esa altura.Altura uniformemente distribuida de elementos secundarios con CSS

Esto es lo que debe ser similar con cuatro colores, una altura lista de 90 píxeles y un borde grueso alrededor:

Firefox

La imagen de arriba se representa en Firefox 3.6.13 de la fuente de seguimiento :

<ul style="height: 90px; border: 5px solid black; padding: 0;"> 
    <li style="height: 25%; background: red;"> 
    <li style="height: 25%; background: blue;"> 
    <li style="height: 25%; background: yellow;"> 
    <li style="height: 25%; background: green;"> 
</ul> 

Todo está bien. La lista es de hecho 90 píxeles de alto, dentro de los bordes, y cada color obtiene una parte (aparentemente) igual de este espacio. Ahora, vamos a convertir las mismas en HTML/CSS en Safari o Chrome:

Chrome

Aviso la fila blanca estrecha entre la fila verde y la frontera. Hay una explicación bastante simple para lo que estamos viendo aquí: 0.25 × 90 = 22.5

A WebKit en Safari y Chrome realmente no le gustan las alturas de píxeles no enteros y descarta el decimal. Con cuatro filas de altura 22 obtenemos 2 píxeles de nada en la parte inferior de la lista: 90 - 4 × 22 = 2

En el contexto de un archivo HTML estático, podríamos establecer fácilmente la altura de los elementos en 23, 22, 23, 23 píxeles respectivamente, y la lista se mostraría bien en cualquier navegador. Si, por otro lado, los colores se cargan desde una base de datos y el recuento varía con cada solicitud, se necesita una solución más flexible.

Sé cómo resolver esto calculando y estableciendo un alto de valor entero en cada fila onload usando Javascript, y publicaré esta solución si no aparece nada más. Sin embargo, preferiría una solución puramente basada en CSS para el problema. Puedes pensar en una?

+0

Se podría considerar hacer trampa y establecer el color de fondo del 'ul' al color de la última 'li'. – thirtydot

+2

[John Resig sobre el tema.] (Http://ejohn.org/blog/sub-pixel-problems-in-css/) – thirtydot

+0

@thirty Bueno, eso se vería bien por unas pocas filas. Con un mayor número de filas, la brecha acumulada puede crecer hasta una altura mayor que una sola fila. En tal caso, "extender" la última fila parecería extraño. –

Respuesta

-2

Intenta eliminar todas las líneas de extremo entre las etiquetas <li>. Por ej.

<ul><li></li><li></li></ul>

A veces esto era un problema, pero en su situación no estoy seguro de que ayudará;) acaba de dar una oportunidad;)

+3

Lo sentimos, pero en este caso, ese no es el problema. Estás pensando en 'display: inline-block'. (no mi downvote) – thirtydot

4

Según lo prometido, he aquí una solución Javascript para el problema . Todavía estoy muy interesado en una solución simple basada en CSS, pero mientras tanto, esta respuesta podría ayudar a otros a hacer su trabajo.

El script espera dos variables a ser declaradas en el punto de entrada: list debe apuntar al elemento DOM del contenedor (por ejemplo <ul>), y items a la colección de elementos (por ejemplo <li>) en esta lista.

La idea es establecer dinámicamente una altura explícita en píxeles en cada elemento, de forma que se garantice que la suma de las alturas sea igual a la altura del contenedor, permitiendo solo la mínima desviación de altura entre los elementos. Hacemos esto haciendo un bucle sobre los elementos, calculando una altura integral para cada uno, simplemente dividiendo el espacio disponible restante con la cantidad de elementos restantes para tener un conjunto de altura explícito.

var spaceRemaining = list.clientHeight; 
var itemsRemaining = items.length; 

while (itemsRemaining > 0) { 
    var itemHeight = Math.round(spaceRemaining/itemsRemaining); 
    items[itemsRemaining - 1].style.height = itemHeight; 
    spaceRemaining -= itemHeight; 
    itemsRemaining -= 1; 
} 

Para los que favorecen la concisión sobre la legibilidad, he aquí una versión más corta del mismo guión:

for (var space = list.clientHeight, i = items.length; i; i--) { 
    space -= items[i-1].style.height = Math.round(space/i); 
} 
+0

+1, me parece bien. Tal vez hagas un [jsFiddle] (http://jsfiddle.net/) ¿demostración? – thirtydot

Cuestiones relacionadas