Cuộn một flexbox với nội dung tràn


214

nhập mô tả hình ảnh ở đây

Đây là mã tôi đang sử dụng để đạt được bố cục trên:

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

Tôi đã bỏ qua mã được sử dụng để tạo kiểu. Bạn có thể thấy tất cả trong bút .


Các công việc trên, nhưng khi contentnội dung của khu vực tràn ra, nó làm cho toàn bộ trang cuộn. Tôi chỉ muốn vùng nội dung chính để cuộn, vì vậy tôi đã thêm overflow: autovào contentdiv .

Vấn đề với điều này bây giờ là các cột không vượt quá chiều cao của cha mẹ chúng, do đó, các đường viền cũng bị cắt ở đó.

Đây là cây bút cho thấy vấn đề cuộn .

Làm cách nào tôi có thể thiết lập contentkhu vực để cuộn độc lập, trong khi vẫn có con của nó vượt quá contentchiều cao của hộp?

Câu trả lời:


263

Tôi đã nói chuyện với Tab Atkins (tác giả của thông số flexbox) về điều này và đây là những gì chúng tôi đã đưa ra:

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

Đây là những cây bút:

  1. Các cột ngắn được kéo dài .
  2. Cột dài hơn tràn và cuộn .

Lý do điều này hoạt động là vì align-items: stretchkhông thu nhỏ các mục của nó nếu chúng có chiều cao nội tại, được thực hiện ở đây bằng cách min-content.


3
Chúng hoạt động khi chiều cao của cha mẹ không phụ thuộc vào con cái, nói chung, đó là trường hợp ở đây. min-height: 100% thực sự khắc phục sự cố kéo dài ngay cả khi cột của bạn trong Firefox (mặc dù không có trong Chrome). Không chắc chắn nếu đó là lỗi Chrome hoặc lỗi Firefox.
dholbert

1
@dholbert - Tab Atkins đã giúp tôi điều này. Tôi đã cập nhật câu trả lời của mình.
Joseph Silber

3
Lưu ý rằng Firefox hiện chỉ hỗ trợ "nội dung tối thiểu" cho các giá trị độ rộng, không phải giá trị chiều cao - vì vậy điều này sẽ không hoạt động trong Firefox, nếu điều đó quan trọng với bạn. (Xem ví dụ bugzilla.mozilla.org/show_orms.cgi?id=852367 )
dholbert

2
@dholbert - Vấn đề với những cây bút này là chúng được công khai, vì vậy bất kỳ ai cũng có thể thay đổi chúng. Tôi đã sở hữu chúng, vì vậy bạn hãy vào đây: codepen.io/JosephSilber/pen/pmyHh
Joseph Silber

5
Vâng, điều này đã bị hỏng trong IE11
Steve

119

Tôi chỉ giải quyết vấn đề này rất thanh lịch sau rất nhiều thử nghiệm và sai sót.

Kiểm tra bài đăng trên blog của tôi: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

Về cơ bản, để làm cho một ô flexbox có thể cuộn được, bạn phải tạo tất cả các cha mẹ của nó overflow: hidden;, hoặc nó sẽ chỉ bỏ qua các cài đặt tràn của bạn và thay vào đó làm cho cha mẹ lớn hơn.


11
Điều này cũng có tác dụng trong trường hợp của tôi, nhưng wow, tôi thực sự muốn xem một lời giải thích tại sao nó hoạt động. Hầu hết thời gian, tôi thấy các thông số kỹ thuật CSS là hoàn toàn không thể hiểu được cho loại điều này.
markrian 8/11/2016

2
Từ bài đăng trên blog của bạn: "Tôi không biết tại sao nó lại hoạt động và thông số kỹ thuật cũng không nói gì cả" . Vì vậy, tôi đang tìm kiếm một lời giải thích tại sao nó hoạt động. Tôi đã lướt qua các thông số kỹ thuật, nhưng như bạn nói, không có gì nhảy ra khỏi đó.
markrian 10/11/2016

3
Sau khi nghĩ về nó nhiều hơn, tôi nghĩ rằng nó có ý nghĩa. Hành vi mặc định là cho mỗi div mở rộng để chứa tất cả các phần tử con của nó, vì vậy sẽ không có bất kỳ lỗi tràn nào để ẩn tại các nút lá. Bạn cần buộc tràn: ẩn tất cả các cách từ đỉnh DOM, vì vậy không có cha mẹ nào có cơ hội chứa con của nó cho đến khi bạn xuống nút bạn muốn tràn và cuộn.
geon

3
Tôi không chắc điều đó thực sự giải thích nó. Đặt tràn thành ẩn trên một phần tử không ngăn nó mở rộng để chứa tất cả các phần tử con của nó, AFAIK. Theo MDN: "Thuộc tính tràn chỉ định xem có nên cắt nội dung, kết xuất thanh cuộn hay chỉ hiển thị nội dung khi nó tràn bộ chứa mức khối của nó." Ngoài ra, việc đặt tràn sang bất cứ thứ gì khác ngoài khả năng hiển thị sẽ tạo bối cảnh định dạng khối mới - nhưng điều đó không liên quan, vì các thùng chứa flex đã tạo bối cảnh định dạng khối riêng của họ: developer.mozilla.org/en-US/docs/Web/Guide / CSS / ' .
markrian

1
Tôi nên nói thêm rằng tôi đồng ý lời giải thích của bạn có ý nghĩa trực quan , nhưng tôi không nghĩ đó là một lời giải thích kỹ thuật chính xác , đó là điều tôi muốn. Chỉ khi thực sự hiểu lý do, tôi mới có thể nhớ được giải pháp trong tương lai!
markrian

55

Làm việc position:absolute;cùng với flex:

Định vị mục flex với position: relative. Sau đó, bên trong nó, thêm một <div>yếu tố khác với:

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

Điều này mở rộng phần tử đến ranh giới của cha mẹ có vị trí tương đối của nó, nhưng không cho phép mở rộng nó. Bên trong, overflow: auto;sau đó sẽ làm việc như mong đợi.

  • đoạn mã được bao gồm trong câu trả lời - Nhấp vào nhập mô tả hình ảnh ở đâyvà sau đó nhấp vào Toàn trangsau khi chạy đoạn mã HOẶC
  • Bấm vào đây để CODEPEN
  • Kết quả: nhập mô tả hình ảnh ở đây

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

Chúc may mắn...


2
Giải pháp này đặc biệt hữu ích nếu thành phần bên trong có bộ đệm vì nó sẽ khóa độc đáo ở vị trí bất cứ nơi nào bạn muốn. Nó đơn giản hơn nhiều. (Có, bạn có thể đặt box-sizing: border-boxthay thế nhưng điều đó có thể phức tạp hơn đối với các điều khiển của bên thứ ba nhất định).
Simon_Weaver

2
bạn đã cứu đêm của tôi
Botea Florin

2
Cảm ơn bạn. Bằng cách nào đó tôi thất vọng vì điều này là cần thiết, nhưng tôi biết ơn lời khuyên!
Mathias

9

Hơi muộn một chút nhưng điều này có thể giúp: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

Về cơ bản bạn cần đặt html, bodyđể height: 100%; và bọc tất cả nội dung của bạn vào một<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

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

Đã làm cho tôi. Hy vọng nó giúp


Bạn nên rất cẩn thận khi sử dụng "height: 100vh" vì nó đo khác nhau trong iOS Safari so với Android. Một cái tính đến chiều cao của thanh URL còn cái kia thì không.
Sean Anderson

7

Thêm điều này:

align-items: flex-start;

theo quy tắc cho .content {}. Điều đó sửa nó trong bút của bạn, ít nhất là (trong cả Firefox và Chrome).

Theo mặc định, .contentalign-items: stretch, làm cho nó có kích thước tất cả trẻ em có chiều cao tự động để phù hợp với chiều cao của chính nó, theo http://dev.w3.org/csswg/css-flexbox/#algo-stretch . Ngược lại, giá trị flex-startcho phép trẻ em tự tính toán độ cao của mình và căn chỉnh chính chúng ở cạnh bắt đầu của nó (và tràn, và kích hoạt một thanh cuộn).



Ngoài ra, các cột sẽ không còn bằng nhau nữa, đây là một trong những điểm thu hút chính của flexbox.
Joseph Silber

ĐỒNG Ý. Tôi không rõ ràng rằng đó là một hạn chế thiết kế - xin lỗi.
dholbert

Gợi ý tuyệt vời
Vlad

1

Một vấn đề mà tôi gặp phải là để có một thanh cuộn, một yếu tố cần có chiều cao được chỉ định (và không phải là%).

Mẹo nhỏ là lồng một bộ div khác trong mỗi cột và đặt màn hình của cột cha thành flex với hướng flex: cột.

    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>

Và đây là 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

Giải pháp cho vấn đề này chỉ là thêm overflow: auto;vào .content để làm cho trình bao bọc nội dung có thể cuộn được.

Hơn nữa, có những trường hợp xảy ra cùng với trình bao bọc Flexbox và overflowednội dung có thể cuộn như codepen này .

Giải pháp là thêm overflow: hidden (or auto);vào cha mẹ của trình bao bọc (được đặt với tràn: auto;) xung quanh nội dung lớn.

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.