Verständnis von flex-grow, flex-shrink und flex-basis

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Wenn Sie eine CSS-Eigenschaft auf ein Element anwenden, geschehen viele Dinge im Hintergrund. Nehmen wir zum Beispiel an, wir haben etwas HTML wie dieses

<div class="parent">
  <div class="child">Child</div>
  <div class="child">Child</div>
  <div class="child">Child</div>
</div>

Und dann schreiben wir etwas CSS…

.parent {
  display: flex;
}

Dies sind technisch gesehen nicht die einzigen Stile, die wir anwenden, wenn wir die obige Zeile CSS schreiben. Tatsächlich werden eine ganze Reihe von Eigenschaften auf die .child-Elemente angewendet, als ob wir diese Stile selbst geschrieben hätten

.child {
  flex: 0 1 auto; /* Default flex value */
}

Das ist seltsam! Warum werden diese Elemente mit diesen zusätzlichen Stilen versehen, obwohl wir diesen Code nicht geschrieben haben? Nun, das liegt daran, dass einige Eigenschaften Standardwerte haben, die dann von uns überschrieben werden sollen. Und wenn wir diese Stile nicht kennen, die angewendet werden, wenn wir CSS schreiben, können unsere Layouts ziemlich verwirrend und schwer zu handhaben sein.

Diese obige flex-Eigenschaft ist eine sogenannte Kurzschreibweise für CSS-Eigenschaften. Und tatsächlich setzt *dies* drei separate CSS-Eigenschaften gleichzeitig. Was wir oben geschrieben haben, ist also dasselbe wie das hier zu schreiben

.child {
  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto;
}

Eine Kurzschreibweise fasst also eine Reihe verschiedener CSS-Eigenschaften zusammen, um das Schreiben mehrerer Eigenschaften auf einmal zu erleichtern, genau wie die background-Eigenschaft, bei der wir etwas wie dieses schreiben können

body {
  background: url(sweettexture.jpg) top center no-repeat fixed padding-box content-box red;                   
}

Ich versuche, Kurzschreibweisen zu vermeiden, da sie ziemlich verwirrend sein können und ich dazu neige, die ausgeschriebenen Versionen zu schreiben, nur weil mein Gehirn lange Zeilen von Eigenschaftswerten nicht verarbeiten kann. Aber es ist empfohlen, die Kurzschreibweise für Flexbox zu verwenden, was... seltsam ist... bis man versteht, dass die flex-Eigenschaft viel Arbeit leistet und jede ihrer Untereigenschaften mit den anderen interagiert.

Außerdem sind die Standardstile gut, weil wir die meiste Zeit nicht wissen müssen, was diese Flexbox-Eigenschaften tun. Zum Beispiel schreibe ich, wenn ich Flexbox verwende, oft so etwas wie

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

Ich muss mich nicht einmal um die Kindelemente oder die auf sie angewendeten Stile kümmern, und das ist großartig! In diesem Fall richten wir die Kindelemente nebeneinander aus und verteilen sie dann gleichmäßig zwischen ihnen. Zwei Zeilen CSS geben Ihnen hier viel Macht, und das ist das Genialste an Flexbox und diesen geerbten Stilen – Sie müssen nicht die gesamte Komplexität unter der Haube verstehen, wenn Sie nur 90% der Zeit dasselbe tun wollen. Es ist bemerkenswert intelligent, weil die gesamte Komplexität aus dem Blickfeld verborgen ist.

Aber was ist, wenn wir verstehen wollen, wie Flexbox – einschließlich der Eigenschaften flex-grow, flex-shrink und flex-basis – tatsächlich funktioniert? Und welche coolen Dinge können wir damit machen?

Gehen Sie einfach zum CSS-Tricks Almanac. Fertig!

Nur ein Scherz. Beginnen wir mit einem kurzen, etwas vereinfachten Überblick und kehren wir zu den Standard-flex-Eigenschaften zurück, die auf Kindelemente angewendet werden

.child {
  flex: 0 1 auto;
}

Diese Standardstile sagen dem Kindelement, wie es sich dehnen und ausdehnen soll. Aber jedes Mal, wenn ich sehe, wie sie verwendet oder überschrieben werden, finde ich es hilfreich, diese Kurzschreibweisen so zu betrachten

/* This is just how I think about the rule above in my head */

.child {
  flex: [flex-grow] [flex-shrink] [flex-basis];
}

/* or... */

.child {
  flex: [max] [min] [ideal size];
}

Der erste Wert ist flex-grow und er ist auf 0 gesetzt, denn standardmäßig wollen wir nicht, dass sich unsere Elemente überhaupt ausdehnen (meistens). Stattdessen wollen wir, dass jedes Element von der Größe des darin enthaltenen Inhalts abhängt. Hier ist ein Beispiel

.parent { 
  display: flex; 
}

Ich habe die Eigenschaft contenteditable zu jedem .child-Element oben hinzugefügt, damit Sie darauf klicken und noch mehr Inhalt eingeben können. Sehen Sie, wie es reagiert? Das ist das Standardverhalten eines Flexbox-Elements: flex-grow ist auf 0 gesetzt, weil wir wollen, dass sich das Element basierend auf dem darin enthaltenen Inhalt vergrößert.

Aber! Wenn wir den Standardwert der Eigenschaft flex-grow von 0 auf 1 ändern würden, so wie hier…

.child {
  flex: 1 1 auto;
}

Dann nehmen alle Elemente einen gleichen Teil des .parent-Elements ein, aber *nur, wenn die Längen ihrer Inhalte gleich sind*.

Dies ist genau dasselbe wie das Schreiben…

.child {
  flex-grow: 1;
}

…und das Ignorieren der anderen Werte, da diese sowieso standardmäßig gesetzt wurden. Ich glaube, das hat mich bei der Arbeit mit flexiblen Layouts *so* lange verwirrt. Ich sah Code, der nur flex-grow hinzufügte, und fragte mich, woher die anderen Stile kamen. Es war wie ein frustrierendes Kriminalrätsel, das ich einfach nicht lösen konnte.

Wenn wir nun nur eines dieser Elemente stärker wachsen lassen wollten als die anderen, müssten wir Folgendes tun

.child-three {
  flex: 3 1 auto;
}

/* or we could just write... */

.child-three {
  flex-grow: 3;
}

Ist dieser Code auch ein Jahrzehnt nach der Einführung von Flexbox in Browsern seltsam anzusehen? Für mich ist er das sicherlich. Ich brauche zusätzliche Denkpower, um beim Lesen der Kurzschreibweise zu sagen: „Ah, max, min, ideale Größe“, aber es wird mit der Zeit einfacher. Jedenfalls nehmen im obigen Beispiel die ersten beiden Kindelemente proportional den gleichen Platz ein, aber das dritte Element versucht, dreimal so viel Platz wie die anderen einzunehmen.

Nun, hier wird es seltsam, denn das alles hängt vom Inhalt der Kindelemente ab. Selbst wenn wir flex-grow auf 3 setzen, wie im obigen Beispiel, und dann mehr Inhalt hinzufügen, wird das Layout etwas Seltsames und Merkwürdiges tun, wie dieses

Diese zweite Spalte nimmt nun zu viel Platz ein! Wir werden später darauf zurückkommen, aber für den Moment ist es nur wichtig zu erinnern, dass der Inhalt eines Flex-Elements einen Einfluss darauf hat, wie flex-grow, flex-shrink und flex-basis zusammenarbeiten.

OK, nun zu flex-shrink. Denken Sie daran, das ist der zweite Wert in der Kurzschreibweise

.child {
  flex: 0 1 auto; /* flex-shrink = 1 */
}

flex-shrink sagt dem Browser, wie klein ein Element sein soll. Der Standardwert ist 1, was bedeutet: „Nimm jederzeit den gleichen Platz ein.“ Aber! Wenn wir diesen Wert auf 0 setzen würden, wie hier

.child {
  flex: 0 0 auto;
}

…dann sagen wir diesem Element, dass es jetzt nicht mehr schrumpfen soll. *Bleib gleich groß, verdammt noch mal!* ist im Wesentlichen das, was dieses CSS sagt, und genau das wird es auch tun. Wir werden in Kürze auf diese Eigenschaft zurückkommen, sobald wir den letzten Wert in dieser Kurzschreibweise betrachtet haben.

flex-basis ist der letzte Wert, der standardmäßig in der flex-Kurzschreibweise hinzugefügt wird, und er gibt an, wie wir einem Element eine ideale Größe geben. Standardmäßig ist er auf auto gesetzt, was bedeutet: „Nutze meine Höhe oder Breite.“ Wenn wir also ein übergeordnetes Element auf display: flex setzen…

.parent {
  display: flex;
}

.child {
  flex: 0 1 auto;
}

Dies erhalten wir standardmäßig im Browser

Beachten Sie, wie alle Elemente standardmäßig die Breite ihres Inhalts haben? Das liegt daran, dass auto besagt, dass die ideale Größe unseres Elements durch seinen Inhalt definiert ist. Damit alle Elemente den vollen Platz des übergeordneten Elements einnehmen, können wir die Kindelemente auf width: 100% setzen, *oder* wir können flex-basis auf 100% setzen, *oder* wir können flex-grow auf 1 setzen.

Macht das Sinn? Es ist seltsam, oder? Wenn man darüber nachdenkt, schon. Jeder dieser Kurzschreibweise-Werte beeinflusst den anderen, und deshalb wird empfohlen, diese Kurzschreibweise anstelle der unabhängigen Einstellung dieser Werte zu verwenden.

OK, weiter geht's. Wenn wir etwas wie das hier schreiben…

.child-three {
  flex: 0 1 1000px;
}

Was wir dem Browser hier sagen, ist, flex-basis auf 1000px zu setzen oder: „Bitte, bitte, bitte nimm einfach 1000px Platz ein.“ Wenn das nicht möglich ist, nimmt das Element diesen Platz proportional zu den anderen Elementen ein.

Sie werden feststellen, dass das dritte Element auf kleineren Bildschirmen nicht tatsächlich 1000px breit ist! Das liegt daran, dass es eigentlich ein Vorschlag ist. Wir haben immer noch flex-shrink angewendet, das dem Element sagt, dass es sich auf die gleiche Größe wie die anderen Elemente verkleinern soll.

Auch das Hinzufügen von mehr Inhalt zu den anderen Kindern wird hier weiterhin Auswirkungen haben

Wenn wir nun verhindern wollen, dass sich dieses Element überhaupt verkleinert, könnten wir etwas wie das hier schreiben

.child-three {
  flex: 0 0 1000px;
}

Denken Sie daran, flex-shrink ist hier der zweite Wert, und indem wir ihn auf 0 setzen, sagen wir: „Schrumpfe niemals, du Idiot.“ Und das wird es auch nicht tun. Das Element wird sogar aus dem übergeordneten Element ausbrechen, weil es nie kürzer als 1000px breit wird

Nun ändert sich all dies, wenn wir flex-wrap für das übergeordnete Element auf true setzen

.parent {
  display: flex;
  flex-wrap: wrap;
}

.child-three {
  flex: 0 0 1000px;
}

Wir sehen dann so etwas wie das hier

Das liegt daran, dass Flex-Elemente standardmäßig versuchen, in eine Zeile zu passen, aber flex-wrap: wrap ignoriert das vollständig. Wenn die Flex-Elemente nicht in den gleichen Platz passen, brechen sie in eine neue Zeile um.


Dies sind nur einige der Möglichkeiten, wie sich flex-Eigenschaften überschneiden und warum es so unglaublich wertvoll ist, zu verstehen, wie diese Eigenschaften unter der Haube funktionieren. Jede dieser Eigenschaften kann die andere beeinflussen, und wenn Sie nicht verstehen, wie eine Eigenschaft funktioniert, verstehen Sie irgendwie gar nichts – was mich früher sicherlich verwirrt hat, bevor ich anfing, mich damit zu beschäftigen!

Aber zusammenfassend

  • Versuchen Sie, die flex-Kurzschreibweise zu verwenden
  • Denken Sie dabei an max, min und ideale Größe
  • Denken Sie daran, dass der Inhalt eines Elements auch die Funktionsweise dieser Werte beeinflussen kann.