ChatGPT解决这个技术问题 Extra ChatGPT

Scrolling a flexbox with overflowing content

https://i.stack.imgur.com/LzsBQ.png

Here's the code I'm using to achieve the above layout:

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

Main header
Column 1
Column 1
Column 1

I omitted the code used for styling. You can see all of it in the pen.

The above works, but when the content area's content overflows, it makes the whole page scroll. I only want the content area itself to scroll, so I added overflow: auto to the content div.

The problem with this now is that the columns themselves don't extend beyond their parents height, so the borders are cut off there too.

Here's the pen showing the scrolling issue.

How can I set the content area to scroll independently, while still having its children extend beyond the content box's height?


K
K-Gun

I've spoken to Tab Atkins (author of the flexbox spec) about this, and this is what we came up with:

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

Here are the pens:

Short columns being stretched. Longer columns overflowing and scrolling.

The reason this works is because align-items: stretch doesn't shrink its items if they have an intrinsic height, which is accomplished here by min-content.


They work when the parent's height doesn't depend on its children, generally, which is the case here. min-height: 100% does indeed fix your stretch-even-when-columns-are-short issue in Firefox (though not in Chrome). Not sure offhand if that's a Chrome bug or a Firefox bug.
Note that Firefox currently only supports "min-content" for width values, not height values -- so this won't work in Firefox, if that matters to you. (See e.g. bugzilla.mozilla.org/show_bug.cgi?id=852367 )
@dholbert - The problem with these pens is that they were public, so anybody could change them. I took ownership of them, so here you go: codepen.io/JosephSilber/pen/pmyHh
Yes, this is broken in IE11
But probably a good idea to also point to stackoverflow.com/a/35609992/740553, below, because that's a solid solution for all those cases where this isn't (although if someone knows why it works, as "here are the parts of the CSS/Flex specs that cause this to be true" explanation, all of SO and the wider web dev world would still greatly benefit from one =)
g
geon

I just solved this problem very elegantly after a lot of trial and error.

Check out my blog post: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

Basically, to make a flexbox cell scrollable, you have to make all its parents overflow: hidden;, or it will just ignore your overflow settings and make the parent larger instead.


This worked in my case as well, but wow, I'd really like to see an explanation of why it works. Most of the time, I find the CSS specs to be totally inscrutable for this kind of thing.
From your blog post: "I have no idea why that works, and the specs says nothing either". So, I'm looking for an explanation of why it works. I've skimmed the specs, but as you said, nothing jumps out there.
After thinking about it some more, I think it makes sense. The default behaviour is for each div to expand to contain all of it's children, so there won't be any overflow to hide at the leaf nodes. You need to force overflow:hidden all the way from the top of the DOM, so no parent has the chance to accommodate it's children until you are down to the node you want to overflow and scroll.
I'm not sure that really explains it. Setting overflow to hidden on an element doesn't stop it from expanding to contain all of its children, AFAIK. According to MDN: "The overflow property specifies whether to clip content, render scrollbars or just display content when it overflows its block level container." Additionally, setting overflow to anything other than visible creates a new block formatting context - but that can't be relevant, because flex containers already create their own block formatting context: developer.mozilla.org/en-US/docs/Web/Guide/CSS/….
I found the technical reason here and then officially here (CSS spec). Basically, changing the overflow changes the min height automatic value. Try replacing the overflow hidden with overflow auto or min height 0. All should still work and the later should be preferred (or at least I understand that after reading the spec).
A
Aakash

Working with position:absolute; along with flex:

Position the flex item with position: relative. Then inside of it, add another <div> element with:

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

This extends the element to the boundaries of its relative-positioned parent, but does not allow to extend it. Inside, overflow: auto; will then work as expected.

.all-0 { top: 0; bottom: 0; left: 0; right: 0; } p { text-align: justify; } .bottom-0 { bottom: 0; } .overflow-auto { overflow: auto; }

Heading 1

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

Heading 1

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

Heading 1

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

Heading 1

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

Heading 1

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

Social Sidebar...


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

https://i.stack.imgur.com/JRlS8.png

CodePen Link


This solution is especially useful if the component inside has padding set because it will lock it nicely in position wherever you want. It's much simpler. (Yes you could set box-sizing: border-box instead but that can be more complex for certain third party controls).
T
TylerH

A little late but this could help: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

Basically you need to put html,body to height: 100%; and wrap all your content into a <div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}
 
.wrap {
  height: 100vh;
  display: flex;
}

You should be very careful when using "height: 100vh" as it measures differently in iOS Safari vs Android. One takes into account the height of the URL bar and the other does not.
this only works if the thing you want to scroll is the full height of the screen. If you add (for example) a header div you're back to square one
C
Chris Janicki

The following CSS changes in bold (plus a bunch of content in the columns to test scrolling) will work. Well, it makes each content column individually scrollable, which may be more (better?) than originally requested. Anyway, see the result in this Pen.

.content { flex: 1; display: flex; height: 1px; } .column { padding: 20px; border-right: 1px solid #999; overflow: auto; }

The trick here seems to be that a scrollable panel needs to have a height literally set somewhere (in this case, via its parent), not just determined by flexbox. So even height: 1px works. The flex-grow:1 will still size the panel to fit properly.


a
amoebe

Add this:

align-items: flex-start;

to the rule for .content {}. That fixes it in your pen for me, at least (in both Firefox & Chrome).

By default, .content has align-items: stretch, which makes it size all of its auto-height children to match its own height, per http://dev.w3.org/csswg/css-flexbox/#algo-stretch. In contrast, the value flex-start lets the children compute their own heights, and align themselves at its starting edge (and overflow, and trigger a scrollbar).


Also, the columns won't be equal height anymore, which is one of the main attractions of flexbox.
OK. It wasn't clear to me that that was a design constraint -- sorry.
S
Seph Reed

I didn't see this answer anywhere. But the trick I needed was to make sure the items had a flex-shrink: 0; else they'll get squeezed.

.container { display: flex; overflow: auto } .container > * { flex-shrink: 0; width: 10em; height: 10em; background: linear-gradient(to bottom right, #F0F, #0FF); }


thank you so much. i have a layout that uses min-height: 0 on all flex containers to allow children to be scrollable. that caused some things to shrink and overlap, but your .container > * thing fixed it
L
Liam

One issue that I've come across is that to have a scrollbar a n element needs a height to be specified (and not as a %).

The trick is to nest another set of divs within each column, and set the column parent's display to flex with flex-direction: column.

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

And here's the 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/


D
Dognose

The solution for this problem is just to add overflow: auto; to the .content for making the content wrapper scrollable.

Furthermore, there are circumstances occurring along with Flexbox wrapper and overflowed scrollable content like this codepen.

The solution is to add overflow: hidden (or auto); to the parent of the wrapper (set with overflow: auto;) around large contents.


z
zhishaofei3
.list-wrap {
  width: 355px;
  height: 100%;
  position: relative;

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

L
Liam

I tried a lot of the answers above without much joy. I suspect that a lot of these answers are out of date or just didn't fit my requirements. The answer to my problem came from a related question:

The Automatic Minimum Size of Flex Items You're encountering a flexbox default setting. A flex item cannot be smaller than the size of its content along the main axis.

So the thing that was preventing my flex box item from scrolling was that the size of the element would automatically adjust to auto based on the content and then resize, not scroll. Here's a fully working modern example (using tailwind):

Header

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque feugiat libero id elementum iaculis. Vestibulum at mauris mauris. Donec blandit nibh rhoncus mollis mattis. Aenean gravida ex sagittis semper aliquet. Suspendisse a dolor enim. Fusce sagittis lectus et eleifend imperdiet. Curabitur iaculis pellentesque rutrum. Fusce et gravida eros. Nam vestibulum pharetra lorem, sed semper leo fermentum nec.

Curabitur varius feugiat maximus. Morbi dolor urna, consectetur ac nisl eget, varius pretium sem. Curabitur aliquam, lectus ut viverra consequat, dolor ligula gravida ex, nec dictum felis mi in enim. Curabitur luctus ligula diam, sed varius orci vehicula a. Ut vehicula imperdiet tempor. Morbi eget sollicitudin mi. Etiam condimentum sem arcu, non dignissim mi ultricies ut. Fusce faucibus sem nec laoreet facilisis. Nullam ut lorem vitae odio gravida rhoncus. Etiam ut orci vitae odio interdum consequat.

Sed felis dui, fermentum ac libero ut, faucibus mattis urna. Morbi at est lobortis, lobortis diam nec, rhoncus augue. Sed at turpis malesuada nulla accumsan accumsan. Mauris pharetra, odio at elementum pharetra, lacus magna luctus sem, sit amet pretium lorem lectus sed libero. Curabitur ullamcorper turpis nunc, a eleifend urna venenatis ac. Vivamus consectetur, nunc quis facilisis vehicula, risus ligula finibus arcu, at vulputate ex dui lobortis dolor. Maecenas tincidunt, lacus et vehicula pulvinar, enim sem venenatis nisi, nec fringilla eros felis quis mauris. Duis luctus eu risus condimentum rutrum. Suspendisse interdum at velit eget mattis. Integer quis porta nisl. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc iaculis, lacus ut dignissim imperdiet, enim enim malesuada quam, id pretium justo neque id ipsum. Vestibulum nec nisl mattis, mattis est sed, venenatis lectus. Quisque sed magna nec purus viverra rhoncus dapibus sed sapien. Quisque id fermentum risus, non vestibulum justo. Donec ultrices enim quis eros porttitor, non posuere tortor viverra.

Phasellus leo ipsum, tristique nec tristique sit amet, molestie eget urna. Aenean suscipit eget ante in vulputate. Morbi tincidunt velit quis lorem gravida, ac scelerisque massa aliquet. Aliquam sem lacus, bibendum ut elit at, mollis dapibus ligula. Suspendisse potenti. Fusce neque est, lobortis a augue a, pretium fermentum turpis. Etiam molestie et odio non rhoncus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus condimentum cursus metus eu hendrerit. Vestibulum ultrices, leo eget consectetur tempus, nisi diam maximus orci, sit amet ultricies leo mauris vitae eros.

Aenean eleifend pretium libero ut venenatis. Quisque maximus nulla eget arcu maximus, id rhoncus lectus lobortis. Nullam at ullamcorper nisi. Aliquam erat volutpat. Curabitur efficitur ante in fermentum euismod. Donec id arcu finibus, finibus mauris id, tempor nisl. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam lobortis feugiat ligula, id aliquet elit placerat ut. In ac mi elementum, varius urna a, condimentum urna. Sed luctus massa nulla, quis elementum sapien lacinia eu. Vestibulum risus leo, rutrum ac finibus in, iaculis at ligula. Nullam hendrerit mattis eleifend. Sed egestas lectus eu vulputate malesuada.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque feugiat libero id elementum iaculis. Vestibulum at mauris mauris. Donec blandit nibh rhoncus mollis mattis. Aenean gravida ex sagittis semper aliquet. Suspendisse a dolor enim. Fusce sagittis lectus et eleifend imperdiet. Curabitur iaculis pellentesque rutrum. Fusce et gravida eros. Nam vestibulum pharetra lorem, sed semper leo fermentum nec.

Curabitur varius feugiat maximus. Morbi dolor urna, consectetur ac nisl eget, varius pretium sem. Curabitur aliquam, lectus ut viverra consequat, dolor ligula gravida ex, nec dictum felis mi in enim. Curabitur luctus ligula diam, sed varius orci vehicula a. Ut vehicula imperdiet tempor. Morbi eget sollicitudin mi. Etiam condimentum sem arcu, non dignissim mi ultricies ut. Fusce faucibus sem nec laoreet facilisis. Nullam ut lorem vitae odio gravida rhoncus. Etiam ut orci vitae odio interdum consequat.

Sed felis dui, fermentum ac libero ut, faucibus mattis urna. Morbi at est lobortis, lobortis diam nec, rhoncus augue. Sed at turpis malesuada nulla accumsan accumsan. Mauris pharetra, odio at elementum pharetra, lacus magna luctus sem, sit amet pretium lorem lectus sed libero. Curabitur ullamcorper turpis nunc, a eleifend urna venenatis ac. Vivamus consectetur, nunc quis facilisis vehicula, risus ligula finibus arcu, at vulputate ex dui lobortis dolor. Maecenas tincidunt, lacus et vehicula pulvinar, enim sem venenatis nisi, nec fringilla eros felis quis mauris. Duis luctus eu risus condimentum rutrum. Suspendisse interdum at velit eget mattis. Integer quis porta nisl. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc iaculis, lacus ut dignissim imperdiet, enim enim malesuada quam, id pretium justo neque id ipsum. Vestibulum nec nisl mattis, mattis est sed, venenatis lectus. Quisque sed magna nec purus viverra rhoncus dapibus sed sapien. Quisque id fermentum risus, non vestibulum justo. Donec ultrices enim quis eros porttitor, non posuere tortor viverra.

Phasellus leo ipsum, tristique nec tristique sit amet, molestie eget urna. Aenean suscipit eget ante in vulputate. Morbi tincidunt velit quis lorem gravida, ac scelerisque massa aliquet. Aliquam sem lacus, bibendum ut elit at, mollis dapibus ligula. Suspendisse potenti. Fusce neque est, lobortis a augue a, pretium fermentum turpis. Etiam molestie et odio non rhoncus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus condimentum cursus metus eu hendrerit. Vestibulum ultrices, leo eget consectetur tempus, nisi diam maximus orci, sit amet ultricies leo mauris vitae eros.

Aenean eleifend pretium libero ut venenatis. Quisque maximus nulla eget arcu maximus, id rhoncus lectus lobortis. Nullam at ullamcorper nisi. Aliquam erat volutpat. Curabitur efficitur ante in fermentum euismod. Donec id arcu finibus, finibus mauris id, tempor nisl. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam lobortis feugiat ligula, id aliquet elit placerat ut. In ac mi elementum, varius urna a, condimentum urna. Sed luctus massa nulla, quis elementum sapien lacinia eu. Vestibulum risus leo, rutrum ac finibus in, iaculis at ligula. Nullam hendrerit mattis eleifend. Sed egestas lectus eu vulputate malesuada.

https://i.stack.imgur.com/AzXx3.png