Lấp đầy không gian dọc còn lại bằng CSS bằng cách sử dụng display: flex


194

Trong bố cục 3 hàng:

  • hàng trên cùng phải có kích thước theo nội dung của nó
  • hàng dưới cùng phải có chiều cao cố định bằng pixel
  • hàng giữa nên mở rộng để lấp đầy container

Vấn đề là khi nội dung chính mở rộng, nó squish các hàng đầu trang và chân trang:

Uốn cong

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

Vĩ cầm:

Tôi đang ở trong tình huống may mắn rằng tôi có thể sử dụng CSS mới nhất và tốt nhất, bỏ qua các trình duyệt cũ. Tôi nghĩ rằng tôi có thể sử dụng bố trí flex để cuối cùng thoát khỏi các bố cục dựa trên bảng cũ. Vì một số lý do, nó không làm những gì tôi muốn ...

Đối với hồ sơ, có nhiều câu hỏi liên quan về SO về "lấp đầy chiều cao còn lại", nhưng không có gì giải quyết được vấn đề tôi gặp phải với flex. Tham chiếu:


Có vẻ như đang làm việc như mong đợi trên fiddle.
Dayan

Có, bạn cần bỏ ghi chú phần còn lại của nội dung <div> để xem nó phá vỡ như thế nào. Có lẽ tôi nên liên kết phiên bản bị hỏng. Lấy làm tiếc.
Zilk

Tôi đã thêm cả hai phiên bản cho câu hỏi bây giờ.
Zilk

Tôi thấy những gì bạn có nghĩa là bây giờ.
Dayan

Câu trả lời:


244

Làm cho nó đơn giản: 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>

Phiên bản toàn màn hình

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>


20
Nếu chúng ta muốn phần có chiều cao 100% thì sao?
Paul Totzke

5
@PaulTotzke Sau đó, nó giống như một câu hỏi khác, bạn chỉ cần đặt chiều cao thành 100%. Như thường lệ, cha mẹ cần một bộ chiều cao / có thể sử dụng được, ngoài ra chúng ta có ví dụ 100% 'null' cổ điển cho mã ở trên: html, body, phần {height: 100%;} trong đó phần là con trực tiếp của cơ thể jsfiddle.net/ 7yLFL / 445 này cung cấp một tiêu đề và chân trang cố định.
G-Cyrillus

1
@GCyrillus Cảm ơn bạn. Tôi đã không nhận ra html, cơ thể VÀ trình bao bọc tất cả phải có kích thước được đặt.
Paul Totzke 22/2/2016

1
Cảm ơn vì "chiều cao tối thiểu có mục đích của nó". Tôi đã tự hỏi tại sao nó không hoạt động, sử dụng chiều cao cho các yếu tố cố định.
Maciej Krawchot

2
Có một vấn đề với giải pháp này trong firefox. Tôi đã sửa nó bằng cách đổi flex: 1thành flex-grow: 1. Cảm ơn giải pháp!
lạ_developer

19

Ví dụ dưới đây bao gồm hành vi cuộn nếu nội dung của thành phần trung tâm mở rộng vượt quá giới hạn của nó. Ngoài ra, thành phần trung tâm chiếm 100% không gian còn lại trong chế độ xem.

jsfiddle ở đây

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

Ví dụ về html có thể được sử dụng để thể hiện hành vi này

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

3
Điều này có thể được đơn giản hóa một chút bằng cách xóa htmlkhỏi bộ chọn và ứng dụng height: 100vhđể bodycụ thể: jsfiddle.net/pm6nqcqh/1
Đại

Tôi đã nhận thấy một sự khác biệt giữa flex: auto và flex: 1 trên đứa trẻ có thể mở rộng. Với flex: auto, những đứa trẻ khác dường như co lại khi cần, với flex: 1 chúng không (trong Chrome)
mvermand

7

Một cách tiếp cận hiện đại hơn sẽ là sử dụng tài sản lưới.

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>


1
Hỗ trợ lưới CSS là khá mới. Tôi sẽ không sử dụng nó trừ khi bạn không phải hỗ trợ các trình duyệt cũ.
adi518

4

Sử dụng thuộc flex-growtính cho div nội dung chính và cung cấp cho dispaly: flex;cha mẹ của nó;

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>


Có giải pháp nào khác cho vấn đề này (nơi mà sectionchiều cao không cố định không?) Thay vì sử dụng position: absolute?
Ben

1
@ben Nếu bạn biết chiều cao của phần tử. Sau đó, bạn có thể tránh sử dụng position: absolute;. https://jsfiddle.net/xa26brzf/
Deepu Reghunath
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.