Boxen, die die Höhe (oder mehr) füllen (und nicht gequetscht werden)

Avatar of Chris Coyier
Chris Coyier am

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

Es ist schwer, all das Tolle, was Flexbox bietet, in einem kleinen Blogbeitrag zusammenzufassen. Obwohl wir es hier versucht haben. Hier konzentrieren wir uns einfach auf eine Sache, die Flexbox sehr gut löst: die Fähigkeit, eine beliebige Anzahl von Boxen die gesamte verfügbare Höhe einer übergeordneten Box füllen zu lassen. Und nicht nur das, sondern bei Bedarf auch darüber hinaus zu expandieren (ohne sie zu quetschen, um sie anzupassen).

Mit „Box“ meine ich einfach ein Block-Element. Div, Section, Article, was auch immer.

Standardmäßig wird die Höhe dieser Boxen durch den darin enthaltenen Inhalt bestimmt. Sie werden übereinander gestapelt. Die Höhe ihrer übergeordneten Boxen kann auch durch ihre kombinierte Höhe bestimmt werden, aber es kann auch anders sein (z. B. ist sie explizit festgelegt oder etwas Variables wie das Browserfenster). Wenn die übergeordnete Box eine größere Höhe hat, bleibt darunter einfach leerer Platz.

Können wir die Boxen zwingen, den Platz gleichmäßig aufzuteilen? Mit Flexbox können wir das.

Links: Standard; Rechts: Was wir tun wollen

Sagen wir, das HTML ist so:

<section class="fill-height-or-more">
  <div>
    <!-- stuff -->
  </div>
  <div>
    <!-- stuff -->
  </div>
  <div>
    <!-- stuff -->
  </div>
</section>

Dann starten wir Flexbox mit der übergeordneten Box:

.fill-height-or-more {
  display: flex;
}

und machen die Boxen von oben nach unten (Spalte) statt von links nach rechts (Zeile), wie es der Standard ist.

.fill-height-or-more {
  display: flex;
  flex-direction: column;
}

Damit allein wird es keinen Unterschied zu dem machen, was wir vorher hatten. Aber jetzt wenden wir die Flex-Eigenschaft auf die Kindelemente an und sie werden den Platz ausfüllen.

.fill-height-or-more > div {
  /* these are the flex items */
  flex: 1;
}

Und fertig =).

Als Detail ist `flex: 1;` dasselbe wie `flex: 1 1 auto;`. Es ist eine Kurzform für drei verschiedene Eigenschaften.

flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;

Es ergibt sich gerade so, dass ihnen die Fähigkeit, auf gleicher Basis zu wachsen, die häufigste Anforderung ist, daher ist `flex: 1;` eine schöne Art, dies zu schreiben.

Eines der schönen Dinge an Flexbox ist, dass dies mit einer beliebigen Anzahl von Boxen funktioniert. Es kann eine einzige Box sein! Es können 100 Boxen sein! Egal. Wenn zusätzlicher Platz vorhanden ist, wird der Platz geteilt und gefüllt. Wenn nicht, kein Problem.

In der Zeit vor Flexbox hätten wir versucht, die Anzahl der Boxen zu kennen/herauszufinden und dann ihre Höhen mit Prozentsätzen festzulegen. Das funktioniert, um zusätzlichen Platz zu füllen, aber wenn es zu viele Boxen gäbe, würden sie gequetscht werden. Das ist eine weitere schöne Sache an Flexbox: Sie quetscht diese Boxen nicht so stark, dass sie ihren Inhalt nicht mehr darstellen können. Also...

Links: Wenn wir Prozentsätze verwenden würden; Rechts: Normales gewünschtes Verhalten

Wenn wir das noch einen Schritt weiter gehen wollten, könnten wir Flexbox verwenden, um den Inhalt auch innerhalb dieser Boxen zu zentrieren (!). Hier werden die Leute wütend auf CSS. Vertikales Zentrieren ist ziemlich schwierig. Selbst mit Flexbox hier müssen wir jedes dieser Flex-Element-Kinder zu Flex-Containern machen. Dann verwenden wir einen internen Wrapper, der zum Flex-Element wird, das wir zentrieren. Also ja, immer noch ein zusätzliches Element. Update: Tedmotu hat es geschafft ohne das zusätzliche Element, was wirklich einfach ist.

Um es zu zentrieren, machen wir die Ausrichtung wieder von oben nach unten (Spalte) und verwenden eine weitere Flexbox-Eigenschaft, `justify-content`, um es zu zentrieren.

.fill-height-or-more > div {
  flex: 1;

  display: flex;
  justify-content: center;
  flex-direction: column;
}

Hier ist, wo die Referenzanleitung nützlich ist… um schnell herauszufinden, welche Eigenschaft was tut.

Dann bekommen wir das:

Siehe den Stift Boxen, die Höhe füllen (oder mehr) von Chris Coyier (@chriscoyier) auf CodePen.

Browser-Unterstützung

Ich habe hier in diesem Beitrag nur die neueste Syntax verwendet. Aktuelle Versionen von Chrome, Opera unterstützen sie genau so. Zukünftige Versionen von Firefox und Android werden sie ebenfalls genau so unterstützen. Safari und iOS unterstützen die neue Syntax, aber mit -webkit-Präfixen. Can I Use hat die ganze Geschichte.

IE ist seltsam. IE 10 unterstützt die Zwischenversion von Flexbox (z. B. display: -ms-flexbox;). IE 11 unterstützt die neueste Flexbox. **Bei dieser speziellen Demo jedoch** ist etwas kaputt. Während die Höhe von .fill-height-or-more durch die Verwendung von `min-height` die volle Höhe erreicht, werden die Boxen gequetscht.

Wenn Sie Höhe statt des Flex-Containers verwenden, "funktioniert" es – aber der Punkt hier war die Verwendung von min-height, um Quetschungen zu vermeiden. Scheint mir ein Implementierungsfehler zu sein.

UPDATE: Nirav Zaveri schrieb mir, dass in IE (ich habe v11 getestet) `flex: 1` nicht dasselbe ist wie `flex: 1 1 auto`, auch wenn es das sein sollte (?). Wenn Sie letzteres einstellen, funktioniert es.

Es ist verständlich, dass Sie möglicherweise etwas weiter zurückgehen müssen, was die Browserunterstützung angeht. Firefox 27, iOS 6 und Safari 6 sind ziemlich legitime Browser-Support-Ziele und all diese verwenden eine Variation der älteren Syntax, manchmal mit Präfix und manchmal nicht.

Unser kleines Beispiel sieht nur so aus, wenn es für die Unterstützung so weit wie möglich ausgearbeitet ist.

.fill-height-or-more {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -moz-box-orient: vertical;
  -moz-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
} 

.fill-height-or-more > div {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  -moz-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -moz-box-orient: vertical;
  -moz-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
}

Autsch. Meine Empfehlung? Schreiben Sie es in der modernen Syntax, wie ich es oben getan habe, und lassen Sie Autoprefixer sich darum kümmern, das nicht nur die Präfixe, sondern auch die ältere Syntax behandelt.

Video-Screencast

Warum nicht gleich? Ich habe es hier veröffentlicht und werde es auch einbetten.


Ach ja, nur für den Fall, dass es interessiert: Das reale Szenario, das mich dazu gebracht hat, war diese Seite.