wake-up-neo.com

Flexbox-Elemente zentrieren und nach rechts ausrichten

Ich möchte AB und C in der Mitte haben.

Wie kann ich D dazu bringen, ganz nach rechts zu gehen?

VOR:

 enter image description here

NACH DEM:

 enter image description here

Was ist die beste Vorgehensweise dafür?

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

62
hazyred

Im Folgenden sind fünf Optionen zum Erreichen dieses Layouts aufgeführt:

  • CSS-Positionierung 
  • Flexbox mit unsichtbarem DOM-Element
  • Flexbox mit unsichtbarem Pseudoelement
  • Flexbox mit flex: 1
  • CSS-Rasterlayout

Methode # 1: CSS-Positionierungseigenschaften

Tragen Sie position: relative auf den Flex-Container auf.

Übernehmen Sie position: absolute auf Punkt D.

Jetzt ist dieser Artikel absolut im Flexbehälter positioniert.

Insbesondere wird Element D aus dem Dokumentenfluss entfernt, bleibt jedoch innerhalb der Grenzen des nächstgelegenen Vorfahren .

Verwenden Sie die CSS-Offset-Eigenschaften top und right, um dieses Element in Position zu bringen.

li:last-child {
  position: absolute;
  top: 0;
  right: 0;
  background: #ddd;
}
ul {
  position: relative;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
  margin-top: 0;
}
span {
  background-color: aqua;
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>

Eine Einschränkung Bei dieser Methode werden einige Browser einen absolut positionierten Flex-Eintrag möglicherweise nicht vollständig aus dem normalen Fluss entfernen. Dies ändert die Ausrichtung auf eine nicht standardmäßige, unerwartete Weise. Weitere Details: In IE11 wird der absolut positionierte Flex-Artikel nicht aus dem normalen Fluss entfernt.


Methode 2: Flex Auto Margins & Invisible Flex-Element (DOM-Element)

Mit einer Kombination aus auto margin und einem neuen, unsichtbaren Flex-Element kann das Layout erreicht werden.

Der neue Flex-Artikel ist identisch mit Artikel D und befindet sich am gegenüberliegenden Ende (linker Rand).

Da die Flex-Ausrichtung auf der Verteilung des freien Raums basiert, ist das neue Element ein notwendiger Ausgleich, um die drei mittleren Felder horizontal zentriert zu halten. Das neue Element muss die gleiche Breite wie das vorhandene D-Element haben. Andernfalls werden die mittleren Felder nicht genau zentriert.

Das neue Element wird mit visibility: hidden aus der Ansicht entfernt.

Zusamenfassend:

  • Erstellen Sie ein Duplikat des Elements D.
  • Platziere es an den Anfang der Liste.
  • Verwenden Sie flexible auto-Ränder, um A, B und C zentriert zu halten, wobei beide D-Elemente das gleiche Gleichgewicht von beiden Enden erzeugen.
  • Anwenden von visibility: hidden auf das Duplikat D

li:first-child {
  margin-right: auto;
  visibility: hidden;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>D</li><!-- new; invisible spacer item -->
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Methode 3: Flex Auto Margins & Invisible Flex Item (Pseudoelement)

Diese Methode ist ähnlich zu # 2, außer dass sie semantisch sauberer ist und die Breite von D bekannt sein muss.

  • Erstellen Sie ein Pseudoelement mit derselben Breite wie D.
  • Platzieren Sie es mit ::before am Anfang des Containers.
  • Verwenden Sie flexible auto-Ränder, um A, B und C perfekt zentriert zu bleiben, wobei die Pseudo- und D-Elemente an beiden Enden die gleiche Balance erzeugen.

ul::before {
  content:"D";
  margin: 1px auto 1px 1px;
  visibility: hidden;
  padding: 5px;
  background: #ddd;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Methode # 4: Fügen Sie flex: 1 zu linken und rechten Elementen hinzu

Beginnen Sie mit Methode 2 oder 3 oben. Statt sich um die gleiche Breite für das linke und das rechte Element zu sorgen, um das gleiche Gleichgewicht zu erhalten, geben Sie einfach jedem flex: 1. Dies zwingt sie beide dazu, den verfügbaren Platz zu verbrauchen, wodurch das mittlere Element zentriert wird.

Sie können dann display: flex zu einzelnen Elementen hinzufügen, um deren Inhalt auszurichten.

NOTEüber die Verwendung dieser Methode mit min-height: In Chrome, Firefox, Edge und möglicherweise anderen Browsern wird die Abkürzungsregel flex: 1 folgendermaßen zusammengefasst:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

Diese Prozenteinheit (%) auf flex-basis führt dazu, dass diese Methode abgebrochen wird, wenn min-height für den Container verwendet wird. Dies liegt daran, dass in der Regel prozentuale Höhen für die untergeordneten Elemente eine explizite Einstellung der height-Eigenschaft für das übergeordnete Element erfordern.

Dies ist eine alte CSS-Regel aus dem Jahr 1998 ( CSS Level 2 ), die in manchen Browsern bis zu einem gewissen Grad noch gültig ist. Für vollständige Details siehe hier und hier .

Hier ist ein Beispiel für das Problem in den Kommentaren von user2651804 :

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container>div {
  background: orange;
  margin: 5px;
}

#flex-container>div:first-child {
  flex: 1;
}

#flex-container::after {
  content: "";
  flex: 1;
}
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>

Die Lösung besteht darin, die prozentuale Einheit nicht zu verwenden. Versuchen Sie px oder einfach gar nichts ( was die Spezifikation tatsächlich empfiehlt , obwohl zumindest einige der wichtigsten Browser aus irgendeinem Grund eine prozentuale Einheit angefügt haben).

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container > div {
  background: orange;
  margin: 5px;
}


/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */

#flex-container > div:first-child {
  flex: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex: 1;
  flex-basis: 0;
}


/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY

#flex-container > div:first-child {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
 */
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>


Methode # 5: CSS-Rasterlayout

Dies kann die sauberste und effizienteste Methode sein. Es besteht keine Notwendigkeit für absolute Positionierung, falsche Elemente oder andere Hacker.

Erstellen Sie einfach ein Raster mit mehreren Spalten. Positionieren Sie dann Ihre Artikel in der mittleren und unteren Spalte. Lassen Sie die erste Spalte einfach leer.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>

107
Michael_B

Sehr klare Frage. Ich konnte nicht anders, als die Antwort nach ein paar Stunden zu graben. Wir konnten das mit Tabellen, Tabellenzellen, absoluten Positionen, Transformationen lösen, aber wir mussten es nur mit Flexbox tun :)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd

3
rgfx

Wenn Sie eine Ausrichtung vornehmen möchten, können Sie einfach einen leeren Bereich anhängen und die drei untergeordneten Bereiche in diese Bereiche aufteilen.

1
Ali Korkmaz

Mit der Methode display:grid können Sie einfach alle ul Kinder in dieselbe Zelle einfügen und dann justify-self einstellen:

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>
0
Steven Spungin

Ich habe erweitert auf Michael_B 's Antwort

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

Hier mit der Hilfe von SASS als Codepen

0
yunzen