การเลื่อนเฟล็กบ็อกซ์พร้อมเนื้อหาล้น


214

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือรหัสที่ฉันใช้เพื่อให้ได้เลย์เอาต์ด้านบน:

.header {
  height: 50px;
}

.body {
  position: absolute;
  top: 50px;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
}

.sidebar {
  width: 140px;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  display: flex;
}

.column {
  padding: 20px;
  border-right: 1px solid #999;
}
<div class="header">Main header</div>
<div class="body">
  <div class="sidebar">Sidebar</div>

  <div class="main">
    <div class="page-header">Page Header. Content columns are below.</div>
    <div class="content">
      <div class="column">Column 1</div>
      <div class="column">Column 1</div>
      <div class="column">Column 1</div>
    </div>
  </div>
</div>

ฉันเว้นรหัสที่ใช้สำหรับการใส่สไตล์ คุณสามารถมองเห็นทั้งหมดของมันในปากกา


ด้านบนใช้งานได้ แต่เมื่อcontentเนื้อหาในพื้นที่มีมากเกินไปก็จะทำให้ทั้งหน้าเลื่อน ฉันต้องการเพียงพื้นที่เนื้อหาตัวเองเพื่อเลื่อนดังนั้นฉันเพิ่มoverflow: autoไปcontent div

ปัญหาในตอนนี้คือคอลัมน์ไม่ขยายเกินความสูงของผู้ปกครองดังนั้นเส้นขอบจึงถูกตัดออกเช่นกัน

นี่คือปากกาแสดงปัญหาการเลื่อน

ฉันจะตั้งค่าcontentพื้นที่ให้เลื่อนอย่างอิสระอย่างไรในขณะที่ยังคงมีลูกของมันขยายเกินcontentความสูงของกล่อง

คำตอบ:


264

ฉันได้พูดคุยกับTab Atkins (ผู้เขียนข้อมูลจำเพาะเกี่ยวกับ flexbox) เกี่ยวกับเรื่องนี้และนี่คือสิ่งที่เราคิดขึ้นมา:

HTML:

<div class="content">
    <div class="box">
        <div class="column">Column 1</div>
        <div class="column">Column 2</div>
        <div class="column">Column 3</div>
    </div>
</div>

CSS:

.content {
    flex: 1;
    display: flex;
    overflow: auto;
}

.box {
    display: flex;
    min-height: min-content; /* needs vendor prefixes */
}

นี่คือปากกา:

  1. คอลัมน์สั้นถูกยืด
  2. คอลัมน์อีกต่อไปล้นและเลื่อน

ด้วยเหตุนี้การทำงานเป็นเพราะไม่หดตัวรายการถ้าพวกเขามีความสูงที่แท้จริงซึ่งก็ประสบความสำเร็จที่นี่align-items: stretchmin-content


3
พวกเขาทำงานเมื่อความสูงของผู้ปกครองไม่ได้ขึ้นอยู่กับลูกโดยทั่วไปซึ่งเป็นกรณีที่นี่ ความสูงขั้นต่ำ: 100% จะแก้ไขปัญหายืดคอลัมน์ของคุณได้อย่างแน่นอนใน Firefox (แม้ว่าไม่ใช่ใน Chrome) ไม่แน่ใจทันทีว่าเป็นบั๊กของ Chrome หรือ Firefox
dholbert

1
@dholbert - Tab Atkins ช่วยฉันด้วยสิ่งนี้ ฉันอัพเดตคำตอบแล้ว
Joseph Silber

3
โปรดทราบว่าขณะนี้ Firefox รองรับเฉพาะ "เนื้อหาขั้นต่ำ" สำหรับค่าความกว้างไม่ใช่ค่าความสูงดังนั้นจึงไม่สามารถใช้งานได้ใน Firefox หากเรื่องนี้เกี่ยวข้องกับคุณ (ดูเช่นbugzilla.mozilla.org/show_bug.cgi?id=852367 )
dholbert

2
@dholbert - ปัญหาเกี่ยวกับปากกาเหล่านี้คือพวกเขาเป็นสาธารณะดังนั้นใคร ๆ ก็สามารถเปลี่ยนได้ ฉันเป็นเจ้าของพวกเขาดังนั้นคุณไปที่นี่: codepen.io/JosephSilber/pen/pmyHh
Joseph Silber

5
ใช่สิ่งนี้เสียใน IE11
Steve

119

ฉันเพิ่งแก้ไขปัญหานี้ได้อย่างงดงามหลังจากการทดลองและข้อผิดพลาดมากมาย

ลองดูโพสต์บล็อกของฉัน: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

โดยทั่วไปในการทำให้เซลล์ flexbox เลื่อนได้คุณต้องทำให้ผู้ปกครอง ทั้งหมดoverflow: hidden;หรือไม่ก็จะเพิกเฉยต่อการตั้งค่าโอเวอร์โฟลว์และทำให้พาเรนต์ใหญ่ขึ้นแทน


11
มันใช้งานได้ในกรณีของฉันเช่นกัน แต่ว้าวฉันอยากเห็นคำอธิบายว่าทำไมมันถึงได้ผล ส่วนใหญ่ฉันพบ CSS สเป็คที่ไม่น่าเชื่อถือทั้งหมดสำหรับสิ่งนี้
markrian

2
จากการโพสต์บล็อกของคุณ: "ผมมีความคิดว่าทำไมผลงานที่และรายละเอียดที่กล่าวว่าไม่มีอะไรอย่างใดอย่างหนึ่ง" ดังนั้นฉันกำลังมองหาคำอธิบายว่าทำไมมันทำงาน ฉันได้อ่านรายละเอียดสเปค แต่อย่างที่คุณพูด
markrian

3
หลังจากคิดเพิ่มอีกฉันคิดว่ามันสมเหตุสมผล พฤติกรรมเริ่มต้นสำหรับแต่ละ div เพื่อขยายเพื่อให้เป็นลูกทั้งหมดดังนั้นจึงไม่มีการล้นที่จะซ่อนที่โหนดใบไม้ คุณต้องบังคับให้โอเวอร์โฟลว์: ซ่อนทุกอย่างจากด้านบนของ DOM ดังนั้นผู้ปกครองจึงไม่มีโอกาสที่จะรองรับเด็ก ๆ จนกว่าคุณจะลงไปที่โหนดที่คุณต้องการโอเวอร์โฟลว์และเลื่อน
geon

3
ฉันไม่แน่ใจว่าจริง ๆ อธิบาย การตั้งค่าโอเวอร์โฟลว์ให้เป็นองค์ประกอบที่ซ่อนอยู่นั้นไม่ได้ขัดขวางไม่ให้ขยายเพื่อให้มีลูก ๆ ทั้งหมดของ AFAIK ตาม MDN: "คุณสมบัติโอเวอร์โฟลระบุว่าจะคลิปเนื้อหาแสดงแถบเลื่อนหรือเพียงแสดงเนื้อหาเมื่อล้นคอนเทนเนอร์ระดับบล็อก" นอกจากนี้การตั้งค่าโอเวอร์โฟลว์ให้เป็นอย่างอื่นนอกเหนือจากที่มองเห็นจะสร้างบริบทการจัดรูปแบบบล็อกใหม่ - แต่ไม่สามารถเกี่ยวข้องได้เนื่องจาก flex container สร้างบริบทการจัดรูปแบบบล็อกของตนเองแล้ว: developer.mozilla.org/en-US/docs/Web/Guide / CSS / … .
markrian

1
ฉันควรเพิ่มว่าฉันเห็นด้วยกับคำอธิบายของคุณอย่างสมเหตุสมผล แต่ฉันไม่คิดว่ามันเป็นคำอธิบายทางเทคนิคที่ถูกต้องซึ่งเป็นสิ่งที่ฉันต้องการ โดยการเข้าใจเหตุผลอย่างแท้จริงเท่านั้นฉันจะสามารถจำวิธีแก้ปัญหาในอนาคตได้!
markrian

55

ทำงานposition:absolute;ร่วมกับflex:

position: relativeวางรายการดิ้นด้วย จากนั้นให้เพิ่ม<div>องค์ประกอบอื่นด้วย:

position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;

สิ่งนี้จะขยายองค์ประกอบไปยังขอบเขตของพาเรนต์ที่สัมพันธ์กัน แต่ไม่อนุญาตให้ขยาย ข้างในoverflow: auto;จะทำงานตามที่คาดไว้

  • ข้อมูลรหัสรวมอยู่ในคำตอบ - คลิกป้อนคำอธิบายรูปภาพที่นี่แล้วคลิกเต็มหน้าหลังจากเรียกใช้ตัวอย่างข้อมูลหรือ
  • คลิกที่นี่เพื่อ CODEPEN
  • ผลลัพธ์: ป้อนคำอธิบายรูปภาพที่นี่

.all-0 {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
p {
  text-align: justify;
}
.bottom-0 {
  bottom: 0;
}
.overflow-auto {
  overflow: auto;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>


<div class="p-5 w-100">
  <div class="row bg-dark m-0">
    <div class="col-sm-9 p-0 d-flex flex-wrap">
      <!-- LEFT-SIDE - ROW-1 -->
      <div class="row m-0 p-0">
        <!-- CARD 1 -->
        <div class="col-md-8 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/700x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 2 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
      </div>
      <div class="row m-0">
        <!-- CARD 3 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 4 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 5-->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
      </div>
    </div>
    <div class="col-sm-3 p-0">
      <div class="bg-white m-2 p-2 position-absolute all-0 d-flex flex-column">
        <h4>Social Sidebar...</h4>
        <hr />
        <div class="d-flex overflow-auto">
          <p>
            Topping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            opping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            opping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream
            chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate
            bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva
        </div>
      </div>
    </div>
  </div>

โชคดี...


2
วิธีนี้มีประโยชน์อย่างยิ่งหากส่วนประกอบด้านในมีชุดการแพ็ดเพราะมันจะล็อคมันไว้ในตำแหน่งที่คุณต้องการ มันง่ายกว่ามาก (ใช่คุณสามารถตั้งค่าbox-sizing: border-boxแทนได้ แต่อาจซับซ้อนกว่าสำหรับการควบคุมของบุคคลที่สาม)
Simon_Weaver

2
คุณช่วยฉันคืน!
Botea Florin

2
ขอบคุณ. ยังไงก็เถอะฉันผิดหวังว่านี่เป็นสิ่งจำเป็น แต่ฉันขอบคุณสำหรับคำแนะนำ!
งัด

9

สายไปหน่อย แต่สิ่งนี้อาจช่วยได้: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

โดยทั่วไปคุณจะต้องใส่html, bodyการheight: 100%; และห่อเนื้อหาทั้งหมดของคุณเป็น<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

.wrap {
  height: 100vh;
  display: flex;
}

ทำงานให้ฉัน หวังว่ามันจะช่วย


คุณควรระวังให้มากเมื่อใช้ "height: 100vh" เนื่องจากมาตรการต่างกันใน iOS Safari และ Android หนึ่งคำนึงถึงความสูงของแถบ URL และอื่น ๆ ไม่ได้
Sean Anderson

7

เพิ่มสิ่งนี้:

align-items: flex-start;

.content {}กฎสำหรับ ที่แก้ไขมันในปากกาของคุณสำหรับฉันอย่างน้อย (ทั้งใน Firefox และ Chrome)

โดยค่าเริ่มต้น.contentมีalign-items: stretchซึ่งทำให้ทุกขนาดเด็กอัตโนมัติสูงเพื่อให้ตรงกับความสูงของตัวเองต่อhttp://dev.w3.org/csswg/css-flexbox/#algo-stretch ในทางตรงกันข้ามค่าflex-startอนุญาตให้เด็กคำนวณความสูงของตนเองและจัดแนวตนเองที่ขอบเริ่มต้น (และล้นและเรียกแถบเลื่อน)


อย่างชัดเจน แต่แล้วพวกเขาไม่ได้ขยายไปถึงความสูงของผู้ปกครองเมื่อความสูงที่แท้จริงของพวกเขาคือสั้น
Joseph Silber

นอกจากนี้คอลัมน์จะไม่สูงเท่ากันอีกต่อไปซึ่งเป็นหนึ่งในจุดสนใจหลักของ flexbox
Joseph Silber

ตกลง. สำหรับฉันมันไม่ชัดเจนว่าเป็นข้อ จำกัด ในการออกแบบ - ขอโทษ
dholbert

ข้อเสนอแนะที่ดี
Vlad

1

ปัญหาหนึ่งที่ฉันเจอคือการมีแถบเลื่อนองค์ประกอบจะต้องระบุความสูง (และไม่ใช่%)

เคล็ดลับคือการซ้อนชุด divs อีกชุดในแต่ละคอลัมน์และตั้งค่าการแสดงผลของพาเรนต์ของคอลัมน์ให้ยืดหยุ่นด้วยทิศทางการโค้ง: คอลัมน์

    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }

    body {
        overflow-y: hidden;
        overflow-x: hidden;
        color: white;
    }

    .base-container {
        display: flex;
        flex: 1;
        flex-direction: column;
        width: 100%;
        height: 100%;
        overflow-y: hidden;
        align-items: stretch;
    }

    .title {
        flex: 0 0 50px;
        color: black;
    }

    .container {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
    }

        .container .header {
            flex: 0 0 50px;
            background-color: red;
        }

        .container .body {
            flex: 1 1 auto;
            display: flex;
            flex-direction: row;
        }

            .container .body .left {
                display: flex;
                flex-direction: column;
                flex: 0 0 80px;
                background-color: blue;
            }
                .container .body .left .content,
                .container .body .main .content,
                .container .body .right .content {
                    flex: 1 1 auto;
                    overflow-y: auto;
                    height: 100px;
                }
                .container .body .main .content.noscrollbar {
                    overflow-y: hidden;
                }

            .container .body .main {
                display: flex;
                flex-direction: column;
                flex: 1 1 auto;
                background-color: green;
            }

            .container .body .right {
                display: flex;
                flex-direction: column;
                flex: 0 0 300px;
                background-color: yellow;
                color: black;
            }

    .test {
        margin: 5px 5px;
        border: 1px solid white;
        height: calc(100% - 10px);
    }
</style>

และนี่คือ html:

<div class="base-container">
    <div class="title">
        Title
    </div>
    <div class="container">
        <div class="header">
            Header
        </div>
        <div class="body">
            <div class="left">
                <div class="content">
                    <ul>
                        <li>1</li>
                        <li>2</li>
                        <li>3</li>
                        <li>4</li>
                        <li>5</li>
                        <li>6</li>
                        <li>7</li>
                        <li>8</li>
                        <li>9</li>
                        <li>10</li>
                        <li>12</li>
                        <li>13</li>
                        <li>14</li>
                        <li>15</li>
                        <li>16</li>
                        <li>17</li>
                        <li>18</li>
                        <li>19</li>
                        <li>20</li>
                        <li>21</li>
                        <li>22</li>
                        <li>23</li>
                        <li>24</li>
                    </ul>
                </div>
            </div>
            <div class="main">
                <div class="content noscrollbar">
                    <div class="test">Test</div>
                </div>
            </div>
            <div class="right">
                <div class="content">
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>End</div>
                </div>
            </div>
        </div>
    </div>
</div>

https://jsfiddle.net/LiamFlavelle/czpjdfr4/


0

ทางออกสำหรับปัญหานี้คือการเพิ่ม overflow: auto;ให้กับ. เนื้อหาในการทำให้ตัวห่อเนื้อหาเลื่อนได้

นอกจากนี้ยังมีสถานการณ์ที่เกิดขึ้นพร้อมกับ Flexbox wrapper และoverflowedเนื้อหาที่เลื่อนได้เช่นนี้ codepenนี้

วิธีแก้ไขคือการเพิ่มพาเรนต์overflow: hidden (or auto);ของ wrapper (ตั้งค่าด้วย overflow: auto;) รอบเนื้อหาขนาดใหญ่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.