Füllen Sie den verbleibenden vertikalen Raum mit CSS über display: flex

194

In einem 3-reihigen Layout:

  • Die obere Reihe sollte entsprechend ihrem Inhalt dimensioniert sein
  • Die untere Reihe sollte eine feste Höhe in Pixel haben
  • Die mittlere Reihe sollte erweitert werden, um den Behälter zu füllen

Das Problem ist, dass beim Erweitern des Hauptinhalts die Kopf- und Fußzeilen zerkleinert werden:

Schlecht biegen

HTML:

<section>
  <header>
    header: sized to content
    <br>(but is it really?)
  </header>
  <div>
    main content: fills remaining space<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- uncomment to see it break - ->
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- -->
  </div>
  <footer>
    footer: fixed height in px
  </footer>
</section>

CSS:

section {
  display: flex;
  flex-flow: column;
  align-items: stretch;
  height: 300px;
}
header {
  flex: 0 1 auto;
  background: tomato;
}
div {
  flex: 1 1 auto;
  background: gold;
  overflow: auto;
}
footer {
  flex: 0 1 60px;
  background: lightgreen;
  /* fixes the footer: min-height: 60px; */
}

Geige:

Ich bin in der glücklichen Situation, dass ich das neueste und beste CSS verwenden kann, ohne auf ältere Browser zu achten. Ich dachte, ich könnte das Flex-Layout verwenden, um die alten tabellenbasierten Layouts endlich loszuwerden. Aus irgendeinem Grund macht es nicht das, was ich will ...

Für die Aufzeichnung gibt es viele verwandte Fragen zu SO über "Füllen der verbleibenden Höhe", aber nichts, was das Problem löst, das ich mit Flex habe. Refs:

Zilk
quelle
Scheint wie erwartet an der Geige zu arbeiten.
Dayan
Ja, Sie müssen den Rest des Inhalts von <div> auskommentieren, um zu sehen, wie er beschädigt wird. Vielleicht hätte ich die kaputte Version verlinken sollen. Es tut uns leid.
Zilk
Ich habe der Frage jetzt beide Versionen hinzugefügt.
Zilk
Ich verstehe, was du jetzt meinst.
Dayan
dup von stackoverflow.com/questions/90178/… ?
Jonathan Stray

Antworten:

244

Machen Sie es einfach: DEMO

section {
  display: flex;
  flex-flow: column;
  height: 300px;
}

header {
  background: tomato;
  /* no flex rules, it will grow */
}

div {
  flex: 1;  /* 1 and it will fill whole space left if no flex value are set to other children*/
  background: gold;
  overflow: auto;
}

footer {
  background: lightgreen;
  min-height: 60px;  /* min-height has its purpose :) , unless you meant height*/
}
<section>
  <header>
    header: sized to content
    <br/>(but is it really?)
  </header>
  <div>
    main content: fills remaining space<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- uncomment to see it break -->
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- -->
  </div>
  <footer>
    footer: fixed height in px
  </footer>
</section>

Vollbildversion

section {
  display: flex;
  flex-flow: column;
  height: 100vh;
}

header {
  background: tomato;
  /* no flex rules, it will grow */
}

div {
  flex: 1;
  /* 1 and it will fill whole space left if no flex value are set to other children*/
  background: gold;
  overflow: auto;
}

footer {
  background: lightgreen;
  min-height: 60px;
  /* min-height has its purpose :) , unless you meant height*/
}

body {
  margin: 0;
}
<section>
  <header>
    header: sized to content
    <br/>(but is it really?)
  </header>
  <div>
    main content: fills remaining space<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- uncomment to see it break -->
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br> x
    <br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    <!-- -->
  </div>
  <footer>
    footer: fixed height in px
  </footer>
</section>

G-Cyrillus
quelle
20
Was ist, wenn der Abschnitt eine Höhe von 100% haben soll?
Paul Totzke
5
@PaulTotzke Dann ist es morelike eine andere Frage, Sie müssen nur die Höhe auf 100% einstellen. Wie üblich benötigen Eltern eine festgelegte / verwendbare Höhe. Andernfalls haben wir das klassische Beispiel für 100% 'Null' für den obigen Code: HTML, Körper, Abschnitt {Höhe: 100%;}, wobei Abschnitt direktes Kind von Körper ist. Jsfiddle.net/ 7yLFL / 445 dies gibt eine Kopf- und Fußzeile behoben.
G-Cyrillus
1
@ GCyrillus Danke. Ich wusste nicht, dass HTML, Body UND der Wrapper eine festgelegte Größe haben mussten.
Paul Totzke
1
Danke für die "min-height hat ihren Zweck". Ich habe mich gefragt, warum es nicht funktioniert hat, indem ich die Höhe für feste Elemente verwendet habe.
Maciej Krawczyk
2
Hatte ein Problem mit dieser Lösung in Firefox. Ich habe es korrigiert, indem ich zu gewechselt flex: 1habe flex-grow: 1. Danke für die Lösung!
seltsamer Entwickler
19

Das folgende Beispiel enthält das Bildlaufverhalten, wenn der Inhalt der erweiterten Mittelkomponente über seine Grenzen hinausgeht. Außerdem nimmt die mittlere Komponente 100% des verbleibenden Speicherplatzes im Ansichtsfenster ein.

jsfiddle hier

html, body, .r_flex_container{
    height: 100%;
    display: flex;
    flex-direction: column;
    background: red;
    margin: 0;
}
.r_flex_container {
    display:flex;
    flex-flow: column nowrap;
    background-color:blue;
}

.r_flex_fixed_child {
    flex:none;
    background-color:black;
    color:white;

}
.r_flex_expand_child {
    flex:auto;
    background-color:yellow;
    overflow-y:scroll;
}

Beispiel für HTML, mit dem dieses Verhalten demonstriert werden kann

<html>
<body>
    <div class="r_flex_container">
      <div class="r_flex_fixed_child">
        <p> This is the fixed 'header' child of the flex container </p>
      </div>
      <div class="r_flex_expand_child">
            <article>this child container expands to use all of the space given to it -  but could be shared with other expanding childs in which case they would get equal space after the fixed container space is allocated. 
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,
            </article>
      </div>
      <div class="r_flex_fixed_child">
        this is the fixed footer child of the flex container
        asdfadsf
        <p> another line</p>
      </div>

    </div>
</body>
</html>
gamozzii
quelle
3
Dies kann etwas vereinfacht werden , indem htmlvon dem Selektor und appyling height: 100vhzu bodyspeziell: jsfiddle.net/pm6nqcqh/1
Dai
Ich habe beim erweiterbaren Kind einen Unterschied zwischen flex: auto und flex: 1 festgestellt. Mit flex: auto scheinen andere Kinder bei Bedarf zu schrumpfen, mit flex: 1 nicht (in Chrome)
mvermand
7

Ein moderner Ansatz wäre die Verwendung der Rastereigenschaft.

section {
  display: grid;
  align-items: stretch;
  height: 300px;
  grid-template-rows: min-content auto 60px;
}
header {
  background: tomato;
}
div {
  background: gold;
  overflow: auto;
}
footer {
  background: lightgreen;
}
<section>
  <header>
    header: sized to content
    <br>(but is it really?)
  </header>
  <div>
    main content: fills remaining space<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    
  </div>
  <footer>
    footer: fixed height in px
  </footer>
</section>

wuppie367
quelle
1
Die Unterstützung von CSS-Grids ist ziemlich neu. Ich würde es nicht verwenden, wenn Sie keine alten Browser unterstützen müssen.
adi518
4

Verwenden Sie die flex-growEigenschaft für den Hauptinhalt div und geben Sie die dispaly: flex;an das übergeordnete Element weiter.

body {
    height: 100%;
    position: absolute;
    margin: 0;
}
section {
  height: 100%;
  display: flex;
  flex-direction : column;
}
header {
  background: tomato;
}
div {
  flex: 1; /* or flex-grow: 1  */;
  overflow-x: auto;
  background: gold;
}
footer {
  background: lightgreen;
  min-height: 60px;
}
<section>
  <header>
    header: sized to content
    <br>(but is it really?)
  </header>
  <div>
    main content: fills remaining space<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
    x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>
  </div>
  <footer>
    footer: fixed height in px
  </footer>
</section>

Deepu Reghunath
quelle
Gibt es eine andere Lösung für dieses Problem (wo die sectionHöhe nicht festgelegt ist?) Als zu verwenden position: absolute?
Ben
1
@ben Wenn Sie die Höhe des Elements kennen. Dann können Sie die Verwendung vermeiden position: absolute;. https://jsfiddle.net/xa26brzf/
Deepu Reghunath