Isi sisa ruang vertikal dengan CSS menggunakan display: flex

196

Dalam tata letak 3 baris:

  • baris atas harus berukuran sesuai dengan isinya
  • baris bawah harus memiliki ketinggian tetap dalam piksel
  • baris tengah harus diperluas untuk mengisi wadah

Masalahnya adalah bahwa ketika konten utama mengembang, ia menekan baris header dan footer:

Meregangkan Buruk

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; */
}

Biola:

Saya dalam situasi beruntung bahwa saya dapat menggunakan CSS terbaru dan terhebat, mengabaikan browser lawas. Saya pikir saya bisa menggunakan tata letak fleksibel untuk akhirnya menyingkirkan tata letak berbasis tabel lama. Untuk beberapa alasan, itu tidak melakukan apa yang saya inginkan ...

Sebagai catatan, ada banyak pertanyaan terkait pada SO tentang "mengisi ketinggian yang tersisa", tetapi tidak ada yang menyelesaikan masalah yang saya alami dengan flex. Referensi:

Zilk
sumber
Tampaknya bekerja seperti yang diharapkan pada biola.
Dayan
Ya, Anda perlu menghapus komentar dari konten <div> yang lain untuk melihat bagaimana pengaruhnya. Mungkin saya harus menautkan versi yang rusak. Maaf.
Zilk
Saya telah menambahkan kedua versi ke pertanyaan sekarang.
Zilk
Saya mengerti maksud Anda sekarang.
Dayan

Jawaban:

246

Sederhanakan: 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>

Versi layar penuh

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
sumber
20
Bagaimana jika kita ingin bagian memiliki ketinggian 100%?
Paul Totzke
5
@ PaulTotzke Maka itu adalah pertanyaan lain yang serupa, Anda hanya perlu mengatur tinggi hingga 100%. Seperti biasa, orang tua memerlukan set ketinggian / dapat digunakan, kalau tidak kita memiliki contoh 100% 'nol' klasik untuk kode di atas: html, tubuh, bagian {tinggi: 100%;} di mana bagian adalah anak langsung dari tubuh jsfiddle.net/ 7yLFL / 445 ini memberikan header dan footer diperbaiki.
G-Cyrillus
1
@GCyrillus Terima kasih. Saya tidak menyadari html, tubuh DAN bungkus semua harus memiliki ukuran yang ditetapkan.
Paul Totzke
1
Terima kasih untuk "min-height memiliki tujuannya". Saya bertanya-tanya mengapa itu tidak berhasil, menggunakan ketinggian untuk elemen tetap.
Maciej Krawczyk
2
Punya masalah dengan solusi ini di firefox. Saya memperbaikinya dengan mengubah flex: 1ke flex-grow: 1. Terima kasih atas solusinya!
aneh_developer
19

Contoh di bawah ini mencakup perilaku pengguliran jika konten komponen pusat yang diperluas melampaui batasnya. Komponen tengah juga mengambil 100% ruang yang tersisa di viewport.

jsfiddle di sini

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;
}

Contoh html yang dapat digunakan untuk menunjukkan perilaku ini

<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
sumber
3
Hal ini dapat sedikit disederhanakan dengan menghilangkan htmldari pemilih dan appyling height: 100vhuntuk bodysecara khusus: jsfiddle.net/pm6nqcqh/1
Dai
Saya memang melihat perbedaan antara flex: auto dan flex: 1 pada anak yang dapat diupgrade. Dengan flex: otomatis, anak-anak lain tampaknya menyusut saat dibutuhkan, dengan flex: 1 mereka tidak (di Chrome)
mvermand
7

Pendekatan yang lebih modern adalah dengan menggunakan properti grid.

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
sumber
1
Dukungan grid CSS terbilang baru. Saya tidak akan menggunakannya kecuali Anda tidak harus mendukung browser lama.
adi518
4

Gunakan flex-growproperti ke div konten utama dan berikan dispaly: flex;ke induknya;

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
sumber
Apakah ada solusi lain untuk masalah ini (di mana sectionketinggian tidak diperbaiki?) Daripada menggunakan position: absolute?
Ben
1
@ Ben Jika Anda tahu ketinggian elemen. Maka Anda dapat menghindari penggunaan position: absolute;. https://jsfiddle.net/xa26brzf/
Deepu Reghunath