So zentrieren Sie einen Flex-Container, aber richten Sie Flex-Elemente nach links aus

90

Ich möchte, dass die Flex-Elemente zentriert sind, aber wenn wir eine zweite Zeile haben, müssen 5 (aus dem Bild unten) unter 1 und nicht im übergeordneten Element zentriert sein.

Geben Sie hier die Bildbeschreibung ein

Hier ist ein Beispiel für das, was ich habe:

ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: 0;
}
li {
  list-style-type: none;
  border: 1px solid gray;
  margin: 15px;
  padding: 5px;
  width: 200px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

http://jsfiddle.net/8jqbjese/2/

Etienne Noël
quelle

Antworten:

78

Flexbox Challenge & Limitation

Die Herausforderung besteht darin, eine Gruppe von Flex-Elementen zu zentrieren und sie beim Wickeln linksbündig auszurichten. Dies ist derzeit mit der Flexbox nicht möglich, es sei denn, es gibt eine feste Anzahl von Boxen pro Zeile und jede Box hat eine feste Breite.

Mit dem in der Frage angegebenen Code könnten wir einen neuen Flex-Container erstellen, der den aktuellen Flex-Container ( ul) umschließt, sodass wir den ulmit zentrieren können justify-content: center.

Dann ulkönnten die Flex-Elemente des linksbündig ausgerichtet werden justify-content: flex-start.

#container {
    display: flex;
    justify-content: center;
}

ul {
    display: flex;
    justify-content: flex-start;
}

Dadurch wird eine zentrierte Gruppe von linksbündigen Flex-Elementen erstellt.

Das Problem bei dieser Methode ist, dass bei bestimmten Bildschirmgrößen rechts vom eine Lücke vorhanden ist ul, die nicht mehr zentriert erscheint.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Dies liegt daran, dass im Flex-Layout (und tatsächlich in CSS im Allgemeinen) der Container:

  1. weiß nicht, wann ein Element umbrochen wird;
  2. weiß nicht, dass ein zuvor besetzter Raum jetzt leer ist, und
  3. berechnet seine Breite nicht neu, um das schmalere Layout zu verkleinern.

Die maximale Länge des Leerzeichens rechts entspricht der Länge des Flex-Elements, das der Container erwartet hatte.

In der folgenden Demo können Sie durch horizontale Größenänderung des Fensters sehen, wie das Leerzeichen kommt und geht.

DEMO


Ein praktischerer Ansatz

Das gewünschte Layout kann ohne Flexbox-Verwendung inline-blockund Medienabfragen erreicht werden .

HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

CSS

ul {
    margin: 0 auto;                  /* center container */
    width: 1200px;
    padding-left: 0;                 /* remove list padding */
    font-size: 0;                    /* remove inline-block white space;
                                        see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 18px;                 /* restore font size removed in container */
    list-style-type: none;
    width: 150px;
    height: 50px;
    line-height: 50px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

Der obige Code rendert einen horizontal zentrierten Container mit linksbündigen untergeordneten Elementen wie folgt:

Geben Sie hier die Bildbeschreibung ein

DEMO


Andere Optionen

Michael Benjamin
quelle
3
Ja, viele Dinge, für die die Leute Flexbox verwenden möchten, sind eigentlich nur das Erstellen eines Rasters. Glücklicherweise wird dies von CSS Grids abgedeckt, wenn diese Reichweiten endgültiger sind.
TylerH
1
Verknüpfte diesen Beitrag mit Ihrem. Ich habe noch eine Version darin, wie man das gleiche Problem löst. Trotzdem könnte es ein Betrug sein. Schauen Sie also selbst und entscheiden Sie selbst, ob Sie es als solches schließen möchten. Und plus 1 für die großartige Erklärung.
Ason
Möglicherweise besteht eine andere Idee darin, margin:0 autoeinen übergeordneten Wrapper zu verwenden, damit alles auf der Seite zentriert ist. Ab diesem Zeitpunkt führen alle untergeordneten Komponenten (dh der erste Flex-Container) nur noch den normalen Ablauf der Zeilen aus? Scheint so, als könnte dies einfach gemacht werden.
Klewis
11

Sie können es mit CSS Grid erreichen, verwenden Sie einfach repeat(autofit, minmax(width-of-the-element, max-content))

ul {
       display: grid;
       grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
       grid-gap: 16px;
       justify-content: center;
       padding: initial;
}

li {
    list-style-type: none;
    border: 1px solid gray;
    padding: 5px;
    width: 210px;
}
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>

http://jsfiddle.net/rwa20jkh/

Joe82
quelle
Interessant. Aber beseitigt nicht die Lücke rechts oder zentriert das Gitter
Rot
2
@ Red Da war eine Sache falsch. Ich wechselte justify-items: centerzu justify-content:center, und jetzt ist es die Mitte perfekt.
Joe82
Ich verstehe den 210pxTeil darin nicht minmax. Wie mache ich das gleiche aber ohne künstliche Einschränkung von 210px? Bei Flexbox gibt es keine solche Einschränkung. Ich möchte genau das gleiche Ergebnis wie bei der Flexbox, aber der Inhaltsbereich muss wie in Ihrer Lösung zentriert sein.
Andrey Mikhaylov - lolmaus
1
Hallo @ AndreyMikhaylov-lolmaus, diese Methode funktioniert, wenn Sie für alle Elemente eine feste Breite festlegen möchten. In der Frage wird es ausgedrückt als width:200px, und in meinem Beispiel, wie ich es gesetzt habe width:210px, muss ich das auch in dem minmaxTeil
hinzufügen
@ Joe82 Danke für die Klarstellung! 🙏 Kennen Sie eine Möglichkeit, wie es für Elemente mit beliebiger Breite funktioniert?
Andrey Mikhaylov - lolmaus
0

Wie @michael vorgeschlagen hat, ist dies eine Einschränkung bei der aktuellen Flexbox. Wenn Sie jedoch weiterhin flexund verwenden möchten, justify-content: center;können Sie dies umgehen, indem Sie ein Dummy- liElement hinzufügen und zuweisen margin-left.

    const handleResize = () => {
        const item_box = document.getElementById('parentId')
        const list_length  = item_box.clientWidth
        const product_card_length = 200 // length of your child element
        const item_in_a_row = Math.round(list_length/product_card_length)
        const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
        const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin 
        const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
        dummy_product.style.marginLeft = `${left_to_set}px`
    }
    handleResize() // Call it first time component mount
    window.addEventListener("resize", handleResize); 

Überprüfen Sie diese Geige (Größe ändern und sehen) oder Video als Referenz

RameshVel
quelle
0

Eine Möglichkeit, den gewünschten Stil mit Rändern zu erhalten, besteht darin, Folgendes zu tun:

#container {
    display: flex;
    justify-content: center;
}

#innercontainer {
    display: flex;
    flex: 0.9; -> add desired % of margin
    justify-content: flex-start;
}
Patrik Rikama-Hinnenberg
quelle
0

Sie können unsichtbare Elemente mit derselben Klasse wie die anderen platzieren (zum Beispiel zu Ausstellungszwecken entfernt) und die Höhe auf 0 setzen. Auf diese Weise können Sie die Elemente bis zum Anfang des Rasters ausrichten.

Beispiel

<div class="table-container">
  <div class="table-content">
    <p class="table-title">Table 1</p>
    <p class="mesa-price">$ 20</p>
  </div>
  
  <!-- Make stuff justified start -->
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>

Ergebnis

Geben Sie hier die Bildbeschreibung ein

Arthur Serafim
quelle
-1

Beim Codieren mit React Native bin ich auf dieses Problem gestoßen. Es gibt eine elegante Lösung, die Sie mit FlexBox haben können. In meiner speziellen Situation habe ich versucht, drei Flexboxen (Flex: 2) mithilfe von alignItems in einer anderen zu zentrieren. Die Lösung, die ich gefunden habe, bestand darin, zwei leere s mit jeweils Flex: 1 zu verwenden.

<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
  <View style={{flex: 1}} />
    // Content here
  <View style={{flex: 1}} />
</View>

Einfach genug, um in Web / CSS zu konvertieren.

Schriftfamilie
quelle
Sie haben die Frage falsch verstanden. Das OP fragt nicht, wie 3 Elemente zentriert werden sollen, sondern wie Elemente links in einer zweiten Reihe ausgerichtet werden sollen, während alle Elemente als Gruppe zentriert werden. Daher funktioniert Ihre Lösung nicht.
Ason