เติมพื้นที่แนวตั้งที่เหลือด้วย CSS โดยใช้ display: flex


196

ในรูปแบบ 3 แถว:

  • แถวด้านบนควรมีขนาดตามเนื้อหา
  • แถวด้านล่างควรมีความสูงคงที่เป็นพิกเซล
  • แถวกลางควรขยายเพื่อเติมตู้คอนเทนเนอร์

ปัญหาคือว่าเมื่อเนื้อหาหลักขยายออกมันจะบีบแถวส่วนหัวและส่วนท้าย:

งอไม่ดี

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

ซอ:

ฉันอยู่ในสถานการณ์ที่โชคดีที่ฉันสามารถใช้ CSS ล่าสุดและยิ่งใหญ่ที่สุดในเบราว์เซอร์เดิมโดยไม่สนใจ ฉันคิดว่าฉันสามารถใช้เค้าโครงแบบยืดหยุ่นเพื่อกำจัดเค้าโครงตารางแบบเก่าได้ในที่สุด ด้วยเหตุผลบางอย่างมันไม่ได้ทำสิ่งที่ฉันต้องการ ...

สำหรับบันทึกมีคำถามที่เกี่ยวข้องมากมายเกี่ยวกับ SO เกี่ยวกับ "การเติมความสูงที่เหลืออยู่" แต่ไม่มีอะไรที่แก้ปัญหาที่ฉันกำลังดิ้น refs:


ดูเหมือนว่าจะทำงานได้ตามที่คาดไว้ในซอ
Dayan

ใช่คุณต้องยกเลิกการคอมเม้นเนื้อหาส่วนที่เหลือของ <div> เพื่อดูว่ามันแตกได้อย่างไร บางทีฉันควรจะเชื่อมโยงรุ่นที่ใช้งานไม่ได้ ขอโทษ
Zilk

ตอนนี้ฉันได้เพิ่มคำถามทั้งสองเวอร์ชันแล้ว
Zilk

ฉันเห็นสิ่งที่คุณหมายถึงตอนนี้
Dayan

คำตอบ:


246

ทำให้มันง่าย: 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>

เวอร์ชันเต็มหน้าจอ

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
ถ้าเราต้องการให้ส่วนมีความสูง 100%
Paul Totzke

5
@PaulTotzke แล้วมันก็ไม่เหมือนกันคำถามอื่นคุณต้องตั้งความสูงถึง 100% ตามปกติผู้ปกครองต้องการชุดความสูง / ใช้งานได้เรามีตัวอย่าง 'null' คลาสสิก 100% สำหรับรหัสด้านบน: html, body, section {height: 100%;} โดยที่ section เป็นส่วนย่อยโดยตรงของร่างกายjsfiddle.net/ 7yLFL / 445สิ่งนี้ให้ส่วนหัวและส่วนท้ายคงที่
G-Cyrillus

1
@Gyrillus ขอบคุณ ฉันไม่ได้ตระหนักถึง HTML, ร่างกายและเสื้อคลุมทั้งหมดต้องมีขนาดที่กำหนด
Paul Totzke

1
ขอบคุณสำหรับ "ความสูงขั้นต่ำมีจุดประสงค์" ฉันสงสัยว่าทำไมมันไม่ทำงานใช้ความสูงสำหรับองค์ประกอบคงที่
Maciej Krawczyk

2
มีปัญหากับวิธีแก้ไขปัญหานี้ใน firefox ผมแก้ไขได้โดยการเปลี่ยนไปflex: 1 flex-grow: 1ขอบคุณสำหรับการแก้ปัญหา!
strange_developer

19

ตัวอย่างด้านล่างรวมถึงพฤติกรรมการเลื่อนหากเนื้อหาขององค์ประกอบศูนย์กลางขยายขยายเกินขอบเขต ส่วนประกอบส่วนกลางใช้พื้นที่ที่เหลือ 100% ในวิวพอร์ต

jsfiddle ที่นี่

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

ตัวอย่างของ html ที่สามารถใช้แสดงพฤติกรรมนี้

<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
สิ่งนี้สามารถทำให้ง่ายขึ้นเล็กน้อยโดยการลบออกhtmlจากตัวเลือกและ appyling height: 100vhเป็นbodyพิเศษ: jsfiddle.net/pm6nqcqh/1
ได

ฉันสังเกตเห็นความแตกต่างระหว่างเฟล็กซ์: อัตโนมัติและเฟล็กซ์: 1 กับเด็กที่ขยายได้ ด้วย flex: auto เด็กคนอื่น ๆ ดูเหมือนจะหดตัวเมื่อต้องการด้วย flex: 1 พวกเขาทำไม่ได้ (ใน Chrome)
mvermand

7

วิธีที่ทันสมัยกว่านี้ก็คือการใช้คุณสมบัติกริด

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
การสนับสนุนตาราง CSS ค่อนข้างใหม่ ฉันจะไม่ใช้มันจนกว่าคุณจะไม่ต้องสนับสนุนเบราว์เซอร์รุ่นเก่า
adi518

4

ใช้flex-growคุณสมบัติของ div เนื้อหาหลักและมอบให้dispaly: flex;กับ parent

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>


มีวิธีอื่นในการแก้ปัญหานี้ (ที่sectionความสูงไม่คงที่?) แทนที่จะใช้position: absolute?
Ben

1
@ben หากคุณรู้ความสูงขององค์ประกอบ position: absolute;จากนั้นคุณสามารถหลีกเลี่ยงการใช้ https://jsfiddle.net/xa26brzf/
Deepu Reghunath
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.