Flüssigkeitsbreite mit gleichmäßig verteilten DIVs

328

Ich habe einen Behälter mit Flüssigkeitsbreite DIV.

Innerhalb dieser habe ich 4 DIVs alle 300px x 250px ...

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

Was ich tun möchte, ist, dass Box 1 nach links schwebt, Box 4 nach rechts schwebt und Box 2 und 3 gleichmäßig zwischen ihnen verteilt werden. Ich möchte, dass der Abstand auch flüssig ist, damit der Browser kleiner wird, wenn der Browser kleiner wird.

Geben Sie hier die Bildbeschreibung ein

Lee Price
quelle
2
Warum nicht display:inline-block;statt schweben?
Ayyp
1
weil IE6 / IE7 unterstützt nur inline-blockauf inlineElemente
Lee Price
Okay, ich war mir nicht sicher, für welche Browser Sie sich entschieden haben.
Ayyp
1
Die beste Lösung, die ich mir vorstellen konnte, war, jedes untergeordnete .box-Div in ein anderes Div mit einer Breite von 25% zu verpacken. Zentrieren Sie dann die untergeordnete .box div auf dem Wrapper. Die .box-Divs sind gleichmäßig verteilt, aber die linken und rechten Divs befinden sich nicht direkt am Rand.
Paul Sham
5
Ich habe @Paul Shams Idee zu einer JSFiddle gemacht .
Sparky

Antworten:

439

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

  • Dies funktioniert in IE6 + und allen modernen Browsern!
  • Ich habe Ihre gewünschten Abmessungen halbiert, um die Arbeit zu erleichtern.
  • text-align: justifykombiniert mit .stretchist das, was die Positionierung handhabt.
  • display:inline-block; *display:inline; zoom:1Korrekturen inline-blockfür IE6 / 7 finden Sie hier .
  • font-size: 0; line-height: 0 behebt ein kleines Problem 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>

Das extra span( .stretch) kann durch ersetzt werden :after.

Dies funktioniert immer noch in allen Browsern wie die obige Lösung. :afterfunktioniert nicht in IE6 / 7, aber sie verwenden es distribute-all-linestrotzdem, also spielt es keine Rolle.

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

Es gibt einen kleinen Nachteil :after: Damit die letzte Zeile in Safari einwandfrei funktioniert, müssen Sie mit den Leerzeichen im HTML-Code vorsichtig sein.

Insbesondere funktioniert dies nicht:

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

Und das tut:

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

Sie können dies für eine beliebige Anzahl von Kindern verwenden, divohne boxNjeder Klasse eine Klasse hinzuzufügen , indem Sie sie ändern

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

zu

#container > div { ...

Dies wählt jedes Div aus, das das erste Kind des #containerDiv ist, und keine anderen darunter. Um die Hintergrundfarben zu verallgemeinern, können Sie den CSS3-Selektor n-ter Ordnung verwenden , obwohl er nur in IE9 + und anderen modernen Browsern unterstützt wird:

.box1, .box3 { ...

wird:

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

Sehen Sie hier für ein jsfiddle Beispiel.

dreißig Punkte
quelle
123
Ich habe 3 Stunden gebraucht, um herauszufinden, dass zwischen den einzelnen Feldern im HTML Leerzeichen stehen sollten. "Ausrichten" erweitert Leerzeichen zwischen den Elementen und wenn Ihr Inhalt vorhanden ist <div/><div/><div/>, funktioniert er nicht. Sie müssen haben <div/> <div/> <div/>.
Venimus
5
Ich wollte das nur beachten :), weil es schwer zu bemerken ist, wenn Sie mit einem generierten Inhalt arbeiten (was der übliche Fall ist). Ich habe überlegt, justifyfür einen solchen Fall zu verwenden, aber ich danke Ihnen, dass Sie eine funktionierende Lösung bereitstellen. hat mir viele Experimente erspart (trotz des 3h Debugging: D). Zusätzlich könnte ich eine Notiz hinzufügen, dass, wenn Sie möchten, dass Ihre letzte Reihe
linksbündig
4
@venimus: Ich habe eine andere Antwort mit dieser Technik geschrieben: stackoverflow.com/questions/10548417/… . Was haben Sie getan, um die zusätzliche Höhe durch Hinzufügen unsichtbarer Kisten zu beseitigen?
dreißig Punkte
11
Kann jemand erklären, warum die .stretch notwendig ist?
atp
6
@HartleySan: Das .stretch/ :afterwird benötigt, da (normalerweise) bei gerechtfertigtem Text die letzte Zeile nicht gerechtfertigt ist . Hier wollen wir, dass die letzte Zeile gerechtfertigt ist, daher die Notwendigkeit für :after. Was Ihre zweite Frage betrifft, habe ich dies vor einiger Zeit in einer früheren Antwort untersucht . In dieser Antwort war JavaScript erforderlich. Wenn Sie ältere Browser (IE8) unterstützen müssen, benötigen Sie meines Erachtens JavaScript.
30.
140

Der einfachste Weg, dies jetzt zu tun, ist mit einer Flexbox:

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

Das CSS ist dann einfach:

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

Demo: http://jsfiddle.net/QPrk3/

Dies wird derzeit jedoch nur von relativ neuen Browsern ( http://caniuse.com/flexbox ) unterstützt. Außerdem wurde die Spezifikation für das Flexbox-Layout einige Male geändert, sodass mehr Browser abgedeckt werden können, indem zusätzlich eine ältere Syntax hinzugefügt wird:

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

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

Ben Jackson
quelle
1
Vielen Dank dafür, so einfach, dass ich es auf vier Listen mit gleichmäßigem Abstand in einer Fußzeile angewendet habe, die am Ende einer Seite fixiert ist. Arbeitete eine Belohnung in FF28.0, Chrome 34.0.1847.116 m und IE11.
user1063287
1
Flexbox ist nicht das am meisten unterstützte Tool im Web und übertrifft nicht den klassischen Ansatz von Rand und Polsterung.
TheBlackBenzKid
Für alle, die mehrere Divs mit nicht definierter Breite rechtfertigen möchten: Verwenden Sie die Option Flex-Wrap mit Anzeige: Flex. Divs werden mit dynamischer Breite umbrochen.
Kamil Budziewski
20

Wenn CSS3 eine Option ist, kann dies mit der CSS- calc()Funktion erfolgen.

Fall 1: Ausrichten von Feldern in einer einzelnen Zeile ( FIDDLE )

Markup ist einfach - eine Reihe von Divs mit einem Containerelement.

CSS sieht folgendermaßen aus:

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

wo -1px , um einen IE9 + Calc / Rounding-Fehler zu beheben - siehe hier

Fall 2: Ausrichten von Feldern in mehreren Zeilen ( FIDDLE )

Hier sind neben der calc()Funktion media queriesauch notwendig.

Die Grundidee besteht darin, eine Medienabfrage für jeden # columns-Status einzurichten, in der ich dann calc () verwende, um den rechten Rand für jedes der Elemente (mit Ausnahme der Elemente in der letzten Spalte) zu ermitteln.

Das klingt nach viel Arbeit, aber wenn Sie WENIGER oder SASS verwenden, kann dies ganz einfach durchgeführt werden

(Es kann immer noch mit normalem CSS durchgeführt werden, aber dann müssen Sie alle Berechnungen manuell durchführen. Wenn Sie dann Ihre Boxbreite ändern, müssen Sie alles erneut ausarbeiten.)

Unten ist ein Beispiel mit WENIGER: (Sie können diesen Code hier kopieren / einfügen, um damit zu spielen. [Es ist auch der Code, mit dem ich die oben erwähnte Geige generiert habe.])

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

Grundsätzlich müssen Sie also zunächst eine Boxbreite und einen Mindestabstand zwischen den Boxen festlegen.

Damit können Sie herausfinden, wie viel Speicherplatz Sie für jeden Status benötigen.

Verwenden Sie dann calc (), um den rechten Rand zu berechnen, und nth-child, um den rechten Rand aus den Feldern in der letzten Spalte zu entfernen.

Der Vorteil dieser Antwort gegenüber der akzeptierten Antwort, die verwendet text-align:justifywird, besteht darin, dass bei mehr als einer Reihe von Feldern die Felder in der letzten Zeile nicht "gerechtfertigt" werden, z. B.: Wenn in der letzten Zeile noch 2 Felder vorhanden sind - I. Ich möchte nicht, dass das erste Feld links und das nächste rechts angezeigt wird, sondern dass die Felder der Reihe nach aufeinander folgen.

In Bezug auf die Browserunterstützung : Dies funktioniert unter IE9 +, Firefox, Chrome, Safari6.0 + - (siehe hier für weitere Details). Ich habe jedoch festgestellt, dass unter IE9 + ein gewisser Fehler zwischen den Status der Medienabfrage besteht. [Wenn jemand weiß, wie man das behebt, würde ich es gerne wissen :)] <- HIER BEHOBEN

Danield
quelle
13

Andere Beiträge haben Flexbox erwähnt , aber wenn mehr als eine Reihe von Elementen erforderlich ist , schlägt die space-betweenEigenschaft von Flexbox fehl (siehe Ende des Beitrags).

Bisher ist die einzige saubere Lösung dafür die mit dem

CSS-Grid-Layout-Modul ( Codepen-Demo )

Grundsätzlich läuft der relevante Code darauf hinaus:

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) Machen Sie das Containerelement zu einem Gittercontainer

2) Stellen Sie das Raster nach Bedarf mit einer 'automatischen' Anzahl von Spalten ein. Dies erfolgt für reaktionsschnelle Layouts. Die Breite jeder Spalte beträgt 120 Pixel. (Beachten Sie die Verwendung von auto-fit(wie angegeben auto-fill), die (für ein 1-Zeilen-Layout) leere Spuren auf 0 reduziert, sodass die Elemente erweitert werden können, um den verbleibenden Platz einzunehmen. ( Sehen Sie sich diese Demo an, um zu sehen, wovon ich spreche )).

3) Legen Sie Lücken / Rinnen für die Rasterzeilen und -spalten fest - da hier ein Zwischenraum-Layout gewünscht wird, ist die Lücke tatsächlich eine minimale Lücke, da sie nach Bedarf wächst.

4) und 5) - Ähnlich wie bei der 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 (Größe ändern, um den Effekt zu sehen)


Browser-Unterstützung - Caniuse

Derzeit unterstützt von Chrome (Blink), Firefox, Safari und Edge! ... mit teilweiser Unterstützung von IE (siehe diesen Beitrag von Rachel Andrew)


NB:

Die space-betweenEigenschaft von Flexbox eignet sich hervorragend für eine Elementreihe. Wenn sie jedoch auf einen Flex-Container angewendet wird, der die Elemente umschließt (mit flex-wrap: wrap), schlägt dies fehl, da Sie keine Kontrolle über die Ausrichtung der letzten Elementreihe haben. Die letzte Zeile ist immer gerechtfertigt (normalerweise nicht das, was Sie wollen).

Demonstrieren:

Codepen (Größe ändern, um zu sehen, wovon ich spreche)


Weitere Informationen zu CSS-Grids:

Danield
quelle
1
Sehr unterschätzte Antwort. Dies war der einfachste und effektivste Weg, um das zu erreichen, was ich tun wollte. Vielen Dank.
Barnaby Mercer
1
Dies war die kleinste Menge an CSS (und kein JS!), Die genau das Verhalten erzeugte, das ich suchte, mit einigen Anpassungen an Größe und Platz.
EKW
1
Ich habe eine Weile danach gesucht und es endlich gefunden!. Vielen Dank @Danield
Nareeboy
2

Dies funktionierte bei mir mit 5 Bildern in verschiedenen Größen.

  1. Erstellen Sie einen Container div
  2. Eine ungeordnete Liste für die Bilder
  3. Auf CSS muss das nicht geordnete vertikal und ohne Aufzählungszeichen angezeigt werden
  4. Begründen Sie den Inhalt des Containers div

Dies funktioniert aufgrund von Begründungsinhalten: Leerzeichen dazwischen und in einer Liste, die horizontal angezeigt wird.

Auf CSS

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

Auf 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
quelle
Obwohl dieser Code möglicherweise funktioniert, enthält eine gute Antwort eine Erklärung, wie er funktioniert und warum er eine gute Lösung ist.
Blackwood
Es ist erwähnenswert, dass Flexbox nicht (oder nur teilweise) von IE caniuse.com/#feat=flexbox
David Salamon
reagiert das?
Stackdave
1

in können jQuerySie den Elternteil direkt ansprechen.

Dies ist nützlich, wenn Sie nicht genau wissen, wie viele Kinder dynamisch hinzugefügt werden, oder wenn Sie ihre Nummer nicht herausfinden können.

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

Dadurch kann parentdas childrenProdukt horizontal wachsen, wenn es hinzugefügt wird.

HINWEIS: Dies setzt voraus, dass die '.children'a widthund HeightSet haben

Ich hoffe, das hilft.

ErickBest
quelle
1

Wenn Sie die Anzahl der Elemente pro "Zeile" und die Breite des Containers kennen, können Sie mit einem Selektor den Elementen, die Sie für ein gerechtfertigtes Aussehen benötigen, einen Rand hinzufügen.

Ich hatte Reihen von drei Divs, die ich begründen wollte, also benutzte ich:

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

Dadurch kann das mittlere Div in jeder Reihe einen Rand haben, der das 1. und 3. Div an die Außenkanten des Containers drückt

Ideal auch für andere Dinge wie Rahmenhintergrundfarben usw.

Dave Robertson
quelle