Div with overflow scroll does not expand to height of children - html

I want a layout with a header, body, and footer. I do not want to use display: fixed, so I'm only scrolling the body. I use flex-grow: 1 to force the body section to fill the height.
The body has 4 columns. The columns are taller than the height of the body, so the body scrolls. However, the columns do not scroll, only their content.
In this codepen, scroll the middle section with the 4 columns. Note the gold background of the columns does not scroll. Instead, you see the orange background of the body.
How do I get the body content area to fill the screen if there's less content but also have the content background expand with the content when it scrolls? I've tried adding clearing div's and setting the column height to 100%.
Video illustration of the problem: http://recordit.co/eGpT87EmPp
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
height: 100vh;
}
.App {
background: red;
display: flex;
flex-direction: column;
height: 100vh;
}
.App .Header {
background: violet;
display: flex;
min-height: 2rem;
}
.App .Header .Player {
background: pink;
flex: 1 1;
text-align: center;
}
.App .Body {
background: orange;
display: flex;
flex-grow: 1;
overflow-y: scroll;
}
.App .Body .Column {
background: gold;
box-shadow: inset -1px 0 0 0 black;
display: flex;
flex-direction: column;
flex: 1 1;
padding-top: 1rem;
}
.App .Tile {
background: #111;
color: white;
margin: 0 auto 1rem;
padding: 5rem 0;
text-align: center;
width: 4rem;
}
.App .Footer {
background: deepskyblue;
min-height: 2rem;
}
<div class="App">
<div class="Header">
<div class="Player">Player</div>
<div class="Player">Player</div>
<div class="Player">Player</div>
<div class="Player">Player</div>
</div>
<div class="Body">
<div class="Column">
<div class="Tile">0</div>
<div class="Tile">1</div>
<div class="Tile">2</div>
<div class="Tile">3</div>
<div class="Tile">4</div>
<div class="Tile">5</div>
<div class="Tile">6</div>
<div class="Tile">7</div>
<div class="Tile">8</div>
<div class="Tile">9</div>
<div class="Tile">10</div>
<div class="Tile">11</div>
<div class="Tile">12</div>
<div class="Tile">13</div>
<div class="Tile">14</div>
<div class="Tile">15</div>
<div class="Tile">16</div>
<div class="Tile">17</div>
<div class="Tile">18</div>
<div class="Tile">19</div>
</div>
<div class="Column">
<div class="Tile">0</div>
<div class="Tile">1</div>
<div class="Tile">2</div>
<div class="Tile">3</div>
<div class="Tile">4</div>
<div class="Tile">5</div>
<div class="Tile">6</div>
<div class="Tile">7</div>
<div class="Tile">8</div>
<div class="Tile">9</div>
<div class="Tile">10</div>
<div class="Tile">11</div>
<div class="Tile">12</div>
<div class="Tile">13</div>
<div class="Tile">14</div>
<div class="Tile">15</div>
<div class="Tile">16</div>
<div class="Tile">17</div>
<div class="Tile">18</div>
<div class="Tile">19</div>
</div>
<div class="Column">
<div class="Tile">0</div>
<div class="Tile">1</div>
<div class="Tile">2</div>
<div class="Tile">3</div>
<div class="Tile">4</div>
<div class="Tile">5</div>
<div class="Tile">6</div>
<div class="Tile">7</div>
<div class="Tile">8</div>
<div class="Tile">9</div>
<div class="Tile">10</div>
<div class="Tile">11</div>
<div class="Tile">12</div>
<div class="Tile">13</div>
<div class="Tile">14</div>
<div class="Tile">15</div>
<div class="Tile">16</div>
<div class="Tile">17</div>
<div class="Tile">18</div>
<div class="Tile">19</div>
</div>
<div class="Column">
<div class="Tile">0</div>
<div class="Tile">1</div>
<div class="Tile">2</div>
<div class="Tile">3</div>
<div class="Tile">4</div>
<div class="Tile">5</div>
<div class="Tile">6</div>
<div class="Tile">7</div>
<div class="Tile">8</div>
<div class="Tile">9</div>
<div class="Tile">10</div>
<div class="Tile">11</div>
<div class="Tile">12</div>
<div class="Tile">13</div>
<div class="Tile">14</div>
<div class="Tile">15</div>
<div class="Tile">16</div>
<div class="Tile">17</div>
<div class="Tile">18</div>
<div class="Tile">19</div>
</div>
</div>
<div class="Footer">Footer</div>
</div>

So it doesn't look like you want the individual columns to scroll. If I've misinterpreted that requirement, then the solution is simple.
Make these adjustments to your code:
.Body {
background: orange;
display: flex;
flex-grow: 1;
/* overflow-y: scroll; */
min-height: 0; /* new */
}
.Column {
overflow: auto; /* new */
background: gold;
box-shadow: inset -1px 0 0 0 black;
display: flex;
flex-direction: column;
flex: 1 1;
padding-top: 1rem;
}
codepen
Here's an explanation for the modifications above: Why don't flex items shrink past content size?
If you just want the .Body element to scroll, add a wrapper:
<div class="Body">
<section><!---- NEW ----->
<div class="Column">
<div class="Tile">0</div>
<div class="Tile">1</div>
<div class="Tile">2</div>
<div class="Tile">3</div>
. . .
.Body {
background: orange;
flex-grow: 1;
overflow: auto;
}
section {
display: flex;
}
codepen
Here's an explanation for the modifications above: Make background color extend into overflow area

Related

Flex nowrap container not wrapping child. when the width of those are in mentioned in percentage

I have a flex container that wraps some cards. I have implemented a horizontal scroller with flex(using flex-nowrap). The flex wrapper container is subjected to have a 36px left spacing and a 0px right spacing initially. The catch here is after the last card is scrolled I need to have a 36px right spacing.
here is what I did so far
*{
box-sizing: border-box;
}
h2 {
margin: 0;
}
body {
background: cadetblue;
}
.container {
width: 500px;
margin: 0 auto;
background: #000;
padding: 20px 36px;
}
.scroll-wrapper {
overflow: hidden;
margin-right: -36px;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: 0px -16px;
}
.card {
height: 250px;
width: 75%;
flex: 1 0 75%;
padding: 0px 16px;
}
.inner-wrapper {
background: #fff;
height: 250px;
}
<div class="container">
<div class="scroll-wrapper">
<div class="scroll-inner">
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
</div>
</div>
</div>
I have given a negative right margin for the wrapper to make it look like it's flowing from the right.
Once the last element is scrolled/reached I want it to look something like this
enter image description here
One thing I noticed is my scroll-inner(flex-nowrap) is not wrapping up the entire children. I presumed if we have five children each having width 50px. The scroll-inner should show a scrollable width of 250px, Unfortunately, it's not how flex is behaving. Any help or suggestion is much appreciated.
Updating few images that show what I'm really looking for
During scrolling
After scrolling till the last card
Try
.scroll-wrapper {
overflow: hidden;
margin: auto;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: auto;
}
I have found a fix and hope this help someone.
*{
box-sizing: border-box;
}
h2 {
margin: 0;
}
body {
background: cadetblue;
}
.container {
width: 500px;
margin: 0 auto;
background: #000;
padding: 20px 36px;
}
.scroll-wrapper {
overflow: hidden;
margin-right: -36px;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: 0px;
}
.card {
height: 250px;
width: 75%;
flex: 1 0 75%;
padding-right: 40px;
margin-right: -8px;
}
.inner-wrapper {
background: #fff;
height: 250px;
}
<div class="container">
<div class="scroll-wrapper">
<div class="scroll-inner">
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
</div>
</div>
</div>
Please do answer if someone has a better solution!! Thanks

How to equally space empty divs with CSS only in flex?

So I have a structure pretty similar to the snippet below.
The issue I have is that I am trying to make it so that the divs such as child always take the same height relative to the container even if they are empty. So if there are two children they have to be 50% of the parent if there are three children 33.3% of the parent and ec.
Did a lot of digging, tried usingflex-grow and setting it on the children, adding an after content on the childContent class if it was empty but the empty children still collapse.
Is it even possible to achieve equal heights on the children without using js and fixed heights and if yes how?
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: auto;
}
.child {
height: 100%;
display: flex;
flex-direction: column;
}
.childHeader {
display: flex;
flex-direction: row;
}
.headerItem {
background-color: red;
}
.childContent {
background-color: white;
}
.childContent:empty:after {
content: '.';
visibility: hidden;
min-height: 300px;
}
.contentItem {
background-color: skyblue;
border: 3px solid black;
}
<div class="container">
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
<div class="contentItem">1</div>
<div class="contentItem">2</div>
<div class="contentItem">3</div>
<div class="contentItem">4</div>
<div class="contentItem">5</div>
<div class="contentItem">6</div>
<div class="contentItem">7</div>
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
</div>
Check this out, I'm not really sure if this is what you want to do.
I just added min-height: calc(100vh - 60px); in your .childContent
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: auto;
}
.child {
display: flex;
flex-direction: column;
}
.childHeader {
display: flex;
flex-direction: row;
}
.headerItem {
display:flex;
flex-basis:100%;
background-color: red;
}
.childContent {
background-color: grey;
position: relative;
display: block;
min-height: calc(80vh - 60px);
}
.childContent:empty::after {
content: '.';
visibility: hidden;
}
.contentItem {
background-color: skyblue;
border: 3px solid black;
}
<div class="container">
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
<div class="contentItem">1</div>
<div class="contentItem">2</div>
<div class="contentItem">3</div>
<div class="contentItem">4</div>
<div class="contentItem">5</div>
<div class="contentItem">6</div>
<div class="contentItem">7</div>
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
</div>
Check this one out https://developer.mozilla.org/en-US/docs/Web/CSS/calc

overflow-y either auto or scroll bar does not allow showing all overflow content

I have a dummy screen with background image. The background image correctly expands or contracts with the size of the viewport. I have dummy flexbox content that I intentionally make overflow the bottom of the page.
The scrollbar correctly appears, but it will not scroll far enough to show all the content that overflowed.
Apologies: the content is varied so I can tell what IS NOT showing.
Dummy header menu bar is fine.. it is supposed to scroll up - and it does.
CSS:
html {
box-sizing: border-box;
}
body {
box-sizing: border-box;
overflow-y: auto;
min-height: 100vh;
width: 100%;
margin: 0; padding: 0; border: 0; cursor: default
}
ul {
list-style: none;
li {
display: inline;
margin-left: 50px;
margin-top: 50px;
}
}
.blockStyleEven {
display: flex;
flex-direction: row;
color: white;
justify-content: space-evenly;
}
.blockSpaceAround {
display: flex;
flex-direction: row;
color: white;
justify-content: space-around;
}
.blockSpaceBetween {
display: flex;
flex-direction: row;
color: white;
justify-content: space-between;
}
.blockStart {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-start;
}
.blockEnd {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-end;
}
.blockCenter {
display: flex;
flex-direction: row;
color: white;
justify-content: center;
}
.maroon {
width: 100px;
height: 100px;
background-color: maroon;
}
.red {
width: 100px;
height: 100px;
background-color: red;
}
.green {
width: 100px;
height: 100px;
background-color: green;
}
.blue {
width: 100px;
height: 100px;
background-color: blue;
}
.workspace {
background: url("././Features.jpg") no-repeat center center fixed;
background-size: cover;
height: 100vh;
width: 100vw;
overflow: hidden;
h1 {
color: #E0B228;
}
h2 {
color: #2856E0;
}
}
HTML:
<div [ngStyle]="{'width': '100vw', 'height': '100vh'}">
<div [ngStyle]="{'display': 'flex', 'flex-direction': 'column'}">
<div [ngStyle]="{'background-color': 'beige'}">
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
</div>
<div class="workspace">
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
</div>
</div>
</div>
Thanks in advance.
Yogi
Finally figured it out. The problem was the scrollbar was "too short" to show all the content. This was because my workspace class was on a div below the dummy menu bar. When I put the workspace (containing Margin: auto) on the outer move div, it worked perfectly.
Thanks for all your help.
Apologies for the earlier poor formatting, which has now been cleaned up.
Yogi

Can't wrap columns in a flexbox flow except under Chrome

How can I fix the max-height of the "content" div. The code works only under Chrome :/
the "content" div should not expand outside the bottom of the window. the items should wrap to the right.
item1 item4 item7
item2 item5 ...
item3 item6
html
<div class="top">
<div class="title">Title</div>
</div>
<div class="wrapper">
<div class="left">
<div class="link">Link</div>
</div>
<div class="content">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
<div class="item">Item6</div>
<div class="item">Item7</div>
<div class="item">Item8</div>
<div class="item">Item9</div>
<div class="item">Item10</div>
<div class="item">Item11</div>
<div class="item">Item12</div>
<div class="item">Item13</div>
<div class="item">Item14</div>
<div class="item">Item15</div>
<div class="item">Item16</div>
<div class="item">Item17</div>
<div class="item">Item18</div>
<div class="item">Item19</div>
</div>
</div>
</div>
css
html, body { height: 100%; margin: 0px; padding: 0px }
.main {
height: 100%;
max-heigth: 100%; /* not required under chrome, do not works for others */
display: flex;
flex-direction: column;
background-color: red;
color: white;
}
.wrapper {
flex: 1 1 auto;
display: flex;
background-color: silver;
}
.left {
width: 50px;
background-color: lightblue;
}
.content {
flex:1;
display: flex;
flex-flow: column wrap; /* warp only under Chrome */
}
https://jsfiddle.net/L7zzucms/
Change your wrapper rule to this and it works everywhere (tested on Chrome,Firefox,Edge,IE11)
.wrapper {
height: 100%;
display: flex;
background-color: silver;
}
Updated fiddle
I suppose the flex: 1 in content need a height, other than flex: 1 1 auto, from its parent to be able to wrap properly

Flexbox items of same size

How can I force flexbox items to have same height.
In examples I found online, people are using align-items: stretch css property, but my example is more complex.
Here is a codepen example:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>
Height of items items below 'Heading' and height of items below 'Heading 2' should be equal.
Used this css and now the boxes have the same height:
.container > .boxes > .boxes {
flex: 1;
}
Take a look at the below snippet:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
.container > .boxes > .boxes {
flex: 1;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>