滚动内容溢出的弹性框

Posted

技术标签:

【中文标题】滚动内容溢出的弹性框【英文标题】:Scrolling a flexbox with overflowing content 【发布时间】:2014-02-26 05:05:22 【问题描述】:

Here's the code我是用来实现上面的布局的:

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

我省略了用于样式的代码。您可以在the pen 中查看所有内容。


上述方法有效,但是当content 区域的内容溢出时,会导致整个页面滚动。我只希望内容区域本身滚动,所以I added overflow: auto to the content div。

现在的问题是列本身并没有超出其父级的高度,所以边界也被切断了。

Here's the pen showing the scrolling issue.

如何将content 区域设置为独立滚动,同时使其子项超出content 框的高度?

【问题讨论】:

【参考方案1】:

我没有在任何地方看到这个答案。但我需要的技巧是确保这些项目有一个flex-shrink: 0;否则他们会被挤压。

.container 
  display: flex;
  overflow: auto


.container > * 
  flex-shrink: 0;
  width: 10em;
  height: 10em;
  background: linear-gradient(to bottom right, #F0F, #0FF);
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

【讨论】:

【参考方案2】:

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

基本上您需要将html,body 放入height: 100%; 并将您的所有内容包装成&lt;div class="wrap"&gt; &lt;!-- content --&gt; &lt;/div&gt;

CSS:

html, body 
  height: 100%;

 
.wrap 
  height: 100vh;
  display: flex;

【讨论】:

在使用“height: 100vh”时应该非常小心,因为它在 ios Safari 和 android 中的测量方式不同。一种考虑 URL 栏的高度,另一种则不考虑。【参考方案3】:

使用position:absolute;flex

使用position: relative 定位弹性项目。然后在其中添加另一个 &lt;div&gt; 元素:

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

这会将元素扩展到其相对定位的父元素的边界,但不允许扩展它。在内部,overflow: auto; 将按预期工作。

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

最终结果:

CodePen Link

【讨论】:

如果内部组件设置了填充,则此解决方案特别有用,因为它将很好地将其锁定在您想要的任何位置。这要简单得多。 (是的,您可以改为设置 box-sizing: border-box,但对于某些第三方控件而言,这可能会更复杂)。【参考方案4】:

以下以粗体显示的 CSS 更改(加上列中的一堆内容以测试滚动)将起作用。好吧,它使每个内容列都可以单独滚动,这可能比最初要求的更多(更好?)。无论如何,请在this Pen 中查看结果。

.content 弹性:1;显示:弯曲; 高度:1px;

.column 填充:20px;右边框:1px 实心 #999; 溢出: 自动;

这里的技巧似乎是一个可滚动的面板需要有一个 height 字面上设置的地方(在这种情况下,通过它的父级),不是只是由 flexbox 确定。所以即使height: 1px 也有效。 flex-grow:1 仍将调整面板的大小以适合。

【讨论】:

【参考方案5】:

您可以简单地将溢出属性设置为“自动”

     .contain
          background-color: #999999;
          margin: 5px; 
          padding: 10px 5px;
          width: 20%;
          height: 20%;
          overflow: auto;
                    
       

contain 是我的弹性项目类名之一

结果:

scroll bar seen properly

【讨论】:

【参考方案6】:

您可以在position: relative 中使用position: absolute

https://codepen.io/Iquixe/pen/RwRzGrM

【讨论】:

【参考方案7】:
.list-wrap 
  width: 355px;
  height: 100%;
  position: relative;

  .list 
    position: absolute;
    top: 0;
    bottom: 0;
    overflow-y: auto;
    width: 100%;
  

【讨论】:

【参考方案8】:

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

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

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

【讨论】:

【参考方案9】:

解决这个问题的方法就是在 .content 中添加overflow: auto; 以使内容包装器可滚动。

此外,Flexbox 包装器和overflowed 可滚动内容(如codepen)也会发生一些情况。

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

【讨论】:

【参考方案10】:

我已经和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 */

这是笔:

    Short columns being stretched. Longer columns overflowing and scrolling。

之所以有效,是因为align-items: stretch 不会缩小它的项目,如果它们具有固有高度,这是由min-content 在这里完成的。

【讨论】:

通常,当父母的身高不依赖于其孩子时,它们会起作用,这里就是这种情况。 min-height: 100% 确实可以解决您在 Firefox 中的拉伸甚至列短问题(尽管在 Chrome 中没有)。不确定这是 Chrome 错误还是 Firefox 错误。 @dholbert - Tab Atkins 帮我解决了这个问题。我已经更新了我的答案。 请注意,Firefox 目前只支持宽度值的“最小内容”,而不是高度值——所以这在 Firefox 中不起作用,如果这对你很重要的话。 (参见例如bugzilla.mozilla.org/show_bug.cgi?id=852367) @dholbert - 这些笔的问题在于它们是公开的,所以任何人都可以更改它们。我拥有它们,所以你去:codepen.io/JosephSilber/pen/pmyHh 是的,这在 IE11 中被破坏了【参考方案11】:

添加这个:

align-items: flex-start;

.content 的规则。至少(在 Firefox 和 Chrome 中),这对我来说是在你的笔中修复的。

默认情况下,.content 具有 align-items: stretch,这使得它的所有自动高度子项的大小都与自己的高度相匹配,根据 http://dev.w3.org/csswg/css-flexbox/#algo-stretch。相比之下,flex-start 值让孩子们计算自己的高度,并在起点边缘对齐(并溢出,并触发滚动条)。

【讨论】:

显然。但随后they don't extend to the parent's height when their intrinsic height is shorter. 另外,列不再等高,这是 flexbox 的主要吸引力之一。 好的。我不清楚这是一个设计限制——抱歉。【参考方案12】:

经过多次反复试验,我刚刚非常优雅地解决了这个问题。

查看我的博文:http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

基本上,要使 flexbox 单元格可滚动,您必须使其所有 父级 overflow: hidden;,否则它会忽略您的溢出设置并让父级变大。

【讨论】:

这在我的情况下也很有效,但是哇,我真的很想看看它为什么有效的解释。大多数时候,我发现 CSS 规范对于这类事情是完全不可理解的。 来自您的博文:“我不知道为什么会这样,而且规格也没有说明”。所以,我正在寻找它为什么起作用的解释。我浏览了规格,但正如你所说,没有任何东西跳出来。 再想一想,觉得有道理。默认行为是每个 div 展开以包含它的所有子节点,因此不会有任何溢出来隐藏在叶节点处。您需要强制 overflow:hidden 从 DOM 的顶部一直隐藏,因此在您到达要溢出和滚动的节点之前,没有父级有机会容纳它的子级。 我不确定这是否真的能解释它。在元素上将溢出设置为隐藏并不能阻止它扩展以包含其所有子元素,AFAIK。根据 MDN:“overflow 属性指定在溢出其块级容器时是否剪切内容、呈现滚动条或仅显示内容。”此外,将溢出设置为可见以外的任何内容都会创建一个新的块格式化上下文 - 但这不相关,因为 flex 容器已经创建了自己的块格式化上下文:developer.mozilla.org/en-US/docs/Web/Guide/CSS/…。 我应该补充一点,我同意您的解释直观有道理,但我认为这不是一个准确的技术解释,这就是我想。只有真正明白了原因,以后才能记住解决办法!

以上是关于滚动内容溢出的弹性框的主要内容,如果未能解决你的问题,请参考以下文章

如何在不给定高度的情况下使内容在弹性框中可滚动?

【Flutter】图片、内容、滚动空间溢出调整

大于动态宽度父项时,弹性项目上的滚动条

防止内容在 flexbox 模态中溢出超出滚动范围

flex容器内的居中元素正在增长并溢出顶部[重复]

flex容器内的居中元素正在增长并溢出顶部[重复]