How to make a flexbox container to scroll? - html

I have a vertical flexbox container on which I set a specific height and set it to scroll vertically when overflows. The problem is that the flex container won't scroll if its content overflows. Here is a plunker that demonstrate what i'm talking about: http://plnkr.co/edit/3t4cuxMSGuNr88u0Whdl?p=preview.
.flex-container {
display: flex;
flex-direction: column;
overflow-y: scroll;
height: 600px;
width: 400px;
}
.block-container {
overflow-y: scroll;
height: 600px;
width: 400px;
margin-left: 50px;
}
.item1 {
height: 200px;
background-color: red;
margin-bottom: 1px;
}
.item2 {
height: 200px;
background-color: green;
margin-bottom: 1px;
}
.item3 {
height: 200px;
background-color: blue;
margin-bottom: 1px;
}
<div style="display: flex">
<div class="flex-container">
<p>Flex Container</p>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
</div>
<div class="block-container">
<p>Block Container</p>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
<div class="item1">Text</div>
<div class="item2">Text</div>
<div class="item3">Text</div>
</div>
</div>
As you can see, I have there two identical boxes - the first one is a flex-box (display: flex) and the other one is a block-box (display: block). I set the height for both of them, but the flexbox will shrink its items to fit its contents inside the height boundaries, while the block-box will just scroll. How can I force the flexbox not to shrink its items and to behave like the block-box in that sense?
Thanks.

Try, set a flex-basis value, and make it to not grow or shrink:
.item1, .item2, .item3 {
flex: 0 0 200px;
}
Or, flex: 1 0 200px; if you do need them to grow as needed.
jsFiddle

You can always provide min-height and flex will respect that. See the updated Plunkr
http://plnkr.co/edit/7rgo7BpWWtXsQqYbJvdU?p=preview

Related

Have flex children only use space if they need it to not scroll, but otherwise share space equally and scroll

I have two flex children that may either each be small or large, and I'm defining small as < 50% of the container's height and large as > 50% the container's height. The sum of the heights of the children may be larger than 100% of the container's height, in which case I'd want one or both to scroll.
If one child is small and the other is large, I'd like the small element to use exactly the space it needs: it should not shrink to accommodate the large element, nor grow to 50%, and it should not scroll its contents. I'd like the large element to use the rest of the space, and scroll its contents if necessary.
If both are large, I'd like them to each use 50% of the container's height and scroll their contents.
I have this Codepen started as an example to help illustrate what I'm trying to achieve, but unfortunately it currently does no amount of scrolling or resizing: https://codepen.io/joeysilva/pen/wvmPqLK. It has both a small-large and a large-large case.
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
display: inline-block;
overflow: hidden;
}
.child {
flex: 50%;
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
<div class="large">Large 2</div>
</div>
</div>
Note 1: Not use disply:inline-block and display:flex the same time. Simply add another wrapper to show elements inside a row or column.
Note 2: flex: 50%; is equivalent to flex: 1 1 50%; and this is the shorthand form of flex-grow: 1; flex-shrink: 1; flex-basis: 50%;. Here in your code no need to use them because you have strictly defined the height of elements and also the basis of 50% height is wrong since you'd like the small element to use exactly the space it needs; no grow & no shrink, so it should be omitted.
.wrapper {
display: flex;
flex-direction: row;
}
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.child {
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="wrapper">
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
</div>
<div class="child">
<div class="large">Large 2</div>
</div>
</div>
</div>

How can I wrap columns vertically when their width doesn't fit their containers? [duplicate]

This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed 4 years ago.
I have problem with flexbox wrapping into column. The container doesn't fit the content width as seen in the snippet below.
This works if you replace both flex-flow of .wrapper and .container with flex-flow: row wrap, the height fit the content height its children, but the problem then is that the columns then flow horizontally and appear under each other, rather than flowing vertically and beside each other.
I expect the following result:
.wrapper {
display: flex;
flex-flow: column wrap;
max-height: 500px;
max-width: 500px;
overflow: scroll;
}
.container {
display: flex;
flex-flow: column wrap;
align-content: flex-start;
background-color: red;
margin: 5px;
}
.product {
margin: 3px;
min-width: 100px;
min-height: 100px;
background-color: #ccc;
text-align: center;
font-weight: bold;
line-height: 100px;
}
<div class='wrapper'>
<div class='container'>
<div class="product">0.1</div>
<div class="product">0.2</div>
<div class="product">0.3</div>
<div class="product">0.4</div>
<div class="product">0.5</div>
<div class="product">0.6</div>
<div class="product">0.7</div>
<div class="product">0.8</div>
</div>
<div class='container'>
<div class="product">1.1</div>
<div class="product">1.2</div>
<div class="product">1.3</div>
<div class="product">1.4</div>
<div class="product">1.5</div>
<div class="product">1.6</div>
<div class="product">1.7</div>
<div class="product">1.8</div>
</div>
<div class='container'>
<div class="product">2.1</div>
<div class="product">2.2</div>
<div class="product">2.3</div>
<div class="product">2.4</div>
<div class="product">2.5</div>
<div class="product">2.6</div>
<div class="product">2.7</div>
<div class="product">2.8</div>
</div>
<div class='container'>
<div class="product">3.1</div>
<div class="product">3.2</div>
<div class="product">3.3</div>
<div class="product">3.4</div>
<div class="product">3.5</div>
<div class="product">3.6</div>
<div class="product">3.7</div>
<div class="product">3.8</div>
</div>
</div>
The problem is that the .container doesn't have a width defined, so how .wrapper does have a maximum of with and it's a Flexbox, all the children (.container) will fit automatically to their parent, that's the problem.
You can solve it by setting a with to the container class.
Something like this: width: 212px;

How to use flexbox inside a fixed container?

I have a div that is position: fixed; within the viewport. Within this are a series of child elements that use display: flex; and I need a scrollable element to fill 100% of the height of the flexed element. The problem I am having is that because done of the parent elements of the scrollable element have a fixed height, so the scrollable element just pushed the bottom of the flexed element rather than scroll.
Please see the following JSBin example. In this example, the blue block needs to extend to 100% the height of the red block, with the contents of the blue block still being scrollable. Needs to work in IE10+, latest Firefox and Chrome:
https://jsbin.com/terimim/edit?html,css,output
There are two primary issues causing the layout problem. They are each explained here:
Why doesn't flex item shrink past content size?
Chrome / Safari not filling 100% height of flex parent
revised demo
* {
box-sizing: border-box;
min-height: 0;
}
body {
background-color: #eaeaea;
}
#menu {
background-color: #fff;
position: fixed;
top: 20px;
right: 20px;
left: 20px;
bottom: 20px;
padding: 0;
z-index: 12;
height: calc(100vh - 40px);
}
#menu-contents {
display: flex;
flex-direction: column;
height: 100%;
}
#menu-pane-wrapper {
display: flex;
flex: 1;
background-color: #eeffcc;
}
#menu-panes {
flex: 1;
display: flex;
}
.menu-pane {
box-sizing: border-box;
background-color: #ff0000;
width: 20%;
padding: 10px;
display: flex;
}
.menu-pane-overflow {
flex: 1;
overflow-x: hidden;
overflow-y: scroll;
background-color: aqua;
}
.menu-item {
padding: 5px;
}
<div id="menu">
<div id="menu-contents">
<div id="menu-header">HEADER</div>
<div id="menu-pane-wrapper">
<div id="menu-panes">
<div class="menu-pane">
<div class="menu-pane-overflow">
<div class="menu-pane-scroll">
<div class="menu-item">1</div>
<div class="menu-item">2</div>
<div class="menu-item">3</div>
<div class="menu-item">4</div>
<div class="menu-item">5</div>
<div class="menu-item">6</div>
<div class="menu-item">7</div>
<div class="menu-item">8</div>
<div class="menu-item">9</div>
<div class="menu-item">10</div>
<div class="menu-item">11</div>
<div class="menu-item">12</div>
<div class="menu-item">13</div>
<div class="menu-item">14</div>
<div class="menu-item">15</div>
<div class="menu-item">16</div>
<div class="menu-item">17</div>
<div class="menu-item">18</div>
<div class="menu-item">19</div>
<div class="menu-item">20</div>
<div class="menu-item">21</div>
<div class="menu-item">22</div>
<div class="menu-item">23</div>
<div class="menu-item">24</div>
<div class="menu-item">25</div>
<div class="menu-item">26</div>
<div class="menu-item">27</div>
<div class="menu-item">28</div>
<div class="menu-item">29</div>
<div class="menu-item">30</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Nested Flexbox with horizontal overflow

I am using a nested flexbox layout.
I would like a left nav to always be 1/3rd of the page, and the right side always be 2/3rds.
The left nav should always stay in view.
The right side (an image carousel in my case) should always take up 2/3rds and have a horizontal scrollbar on the boxes.
In the code below, it simply stretches and ignores the overflow.
<div>
Top Header (should stay in view)
</div>
<div style="display: flex">
<div style="flex: 1 0 auto">
LeftNav
</div>
<div style="flex: 2 0 auto">
<div style="display: flex; flex-direction: row; overflow-x: scroll">
<div style="background-color: blue; min-width: 400px; height: 500px">
</div>
<div style="background-color: red; min-width: 400px; height: 500px">
</div>
<div style="background-color: green; min-width: 400px; height: 500px">
</div>
</div>
</div>
Instead of flex-grow, which simply distributes free space in the container, use flex-basis, which explicitly sizes your items 1/3 and 2/3.
Then, because the default minimum width of flex items is min-width: auto, meaning they cannot be smaller than the size of their content, use min-width: 0 to override that default on the carousel.
<div>
Top Header (should stay in view)
</div>
<div style="display: flex">
<div style="flex: 0 0 33%">LeftNav</div>
<div style="flex: 0 0 67%; min-width: 0;">
<div style="display: flex; flex-direction: row; overflow-x: scroll">
<div style="background-color: blue; min-width: 400px; height: 500px">
</div>
<div style="background-color: red; min-width: 400px; height: 500px">
</div>
<div style="background-color: green; min-width: 400px; height: 500px">
</div>
</div>
</div>
First, I've moved your styles to classes. Don't use inline CSS.
flex CSS property is shorthand for setting flex: [flex-grow] [flex-shrink] [flex-basis].
You can set fixed percentage to your flex-basis values and zeros to flex-grow and flex-shrink to avoid flex items growing and shrinking.
Also you show move scroll CSS to your right nav block.
*,
*:before,
*:after {
box-sizing: border-box;
}
.main-container {
display: flex;
}
.left-nav {
flex: 0 0 calc(100% / 3); /* One third width */
}
.right-nav {
flex: 0 0 calc(200% / 3); /* Two third width */
overflow-x: scroll;
}
.right-nav-container {
display: flex;
}
.right-nav-item {
min-width: 400px;
height: 500px
}
.right-nav-item:nth-child(1) {
background-color: blue;
}
.right-nav-item:nth-child(2) {
background-color: red;
}
.right-nav-item:nth-child(3) {
background-color: green;
}
<div>
Top Header (should stay in view)
</div>
<div class="main-container">
<div class="left-nav">
LeftNav
</div>
<div class="right-nav">
<div class="right-nav-container">
<div class="right-nav-item">
</div>
<div class="right-nav-item">
</div>
<div class="right-nav-item">
</div>
</div>
</div>
</div>

Control width of flex items arranged vertically in a flex container

I'm trying to achieve the effect where the boxes labeled "HALF", take up only 50% of the width (aka they share the first row evenly).
The base requirement is that they remain in a single container. Is this possible to achieve using flexbox?
I've tried playing around with flex-grow, flex-shrink, and flex-basis but I'm afraid I'm not understanding how to make it work, or if it's even possible, given the single container requirement.
Consider this fiddle: http://jsfiddle.net/GyXxT/270/
div {
border: 1px solid;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.child {
height: 200px;
}
.child.half {
flex: 1 1 10em;
color: green;
}
.child:not(.half) {
flex-shrink: 2;
flex-basis: 50%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
Instead of flex-direction: column, you can try a wrapping flexbox using flex-wrap: wrap; and you can set:
flex-basis: 50% for the half width divs
flex-basis: 100% for the full width divs
See that I have thrown in box-sizing: border-box to adjust for the widths when using flex-basis.
See demo below:
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.child {
height: 200px;
}
.child.half {
flex-basis: 50%;
color: green;
}
.child:not(.half) {
flex-basis: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
The flex sizing properties -- flex-grow, flex-shrink, flex-basis and flex -- work only along the main axis of the flex container.
Since your container is flex-direction: column, the main axis is vertical, and these properties are controlling height, not width.
For sizing flex items horizontally in a column-direction container you'll need the width property.
(Here's a more detailed explanation: What are the differences between flex-basis and width?)
To achieve your layout with a single container, see another answer to this question.
If you want to stay in column-direction, you'll need to wrap the .half elements in their own container.
.container {
display: flex;
flex-direction: column;
width: 400px;
}
.container > div:first-child {
display: flex;
}
.child.half {
flex: 1 1 10em;
color: green;
width: 50%;
}
.child {
height: 200px;
width: 100%;
border: 1px solid;
}
* {
box-sizing: border-box;
}
<div class="container">
<div><!-- nested flex container for half elements -->
<div class="child half">HALF</div>
<div class="child half">HALF</div>
</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
</div>
The base requirement is that they remain in a single container.
That can also be done without flexbox, by simply float the 2 half elements
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
}
.child {
height: 200px;
}
.child.half {
float: left;
width: 50%;
color: green;
}
.child:not(.half) {
width: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
If the purpose is to hardcode the size in CSS units, or in percentages (which was mentioned the question), #kukkuz's solution is good as it is.
If you want to size element widths according to their own individual contents, then align-tems: flex-start or similar could do the job. It's possible to deal with the dimension perpendicular to that of the flex layout itself. See a tester on the bottom of the doc page
(Old question, but previous answers were incomplete, some are misleading)