Halten Sie das mittlere Element zentriert, wenn die seitlichen Elemente unterschiedliche Breiten haben


161

Geben Sie hier die Bildbeschreibung ein

Stellen Sie sich das folgende Layout vor, in dem die Punkte den Abstand zwischen den Feldern darstellen:

[Left box]......[Center box]......[Right box]

Wenn ich die rechte Box entferne, möchte ich, dass sich die mittlere Box immer noch in der Mitte befindet, wie folgt:

[Left box]......[Center box].................

Das gleiche gilt, wenn ich die linke Box entfernen würde.

................[Center box].................

Wenn der Inhalt in der mittleren Box länger wird, nimmt er so viel verfügbaren Speicherplatz wie nötig ein, während er zentriert bleibt. Die linke und rechte Feld wird nie schrumpfen und somit , wenn , wo kein Platz links overflow:hiddenund text-overflow: ellipsiskommt in der Tat um den Inhalt zu brechen;

[Left box][Center boxxxxxxxxxxxxx][Right box]

All dies ist meine ideale Situation, aber ich habe keine Ahnung, wie ich diesen Effekt erzielen kann. Denn wenn ich so eine flexible Struktur erstelle:

.parent {
    display : flex; // flex box
    justify-content : space-between; // horizontal alignment
    align-content   : center; // vertical alignment
}

Wenn das linke und das rechte Feld genau die gleiche Größe haben, erhalte ich den gewünschten Effekt. Wenn jedoch einer der beiden eine andere Größe hat, ist die zentrierte Box nicht mehr wirklich zentriert.

Gibt es jemanden, der mir helfen kann?

Aktualisieren

A justify-selfwäre schön, das wäre ideal:

.leftBox {
     justify-self : flex-start;
}

.rightBox {
    justify-self : flex-end;
}

3
Grundsätzlich ... kannst du nicht. So soll das nicht flexboxfunktionieren. Sie könnten eine andere Methode ausprobieren.
Paulie_D

1
Würde die Flexbox wirklich vervollständigen, wenn es so wäre. Bei flexbox dreht sich alles um die Verteilung des Speicherplatzes und das Verhalten der Elemente innerhalb der Datei.
Mark

1
Wir justify-selfhaben heute früher darüber gesprochen, daher könnte dies interessant sein: stackoverflow.com/questions/32551291/…
Michael Benjamin

Antworten:


130

Wenn das linke und das rechte Feld genau die gleiche Größe haben, erhalte ich den gewünschten Effekt. Wenn jedoch eine der beiden eine andere Größe hat, ist die zentrierte Box nicht mehr wirklich zentriert. Gibt es jemanden, der mir helfen kann?

Hier ist eine Methode, bei der Flexbox verwendet wird, um das mittlere Element unabhängig von der Breite der Geschwister zu zentrieren.

Hauptmerkmale:

  • reines CSS
  • keine absolute Positionierung
  • keine JS / jQuery

Verwenden Sie verschachtelte Flex-Container und autoRänder:

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}

.box:first-child > span { margin-right: auto; }

.box:last-child  > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
p {
  text-align: center;
  margin: 5px 0 0 0;
}
<div class="container">
  <div class="box"><span>short text</span></div>
  <div class="box"><span>centered text</span></div>
  <div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>&#8593;<br>true center</p>

So funktioniert das:

  • Das oberste div ( .container) ist ein Flex-Container.
  • Jedes untergeordnete div ( .box) ist jetzt ein flexibles Element.
  • Jeder .boxArtikel wird angegeben, flex: 1um den Containerraum gleichmäßig zu verteilen ( weitere Details ).
  • Jetzt belegen die Elemente den gesamten Platz in der Reihe und sind gleich breit.
  • Machen Sie aus jedem Element einen (verschachtelten) Flex-Container und fügen Sie ihn hinzu justify-content: center.
  • Jetzt ist jedes spanElement ein zentriertes Flex-Element.
  • Verwenden Sie flexible autoRänder, um die äußeren spans nach links und rechts zu verschieben.

Sie können auch ausschließlich auf Ränder verzichten justify-contentund diese verwenden auto.

Aber justify-contentkönnen hier arbeiten , weil die autoMargen immer Vorrang haben.

8.1. An den auto Rändern ausrichten

Vor der Ausrichtung über justify-contentund align-selfwird jeder positive freie Speicherplatz an die automatischen Ränder in dieser Dimension verteilt.


5
Diese Lösung lässt sich nicht widthspezifizieren
Alex G

@AlexG, wie so? Können Sie ein Beispiel geben?
Michael Benjamin

4
Das Ändern der Breite der gebogenen Elemente, um den Raum gleichmäßig zu verteilen, lässt die Frage von OP völlig außer Acht. Ihre Frage hat Raum zwischen Elementen. Beispiel: "Stellen Sie sich das folgende Layout vor, in dem die Punkte den Abstand zwischen den Feldern darstellen." Das Zentrieren von Text in 3 gleichmäßig großen Elementen ist trivial.
Leland

1
Ich schwöre, ich könnte dich jetzt einfach küssen! Dies ist genau das, was ich brauchte und nicht herausfinden konnte.
EliotRosewater

1
Dies hat genau das getan, was ich für die Implementierung von Fenstertitelleisten im MacOS-Stil benötigte. Das Hinzufügen white-space: nowrapwar das letzte Puzzleteil, um zu verhindern, dass Text umbrochen wird, wenn der Bereich zu klein wird.
Geo1088

32
  1. Verwenden Sie drei flexible Gegenstände im Behälter
  2. Stellen Sie flex: 1den ersten und den letzten ein. Dadurch wachsen sie gleichmäßig, um den verfügbaren Platz des mittleren zu füllen.
  3. Daher wird der mittlere tendenziell zentriert sein.
  4. Wenn jedoch das erste oder letzte Element einen breiten Inhalt hat, wächst dieses flexible Element aufgrund des neuen min-width: autoAnfangswertes ebenfalls.

    Hinweis Chrome scheint dies nicht richtig zu implementieren. Sie können jedoch min-widthauf -webkit-max-contentoder einstellen -webkit-min-contentund es wird auch funktionieren.

  5. Nur in diesem Fall wird das mittlere Element aus der Mitte herausgeschoben.

.outer-wrapper {
  display: flex;
}
.item {
  background: lime;
  margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
  flex: 1;
  display: flex;
  min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
  justify-content: flex-end;
}
.animate {
  animation: anim 5s infinite alternate;
}
@keyframes anim {
  from { min-width: 0 }
  to { min-width: 100vw; }
}
<div class="outer-wrapper">
  <div class="left inner-wrapper">
    <div class="item animate">Left</div>
  </div>
  <div class="center inner-wrapper">
    <div class="item">Center</div>
  </div>
  <div class="right inner-wrapper">
    <div class="item">Right</div>
  </div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>


Vielen Dank, diese Antwort beantwortet erfolgreich die Frage des OP, im Gegensatz zu der akzeptierten Antwort
Blowsie

8

Anstatt standardmäßig Flexbox zu verwenden, wird die Verwendung von Grid in zwei CSS-Zeilen ohne zusätzliches Markup innerhalb der untergeordneten Elemente der obersten Ebene gelöst.

HTML:

<header class="header">
  <div class="left">variable content</div>
  <div class="middle">variable content</div>
  <div class="right">variable content which happens to be very long</div>
</header>

CSS:

.header {
  display: grid;
  grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
  /* use either */
  margin: 0 auto;
  /* or */
  text-align: center;
}

Flexbox rockt, sollte aber nicht die Antwort auf alles sein. In diesem Fall ist das Gitter eindeutig die sauberste Option.

Sogar einen Codepen für Ihr Testvergnügen erstellt: https://codepen.io/anon/pen/mooQOV


2
+1 für das Eingestehen, dass es andere Optionen als flexfür alles geben kann. Mein einziger Einwand ist, dass die vertikale Ausrichtung mit flex ( align-items: center) einfacher wird, falls Ihre Artikel unterschiedliche Höhen haben und ausgerichtet werden müssen
Felipe

1
Ich mag diese Lösung und die Idee, Grid für dieses Problem zu verwenden, aber ich denke, Ihre Lösung hat einige bemerkenswerte Nachteile. Erstens, wenn einer der Inhalte der äußeren Zellen größer als 20% ist, wird der Inhalt entweder in die mittlere Zelle gewickelt oder läuft über. Zweitens, wenn das Zentrum größer als 60% ist, wächst es außerhalb des Inhaltsfelds und wickelt die letzte Zelle entweder ein oder schiebt sie heraus. Schließlich verschiebt sich das Zentrum nicht, um Platz für die äußeren Zellen zu schaffen. Es zwingt sie nur zum Wickeln / Überlaufen. Es ist keine schlechte Lösung, aber IMO, es ist nicht "eindeutig die sauberste Option".
Chris

6

Sie können dies folgendermaßen tun:

.bar {
    display: flex;    
    background: #B0BEC5;
}
.l {
    width: 50%;
    flex-shrink: 1;
    display: flex;
}
.l-content {
    background: #9C27B0;
}
.m { 
    flex-shrink: 0;
}
.m-content {    
    text-align: center;
    background: #2196F3;
}
.r {
    width: 50%;
    flex-shrink: 1;
    display: flex;
    flex-direction: row-reverse;
}
.r-content { 
    background: #E91E63;
}
<div class="bar">
    <div class="l">
        <div class="l-content">This is really long content.  More content.  So much content.</div>
    </div>
    <div class="m">
        <div class="m-content">This will always be in the center.</div>
    </div>
    <div class="r">
        <div class="r-content">This is short.</div>
    </div>
</div>


2

Hier ist eine Antwort, die Raster anstelle von Flexbox verwendet. Diese Lösung erfordert keine zusätzlichen Enkelelemente im HTML wie die akzeptierte Antwort. Und es funktioniert auch dann richtig, wenn der Inhalt auf einer Seite lang genug ist, um in die Mitte zu gelangen, im Gegensatz zur Rasterantwort von 2019.

Das einzige, was diese Lösung nicht tut, ist, Auslassungspunkte anzuzeigen oder den zusätzlichen Inhalt im mittleren Feld auszublenden, wie in der Frage beschrieben.

section {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}

section > *:last-child {
  white-space: nowrap;
  text-align: right;
}

/* not essential; just for demo purposes */
section {
  background-color: #eee;
  font-family: helvetica, arial;
  font-size: 10pt;
  padding: 4px;
}

section > * {
  border: 1px solid #bbb;
  padding: 2px;
}
<section>
  <div>left</div>
  <div>center</div>
  <div>right side is longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer, super long in fact</div>
</section>


0

Sie können auch diese einfache Methode verwenden, um die exakte Mittelausrichtung für das mittlere Element zu erreichen:

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

.container .sibling {
    display: flex;
    align-items: center;
    height: 50px;
    background-color: gray;
}

.container .sibling:first-child {
    width: 50%;
    display: flex;
    justify-content: space-between;
}

.container .sibling:last-child {
    justify-content: flex-end;
    width: 50%;
    box-sizing: border-box;
    padding-left: 100px; /* .center's width divided by 2 */
}

.container .sibling:last-child .content {
    text-align: right;
}

.container .sibling .center {
    height: 100%;
    width: 200px;
    background-color: lightgreen;
    transform: translateX(50%);
}

Codepen: https://codepen.io/ErAz7/pen/mdeBKLG


0

Hier ist eine andere Möglichkeit, dies display: flexbei Eltern und Kindern zu tun :

.Layout{
    display: flex;
    justify-content: center;
}
.Left{
    display: flex;
    justify-content: flex-start;
    width: 100%;
}
.Right{
    display: flex;
    justify-content: flex-end;
    width: 100%;
}
<div class = 'Layout'>
    <div class = 'Left'>I'm on the left</div>
    <div class = 'Mid'>Centered</div>
    <div class = 'Right'>I'm on the right</div>
</div>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.