滚动内容溢出的Flexbox


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: autocontentdiv中

现在的问题是,列本身不会超出其父级的高度,因此边界也被切除。

这是显示滚动问题的笔

我如何设置content区域独立滚动,同时仍然让其子项超出content框的高度?

Answers:


263

我已经与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: stretch如果它们具有固有高度,则不会收缩其项,这可以通过完成min-content


3
通常,当父母的身高不取决于孩子的高度时,它们会起作用。最小高度:100%的确可以解决Firefox中的列均匀伸长问题(尽管在Chrome中不行)。不知道是Chrome错误还是Firefox错误。
dholbert

1
@dholbert-Tab Atkins帮助了我。我已经更新了答案。
约瑟夫·西尔伯

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的顶部一直隐藏,因此父级没有机会容纳它的子级,直到您到达要溢出和滚动的节点为止。
乔治,

3
我不确定这真的可以解释。将溢出设置为隐藏在元素上并不会阻止它扩展为包含其所有子元素AFAIK。根据MDN:“ overflow属性指定是在其块级容器溢出时是剪切内容,渲染滚动条还是仅显示内容。” 此外,将溢出设置为可见以外的任何内容都会创建新的块格式上下文-但这不相关,因为flex容器已经创建了自己的块格式上下文: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
谢谢。不知何故我对此感到失望,但我很感谢您的建议!
Mathias

9

有点晚了,但这可能会有所帮助:http : //webdesign.tutsplus.com/tutorials/how-to-make-sensitive-scrollable-panels-with-flexbox--cms-23269

基本上,你需要把htmlbodyheight: 100%; 和包装所有内容成<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

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

为我工作。希望能帮助到你


使用“高度:100vh”时应格外小心,因为它在iOS Safari和Android中的测量方式有所不同。一个考虑URL栏的高度,而另一个则不考虑。
肖恩·安德森

7

添加此:

align-items: flex-start;

遵守规则.content {}。至少(无论是Firefox还是Chrome),这都能为您解决。

默认情况下,.contenthas align-items: stretch可以根据http://dev.w3.org/csswg/css-flexbox/#algo-stretch调整其所有自动高度子项的大小以匹配其自身的高度。相反,该值flex-start可让子代计算自己的高度,并使其在其起始边缘对齐(并溢出,并触发滚动条)。



而且,列的高度不再相等,这是flexbox的主要吸引力之一。
约瑟夫·席尔伯

好。我不清楚这是设计上的限制-对不起。
dholbert 2014年

很棒的建议
弗拉德(Vlad)

1

我遇到的一个问题是要有一个滚动条,一个元素需要指定一个高度(而不是一个百分比)。

诀窍是在每列内嵌套另一组div,并将列父级的显示设置为使用flex-direction:column弯曲。

    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;到.content中,以使内容包装器可滚动。

此外,在某些情况下,Flexbox包装器和overflowed可滚动内容(如此Codepen)也会发生

解决方案是将overflow: hidden (or auto);大内容添加到包装器的父级(通过溢出设置:auto;)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.