Ancho de fluido con DIVs igualmente espaciados

329

Tengo un contenedor de ancho de fluido DIV.

Dentro de esto tengo 4 DIVs todos 300px x 250px ...

<div id="container">
   <div class="box1"> </div>
   <div class="box2"> </div>
   <div class="box3"> </div>
   <div class="box4"> </div>
</div>

Lo que quiero que suceda es que la casilla 1 se haga flotar a la izquierda, la casilla 4 se flote a la derecha y las casillas 2 y 3 se separen de manera uniforme entre ellas. Quiero que el espaciado sea fluido también para que el navegador se haga más pequeño y el espacio también se haga más pequeño.

ingrese la descripción de la imagen aquí

Lee Price
fuente
2
¿Por qué no hacer en display:inline-block;lugar de flotar?
ayyp
1
porque IE6 / IE7 sólo admite inline-blocken inlinelos elementos
Lee Precio
De acuerdo, no estaba seguro de qué navegadores estabas buscando.
ayyp
1
La solución más cercana que se me ocurrió fue envolver cada div .box secundario en otro div de 25% de ancho. Luego, centre el niño .box div en la envoltura. Los div .box estarán espaciados de manera uniforme, pero los div izquierdo y derecho no estarán directamente en el borde.
Paul Sham
55
Hice la idea de @Paul Sham en un JSFiddle .
Sparky

Respuestas:

440

Ver: http://jsfiddle.net/thirtydot/EDp8R/

  • ¡Esto funciona en IE6 + y en todos los navegadores modernos!
  • Reduje a la mitad las dimensiones solicitadas solo para facilitar el trabajo.
  • text-align: justifycombinado con .stretches lo que está manejando el posicionamiento.
  • display:inline-block; *display:inline; zoom:1correcciones inline-blockpara IE6 / 7, ver aquí .
  • font-size: 0; line-height: 0 soluciona un problema menor en IE6.

#container {
  border: 2px dashed #444;
  height: 125px;
  text-align: justify;
  -ms-text-justify: distribute-all-lines;
  text-justify: distribute-all-lines;
  /* just for demo */
  min-width: 612px;
}

.box1,
.box2,
.box3,
.box4 {
  width: 150px;
  height: 125px;
  vertical-align: top;
  display: inline-block;
  *display: inline;
  zoom: 1
}

.stretch {
  width: 100%;
  display: inline-block;
  font-size: 0;
  line-height: 0
}

.box1,
.box3 {
  background: #ccc
}

.box2,
.box4 {
  background: #0ff
}
<div id="container">
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="box3"></div>
  <div class="box4"></div>
  <span class="stretch"></span>
</div>

El extra span( .stretch) se puede reemplazar con :after.

Esto todavía funciona en los mismos navegadores que la solución anterior. :afterno funciona en IE6 / 7, pero están usando de distribute-all-linestodos modos, por lo que no importa.

Ver: http://jsfiddle.net/thirtydot/EDp8R/3/

Hay un inconveniente menor para :after: para que la última fila funcione perfectamente en Safari, debes tener cuidado con el espacio en blanco en el HTML.

Específicamente, esto no funciona:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div>
</div>

Y esto hace:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div></div>

Puede usar esto para cualquier número arbitrario de niños divsin agregar una boxNclase a cada uno cambiando

.box1, .box2, .box3, .box4 { ...

a

#container > div { ...

Esto selecciona cualquier div que sea el primer hijo del #containerdiv, y ningún otro debajo de él. Para generalizar los colores de fondo, puede usar el selector de enésimo orden CSS3 , aunque solo es compatible con IE9 + y otros navegadores modernos:

.box1, .box3 { ...

se convierte en:

#container > div:nth-child(odd) { ...

Vea aquí un ejemplo de jsfiddle.

Thirtydot
fuente
123
Me tomó 3 horas para encontrar que debería tener espacios entre cada cuadro en el html. "Justificar" extiende los espacios entre los elementos y si su contenido es <div/><div/><div/>, no funciona. Usted necesita tener <div/> <div/> <div/>.
venimus
55
solo quería señalar eso :) porque es difícil de notar si trabajas con un contenido generado (que es el caso común). Estaba pensando en usar justifypara tal caso, pero gracias por proporcionar una solución de trabajo. Me ahorró muchos experimentos (a pesar de la depuración de 3h: D). Además, podría agregar una nota de que si desea que su última fila quede alineada, debe agregar algunos cuadros invisibles adicionales (para completar la fila)
venimus
44
@venimus: escribí otra respuesta usando esta técnica: stackoverflow.com/questions/10548417/… . ¿Qué hiciste para deshacerte de la altura adicional causada al agregar cajas invisibles?
thirtydot
11
¿Alguien puede explicar por qué es necesario el estiramiento?
atp
66
@HartleySan: El .stretch/ :afteres necesario porque (normalmente) con texto justificado, la última línea no está justificada . Aquí, queremos que la última línea esté justificada, de ahí la necesidad :after. En cuanto a su segunda pregunta, exploré eso hace un tiempo en una respuesta anterior . En esa respuesta, se requería JavaScript. Si necesita admitir navegadores antiguos (IE8), creo que necesita JavaScript.
Thirtydot
140

La forma más fácil de hacer esto ahora es con un flexbox:

http://css-tricks.com/snippets/css/a-guide-to-flexbox/

El CSS es simplemente:

#container {
    display: flex;
    justify-content: space-between;
}

demostración: http://jsfiddle.net/QPrk3/

Sin embargo , actualmente solo es compatible con navegadores relativamente recientes ( http://caniuse.com/flexbox ). Además, la especificación para el diseño de flexbox ha cambiado varias veces, por lo que es posible cubrir más navegadores incluyendo adicionalmente una sintaxis anterior:

http://css-tricks.com/old-flexbox-and-new-flexbox/

http://css-tricks.com/using-flexbox/

Ben Jackson
fuente
1
Gracias por esto, tan fácil, lo apliqué a cuatro listas espaciadas en un pie de página fijo en la parte inferior de una página. Trabajó un placer en FF28.0, Chrome 34.0.1847.116 my IE11.
user1063287
1
Flexbox no es la herramienta más compatible en la web y no supera el enfoque clásico de margen y relleno.
TheBlackBenzKid
Para todos los que buscan justificar múltiples divs con ancho no definido: use flex-wrap con display: opción flex. Envolverá divs con ancho dinámico.
Kamil Budziewski
20

Si css3 es una opción, esto se puede hacer usando la calc()función css .

Caso 1: Justificar cuadros en una sola línea ( FIDDLE )

El marcado es simple: un montón de divs con algún elemento contenedor.

CSS se ve así:

div
{
    height: 100px;
    float: left;
    background:pink;
    width: 50px;
    margin-right: calc((100% - 300px) / 5 - 1px); 
}
div:last-child
{
    margin-right:0;
}

donde -1px para corregir un error de IE9 + calc / redondeo - ver aquí

Caso 2: Justificación de cuadros en varias líneas ( FIDDLE )

Aquí, además de la calc()función, media queriesson necesarios.

La idea básica es configurar una consulta de medios para cada #columnas de estados, donde luego uso calc () para calcular el margen derecho de cada uno de los elementos (excepto los de la última columna).

Esto parece mucho trabajo, pero si está usando MENOS o SASS, esto se puede hacer con bastante facilidad.

(Todavía se puede hacer con CSS normal, pero luego tendrá que hacer todos los cálculos manualmente, y luego, si cambia el ancho de su caja, tendrá que resolver todo de nuevo)

A continuación se muestra un ejemplo usando MENOS: (Puede copiar / pegar este código aquí para jugar con él, [también es el código que usé para generar el violín mencionado anteriormente])

@min-margin: 15px;
@div-width: 150px;

@3divs: (@div-width * 3);
@4divs: (@div-width * 4);
@5divs: (@div-width * 5);
@6divs: (@div-width * 6);
@7divs: (@div-width * 7);

@3divs-width: (@3divs + @min-margin * 2);
@4divs-width: (@4divs + @min-margin * 3);
@5divs-width: (@5divs + @min-margin * 4);
@6divs-width: (@6divs + @min-margin * 5);
@7divs-width: (@7divs + @min-margin * 6);


*{margin:0;padding:0;}

.container
{
    overflow: auto;
    display: block;
    min-width: @3divs-width;
}
.container > div
{
    margin-bottom: 20px;
    width: @div-width;
    height: 100px;
    background: blue;
    float:left;
    color: #fff;
    text-align: center;
}

@media (max-width: @3divs-width) {
    .container > div {  
        margin-right: @min-margin;
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @3divs-width) and (max-width: @4divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{3divs})/2 - 1px)";
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @4divs-width) and (max-width: @5divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{4divs})/3 - 1px)";
    }
    .container > div:nth-child(4n) {  
        margin-right: 0;
    }
}

@media (min-width: @5divs-width) and (max-width: @6divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{5divs})/4 - 1px)";
    }
    .container > div:nth-child(5n) {  
        margin-right: 0;
    }
}

@media (min-width: @6divs-width){
    .container > div {  
        margin-right: ~"calc((100% - @{6divs})/5 - 1px)";
    }
    .container > div:nth-child(6n) {  
        margin-right: 0;
    }
}

Entonces, básicamente, primero debe decidir el ancho de la caja y el margen mínimo que desea entre las cajas.

Con eso, puede calcular cuánto espacio necesita para cada estado.

Luego, use calc () para calcular el margen derecho y nth-child para eliminar el margen derecho de los cuadros en la columna final.

La ventaja de esta respuesta sobre la respuesta aceptada que utiliza text-align:justifyes que cuando tiene más de una fila de casillas, las casillas de la fila final no se 'justifican', por ejemplo: si quedan 2 casillas en la fila final: I no quiero que el primer cuadro esté a la izquierda y el siguiente a la derecha, sino que los cuadros se sucedan en orden.

Con respecto al soporte del navegador : Esto funcionará en IE9 +, Firefox, Chrome, Safari6.0 + - (vea aquí para más detalles) Sin embargo, noté que en IE9 + hay un pequeño problema entre los estados de consulta de medios. [si alguien sabe cómo solucionar esto, me gustaría saber :)] <- FIJO AQUÍ

Danield
fuente
13

Otras publicaciones han mencionado flexbox , pero si se necesita más de una fila de elementos , la space-betweenpropiedad de flexbox falla (ver el final de la publicación)

Hasta la fecha, la única solución limpia para esto es con el

Módulo de diseño de cuadrícula CSS ( demostración de Codepen )

Básicamente, el código relevante necesario se reduce a esto:

ul {
  display: grid; /* (1) */
  grid-template-columns: repeat(auto-fit, 120px); /* (2) */
  grid-gap: 1rem; /* (3) */
  justify-content: space-between; /* (4) */
  align-content: flex-start; /* (5) */
}

1) Haga que el elemento contenedor sea un contenedor de cuadrícula

2) Establezca la cuadrícula con una cantidad 'automática' de columnas, según sea necesario. Esto se hace para diseños receptivos. El ancho de cada columna será de 120px. (Tenga en cuenta el uso de auto-fit(según lo indicado auto-fill) que (para un diseño de 1 fila) contrae las pistas vacías a 0, lo que permite que los elementos se expandan para ocupar el espacio restante. (Consulte esta demostración para ver de qué estoy hablando )).

3) Establezca espacios / canales para las filas y columnas de la cuadrícula, aquí, dado que desea un diseño de 'espacio intermedio', el espacio en realidad será un espacio mínimo porque crecerá según sea necesario.

4) y 5) - Similar a flexbox.

body {
  margin: 0;
}
ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, 120px);
  grid-gap: 1rem;
  justify-content: space-between;
  align-content: flex-start;
  
  /* boring properties: */
  list-style: none;
  width: 90vw;
  height: 90vh;
  margin: 2vh auto;
  border: 5px solid green;
  padding: 0;
  overflow: auto;
}
li {
  background: tomato;
  height: 120px;
}
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Codepen demo (Cambiar tamaño para ver el efecto)


Soporte de navegador - Caniuse

Actualmente compatible con Chrome (Blink), Firefox, Safari y Edge. ... con apoyo parcial de IE (Ver esta publicación de Rachel Andrew)


NÓTESE BIEN:

La space-betweenpropiedad de Flexbox funciona muy bien para una fila de elementos, pero cuando se aplica a un contenedor flexible que envuelve sus elementos, (con flex-wrap: wrap), falla porque no tiene control sobre la alineación de la última fila de elementos; la última fila siempre estará justificada (generalmente no es lo que quieres)

Demostrar:

Codepen (Cambiar el tamaño para ver de qué estoy hablando)


Lecturas adicionales sobre cuadrículas CSS:

Danield
fuente
1
Respuesta muy subestimada. Esta fue la forma más simple y efectiva de lograr lo que quería hacer. Gracias.
Barnaby Mercer
1
Esta fue la cantidad más pequeña de CSS (¡y no JS!) Que produjo exactamente el comportamiento que estaba buscando, con algunos ajustes de tamaño y espacio.
EKW
1
He estado buscando esto por un tiempo y finalmente lo encontré. Gracias @Danield
nareeboy
2

Esto funcionó para mí con 5 imágenes en diferentes tamaños.

  1. Crear un contenedor div
  2. Una lista desordenada para las imágenes.
  3. En css lo no ordenado debe mostrarse verticalmente y sin viñetas
  4. Justificar el contenido del contenedor div

Esto funciona debido a justify-content: space-between, y está en una lista, que se muestra horizontalmente.

En CSS

 #container {
            display: flex;
            justify-content: space-between;
 }
    #container ul li{ display:inline; list-style-type:none;
}

En html

<div id="container"> 
  <ul>  
        <li><img src="box1.png"><li>
        <li><img src="box2.png"><li>
        <li><img src="box3.png"><li>
        <li><img src="box4.png"><li>
        <li><img src="box5.png"><li>
    </ul>
</div>
Sebastián Brun Valiente
fuente
Si bien este código puede funcionar, una buena respuesta incluiría una explicación de cómo funciona y por qué es una buena solución.
Blackwood
Vale la pena señalar que flexbox no es (o solo parcialmente) compatible con IE caniuse.com/#feat=flexbox
David Salamon
¿Es esto receptivo?
stackdave
1

en jQueryusted puede apuntar al padre directamente.

ESTO ES ÚTIL SI NO SABE EXACTAMENTE CUÁNTOS NIÑOS SERÁN AGREGADOS DINÁMICAMENTE O SI NO PUEDE RESULTAR SU NÚMERO.

var tWidth=0;

$('.children').each(function(i,e){
tWidth += $(e).width();

///Example: If the Children have a padding-left of 10px;..
//You could do instead:
tWidth += ($(e).width()+10);

})
$('#parent').css('width',tWidth);

Esto permitirá que parentcrezca horizontalmente a medida que childrense agreguen beng.

NOTA: Esto asume que el '.children'tener una widthy HeightSet

Espero que ayude.

ErickBest
fuente
1

Si conoce el número de elementos por "fila" y el ancho del contenedor, puede usar un selector para agregar un margen a los elementos que necesita para causar una apariencia justificada.

Tenía filas de tres divs que quería justificar, así que utilicé:

.tile:nth-child(3n+2) { margin: 0 10px }

Esto permite que el centro div en cada fila tenga un margen que fuerce el 1 ° y 3 ° div a los bordes exteriores del contenedor

También es ideal para otras cosas como bordes, colores de fondo, etc.

Dave Robertson
fuente