Larghezza del fluido con DIV equidistanti


329

Ho un contenitore DIV a larghezza fluida.

All'interno di questo ho 4 DIV tutti 300px x 250px ...

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

Quello che voglio che succeda è che la casella 1 sia flottata a sinistra, la casella 4 sia flottata a destra e le caselle 2 e 3 siano distanziate uniformemente tra loro. Voglio che la spaziatura sia fluida così che il browser si riduca e anche lo spazio si riduca.

inserisci qui la descrizione dell'immagine


2
Perché non fare display:inline-block;invece di float?
Ayyp,

1
perché IE6 / IE7 supporta solo inline-blocksu inlineelementi
Lee Prezzo

Ok, non ero sicuro di quali browser stavi cercando.
Ayyp,

1
La soluzione più vicina a cui potevo pensare era quella di avvolgere ogni bambino .box div in un altro div con una larghezza del 25%. Quindi, centrare il div .box secondario sul wrapper. I div .box saranno distanziati in modo uniforme, ma i div sinistro e destro non saranno esattamente sul bordo.
Paul Sham,

5
Ho trasformato l'idea di Paul Sham in un JSFiddle .
Sparky

Risposte:


440

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

  • Funziona con IE6 + e tutti i browser moderni!
  • Ho dimezzato le dimensioni richieste solo per semplificare il lavoro.
  • text-align: justifycombinato con .stretchciò che gestisce il posizionamento.
  • display:inline-block; *display:inline; zoom:1correzioni inline-blockper IE6 / 7, vedere qui .
  • font-size: 0; line-height: 0 risolve un problema minore in 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>

Il extra span( .stretch) può essere sostituito con :after.

Questo funziona ancora in tutti gli stessi browser come la soluzione di cui sopra. :afternon funziona in IE6 / 7, ma lo usano distribute-all-linescomunque, quindi non importa.

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

C'è un piccolo aspetto negativo :after: per far funzionare perfettamente l'ultima riga in Safari, devi stare attento con lo spazio bianco nell'HTML.

In particolare, questo non funziona:

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

E questo fa:

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

Puoi usarlo per qualsiasi numero arbitrario di figli divsenza aggiungere una boxNclasse a ciascuno cambiando

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

per

#container > div { ...

Questo seleziona qualsiasi div che è il primo figlio del #containerdiv e nessun altro sotto di esso. Per generalizzare i colori di sfondo, è possibile utilizzare il selettore CSS3 di ordine inferiore , sebbene sia supportato solo in IE9 + e altri browser moderni:

.box1, .box3 { ...

diventa:

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

Vedi qui per un esempio di jsfiddle.


123
Mi ci sono voluti 3 ore per scoprire che dovresti avere spazi tra le caselle nel codice HTML. "Giustifica" estende gli spazi tra gli elementi e se i tuoi contenuti <div/><div/><div/>non funzionano. Devi avere <div/> <div/> <div/>.
venimus,

5
volevo solo notare che :) perché è difficile notare se lavori con un contenuto generato (che è il caso comune). Stavo pensando di utilizzare justifyper questo caso, ma grazie per fornire una soluzione funzionante. mi ha salvato un sacco di esperimenti (nonostante il debug 3h: D). Inoltre, potrei aggiungere una nota che se vuoi che la tua ultima riga sia allineata a sinistra, dovresti aggiungere alcune caselle extra invisibili (per completare la riga)
venimus,

4
@venimus: ho scritto un'altra risposta usando questa tecnica: stackoverflow.com/questions/10548417/… . Cosa hai fatto per sbarazzarti dell'altezza aggiuntiva causata dall'aggiunta di scatole invisibili?
trenta,

11
Qualcuno può spiegare perché è necessario .stretch?
atp

6
@HartleySan: .stretch/ :afterè necessario perché (in genere) con testo giustificato, l'ultima riga non è giustificata . Qui, vogliamo che l'ultima riga sia giustificata, quindi la necessità di :after. Per quanto riguarda la tua seconda domanda, l'ho esplorata qualche tempo fa in una risposta precedente . In quella risposta, era richiesto JavaScript. Se devi supportare i browser più vecchi (IE8), credo che tu abbia bisogno di JavaScript.
trenta,

140

Il modo più semplice per farlo ora è con un flexbox:

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

Il CSS è quindi semplicemente:

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

demo: http://jsfiddle.net/QPrk3/

Tuttavia , questo è attualmente supportato solo da browser relativamente recenti ( http://caniuse.com/flexbox ). Inoltre, le specifiche per il layout di flexbox sono cambiate alcune volte, quindi è possibile coprire più browser includendo inoltre una sintassi precedente:

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

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


1
Grazie per questo, così facile, l'ho applicato a quattro liste anche distanziate in un piè di pagina fissato in fondo a una pagina. Ha funzionato a meraviglia in FF28.0, Chrome 34.0.1847.116 me IE11.
user1063287

1
Flexbox non è lo strumento più supportato in tutto il Web e non batte l'approccio classico di margine e padding.
TheBlackBenzKid,

Per tutti coloro che cercano di giustificare più div con larghezza non definita: utilizzare flex-wrap con display: opzione flex. Avvolge div con larghezza dinamica.
Kamil Budziewski,

20

Se css3 è un'opzione, questo può essere fatto usando la calc()funzione css .

Caso 1: giustificare le caselle su una sola riga ( FIDDLE )

Il markup è semplice: un gruppo di div con qualche elemento contenitore.

CSS assomiglia a questo:

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

dove -1px per correggere un bug di IE9 + calc / rounding - vedi qui

Caso 2: giustificazione di caselle su più righe ( FIDDLE )

Qui, oltre alla calc()funzione, media queriessono necessari.

L'idea di base è quella di impostare una media query per ogni stato #columns, dove uso quindi calc () per calcolare il margine destro su ciascuno degli elementi (eccetto quelli nell'ultima colonna).

Sembra un sacco di lavoro, ma se stai usando LESS o SASS questo può essere fatto abbastanza facilmente

(Può ancora essere fatto con i normali CSS, ma poi dovrai fare tutti i calcoli manualmente, e quindi se cambi la larghezza della tua scatola, devi elaborare di nuovo tutto)

Di seguito è riportato un esempio usando MENO: (Puoi copiare / incollare questo codice qui per giocarci, [è anche il codice che ho usato per generare il violino sopra menzionato])

@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;
    }
}

Quindi, in sostanza, devi prima decidere una larghezza della scatola e un margine minimo che desideri tra le scatole.

Con ciò, puoi capire di quanto spazio hai bisogno per ogni stato.

Quindi, utilizza calc () per calcolare il margine destro e nth-child per rimuovere il margine destro dalle caselle nella colonna finale.

Il vantaggio di questa risposta rispetto alla risposta accettata che utilizza text-align:justifyè che quando si dispone di più di una riga di caselle - le caselle nell'ultima riga non vengono "giustificate", ad esempio: se sono rimaste 2 caselle nell'ultima riga - I non voglio che la prima casella sia a sinistra e la successiva a destra, ma piuttosto che le caselle si susseguano in ordine.

Per quanto riguarda il supporto del browser : questo funzionerà su IE9 +, Firefox, Chrome, Safari6.0 + - (vedi qui per maggiori dettagli) Tuttavia ho notato che su IE9 + c'è un piccolo problema tra gli stati delle query multimediali. [se qualcuno sa come risolvere questo mi piacerebbe davvero saperlo :)] <- RISOLTO QUI


13

Altri post hanno menzionato flexbox , ma se è necessaria più di una riga di elementi , la space-betweenproprietà di flexbox non riesce (vedere la fine del post)

Ad oggi, l'unica soluzione pulita per questo è con il

Modulo layout griglia CSS ( codepen demo )

Fondamentalmente il codice pertinente necessario si riduce a questo:

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) Trasforma l'elemento contenitore in un contenitore griglia

2) Imposta la griglia con una quantità "automatica" di colonne, se necessario. Questo viene fatto per layout reattivi. La larghezza di ogni colonna sarà 120px. (Nota l'uso di auto-fit(come apposto a auto-fill) che (per un layout a 1 riga) comprime le tracce vuote su 0 - consentendo agli elementi di espandersi per occupare lo spazio rimanente. (Dai un'occhiata a questa demo per vedere di cosa sto parlando )).

3) Impostare spazi / grondaie per le righe e le colonne della griglia - qui, poiché si desidera un layout "spazio tra" - lo spazio sarà effettivamente uno spazio minimo perché crescerà secondo necessità.

4) e 5) - Simile 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>

Demo Codepen (ridimensiona per vedere l'effetto)


Supporto per browser - Caniuse

Attualmente supportato da Chrome (Blink), Firefox, Safari ed Edge! ... con il supporto parziale di IE (vedi questo post di Rachel Andrew)


NB:

La space-betweenproprietà di Flexbox funziona benissimo per una fila di oggetti, ma quando applicata a un contenitore flessibile che avvolge i suoi oggetti (con flex-wrap: wrap) - fallisce, perché non hai alcun controllo sull'allineamento dell'ultima fila di oggetti; l'ultima riga sarà sempre giustificata (di solito non è quello che vuoi)

Dimostrare:

Codepen (ridimensiona per vedere di cosa sto parlando)


Ulteriori letture sulle griglie CSS:


1
Risposta molto sottovalutata. Questo era il modo più semplice ed efficace per ottenere ciò che volevo fare. Grazie.
Barnaby Mercer,

1
Questa era la più piccola quantità di CSS (e non JS!) Che produceva esattamente il comportamento che stavo cercando, con qualche modifica per dimensioni e spazio.
EKW,

1
Lo cerco da un po 'e finalmente l'ho trovato !. Grazie @Danield
nareeboy,

2

Questo ha funzionato per me con 5 immagini di dimensioni diverse.

  1. Crea un div contenitore
  2. Un elenco non ordinato per le immagini
  3. Su CSS i non ordinati devono essere visualizzati in verticale e senza proiettili
  4. Giustifica il contenuto del contenitore div

Questo funziona a causa del contenuto giustificato: spazio tra, ed è in un elenco, visualizzato in orizzontale.

Su CSS

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

Su 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>

Anche se questo codice potrebbe funzionare, una buona risposta dovrebbe includere una spiegazione di come funziona e perché è una buona soluzione.
Blackwood,

Vale la pena notare che flexbox non è (o solo parzialmente) supportato da IE caniuse.com/#feat=flexbox
David Salamon,

è reattivo?
stackdave,

1

in jQueryte potresti indirizzare direttamente il genitore.

QUESTO È UTILE SE NON CONOSCI ESATTAMENTE QUANTI BAMBINI VERRANNO AGGIUNTI DINAMICAMENTE o SE NON PUOI ESSERE ADEGUATO IL LORO NUMERO.

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);

Ciò consentirà di parentcrescere orizzontalmente man mano che childrenvengono aggiunti.

NOTA: ciò presuppone che '.children'abbiano a widthe HeightSet

Spero che aiuti.


1

Se si conosce il numero di elementi per "riga" e la larghezza del contenitore, è possibile utilizzare un selettore per aggiungere un margine agli elementi necessari per creare un aspetto giustificato.

Avevo file di tre div che volevo giustificate, quindi ho usato:

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

ciò consente al div centrale di ogni riga di avere un margine che forza il 1 ° e il 3 ° div ai bordi esterni del contenitore

Ottimo anche per altre cose come i colori di sfondo dei bordi ecc

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.