Flex container with two columns; second column has four rows - html

I am having difficulty displaying the following layout in flex. I have 5 boxes and I want to divide my container in two, displaying one box vertically and the other 4 vertically.
Here's my CSS:
.trades, .trade-panel {
flex: 1;
}
.layout-4-5 {
flex-direction: column;
}
.layout-4-5 > div {
width: 50%;
}
Then I set the basis of the fourth or last child to 100%.
.layout-4-5 > div:nth-child(1) {
flex-basis: 100%;
}
And here's my HTML
<div class="trades layout-4-5">
<!--trade-panel are my individual boxes --->
<div class="trade-panel">
</div>
</div>
Above print my layout horizontally. Considering My flex-direction is column and my first child or box has a 100% basis, shouldn't that print what I want? Please any help would be appreciated.
Note: Since the boxes are of equal size, the column containing the four other boxes should be longer, provided they are in the arrangement above, its ok. tq

I'm not entirely clear on your question or code. But here's a general solution:
flex-container-1 {
display: flex; /* establish flex container */
flex-direction: row; /* flex items will align horizontally */
justify-content: center; /* center flex items horizontally */
align-items: center; /* center flex items vertically */
/* for demo purposes only */
height: 250px;
width: 400px;
border: 1px solid #777;
background-color: lightgreen;
}
flex-container-1 > flex-item {
height: 90%;
flex: 0 0 45%; /* <flex-grow> <flex-shrink> <flex-basis> */
margin-right: 8px; /* a bit of space between the centered items */
border: 1px dashed #333;
background-color: yellow;
}
flex-container-2 {
height: 90%;
flex: 0 0 45%;
display: flex; /* flex item is now also flex container */
flex-direction: column; /* items will stack vertically */
justify-content: space-between; /* align items vertically */
}
flex-container-2 > flex-item {
flex: 0 0 22%;
border: 1px dashed #333;
background-color: yellow;
}
<flex-container-1><!-- main container -->
<flex-item></flex-item><!-- flex item #1 (first column) -->
<flex-container-2><!-- flex item #2 / nested flex container (second column) -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container-2><!-- close nested container -->
</flex-container-1><!-- close main container -->
jsFiddle

I struggled and struggled on this one and then serendipitously discovered a new solution to this problem right as I had decided to give up and use floats. I was finally able to get this to work without using separate DIVs for columns.
UPDATE: I have simplified my previous version of this by having the height specified on .items.
Provide non-percentage width and height to .items.
Use flex-direction: column on .items.
CSS:
.items {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 40em;
height: 20em;
}
.item:first-child {
width: 20em;
height: 20em;
background-color: black;
}
.item:nth-child(2) {
width: 20em;
height: 5em;
background-color: pink;
}
.item:nth-child(3) {
width: 20em;
height: 5em;
background-color: blue;
}
.item:nth-child(4) {
width: 20em;
height: 5em;
background-color: yellow;
}
.item:last-child {
width: 20em;
height: 5em;
background-color: red;
}
HTML:
<div class="items">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div><!-- .items -->
Codepen:
https://codepen.io/anon/pen/ZXoqJJ

I have give margin and background color property so you can better understand.
<div id="wrapper">
<div id="left">
<div class="flex-harshad">
<div class = "flex-harshad2">
Harshad
</div></div>
</div>
<div id="right">
<div class="flex-harshad">
<div class="flex-item">world</div>
<div class="flex-item">by</div>
<div class="flex-item">Alan</div>
<div class="flex-item">Dong</div>
</div>
</div>
</div>
Here is css.
body,
div {
margin: 0;
border: 0 none;
padding: 0;
}
html,
body,
#wrapper,
#left,
#right {
height: 100%;
min-height: 100%;
}
#wrapper {
margin: 0 auto;
overflow: hidden;
}
#left {
float: left;
}
div.flex-harshad2{
margin : 5px;
margin-top : 25px;
min-height: 91%;
background : white ;
width : 90px;
}
div.flex-harshad{
background: red;
height : 100%;
width : 100px;
text-align: center;
display : inline-block;
background :orange ;
margin :10px;
}
div.flex-item {
background: white;
margin: 5px;
margin-top : 25%;
min-height : 20%;;
/* remove text-lign will not center text itself */
text-align: center;
}
Here is output :

flex-container-1 {
display: flex; /* establish flex container */
flex-direction: row; /* flex items will align horizontally */
justify-content: center; /* center flex items horizontally */
align-items: center; /* center flex items vertically */
/* for demo purposes only */
height: 250px;
width: 400px;
border: 1px solid #777;
background-color: lightgreen;
}
flex-container-1 > flex-item {
height: 90%;
flex: 0 0 45%; /* <flex-grow> <flex-shrink> <flex-basis> */
margin-right: 8px; /* a bit of space between the centered items */
border: 1px dashed #333;
background-color: yellow;
}
flex-container-2 {
height: 90%;
flex: 0 0 45%;
display: flex; /* flex item is now also flex container */
flex-direction: column; /* items will stack vertically */
justify-content: space-between; /* align items vertically */
}
flex-container-2 > flex-item {
flex: 0 0 22%;
border: 1px dashed #333;
background-color: yellow;
}
<flex-container-1><!-- main container -->
<flex-item></flex-item><!-- flex item #1 (first column) -->
<flex-container-2><!-- flex item #2 / nested flex container (second column) -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container-2><!-- close nested container -->
</flex-container-1><!-- close main container -->

Related

In container with flex-grow: 1 the content is overflowing when it should be scrollable

I have a container that is flex-grow sized to fill up the remaining space within a fixed size container.
Within the flex-grow container, I have another div that is a lot bigger than the flex sized container. How do I make it so that the content-wrapper element is scrollable instead of the child element overflowing.
Thank you!
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
Generally speaking, for the overflow property to work, the container needs to be overflowed. That requires a fixed length on the container. Without a fixed length (height or width), there's nothing to trigger an overflow. The flex-grow property doesn't establish a fixed length, so it doesn't work.
Of course, setting a fixed height on your container is not an option if you want a dynamic layout.
So, to solve both problems, set the container to height: 1px.
this establishes the fixed length;
it doesn't interfere with the dynamic lengths; and,
the flex-grow property expands the container to full height
But there's one more problem. The nested flex container in column direction seems to be ignoring the overflow property. This is possibly because of the nesting in a flex formatting context. Hence, if possible, switch that container back to a block formatting context.
Make these adjustments to your code:
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.main-content-container {
padding: 0 20px;
display: flex;
flex-flow: column nowrap;
grid-gap: 10px;
height: 550px;
background: green;
}
.sub-content-container {
width: 300px;
background: grey;
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
.content-wrapper {
height: 1px; /* new */
flex-grow: 1;
/* display: flex; */
flex-flow: column nowrap;
overflow: auto;
}
.content-container {
height: 10000px;
background: #555;
}
body {
background: black;
color: white;
padding-bottom: 30px;
}
<div class='main-content-container'>
<p>stuff</p>
<div class='sub-content-container'>
<p>header</p>
<div class='content-wrapper'>
<div class="content-container">I WANT THIS TO STAY WITHIN THE CONTENT-WRAPPER</div>
</div>
</div>
</div>
jsFiddle demo

How can I make a div grow to fit its content, up to the max size of the parent container?

I'm positioning a modal div in the middle of the page with a max-height defined as a % of its container, in this case it shouldn't exceed 70% of the page height.
The contents of the div are two elements:
A fixed height header div
And a variable height content div
I want the modal to grow with the content until the max-height, then the content div should start scrolling. However whatever I do, the content seems to spill out of the modal like so:
This is my markup and styling:
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
}
.container {
/* I cannot remove this container */
display: flex;
flex-direction: column;
width: 600px;
}
.header {
flex: none;
background: red;
height: 100px;
}
.content {
flex: 1;
background: yellow;
overflow: auto;
}
.big-stuff {
margin: 10px;
background: orange;
height: 600px;
}
<div class="modal">
<div class="container">
<div class="header">
Header
</div>
<div class="content">
Content. Should shrink or grow to fit content but only to a max of the container height
<div class="big-stuff">
Large content
</div>
</div>
</div>
</div>
Unfortunately I can't change the markup so I'm trying to get this working just by modifying CSS. If I remove the .container div, then everything seems to work but I was hoping there was another way.
Full example available here: https://codepen.io/dyancat/pen/QWaOGpB
You can add flex to the modal, so that the content will not expand out of its parent (modal in this example):
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
display: flex; /* Add this flex */
}
Just add display:flex in the css to the modal class.
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
display: flex;
}
.container {
/* I cannot remove this container */
display: flex;
flex-direction: column;
width: 600px;
}
.header {
flex: none;
background: red;
height: 100px;
}
.content {
flex: 1;
background: yellow;
overflow: auto;
}
.big-stuff {
margin: 10px;
background: orange;
height: 600px;
}
<div class="modal">
<div class="container">
<div class="header">
Header
</div>
<div class="content">
Content. Should shrink or grow to fit content but only to a max of the container height
<div class="big-stuff">
Large content
</div>
</div>
</div>
</div>

Absolute Position Vertical Nav with Flexbox

I want to make a vertical nav that say will be 50px and then I want to have a flex area that has my header, main content area and footer.
Right now when I use absolute the flexbox container gets covered over as absolute it doing it's own thing. I am wondering if I can tell my flex container to start 50px from the left so I don't have to worry about icons and such getting swallowed up by it.
Do I have to make the flex container absolute as well?
You don't need any positioning or margins, just make it natural with the additional flex wrapper:
body {margin: 0}
.outerFlex {
display: flex; /* displays flex-items (children) inline */
height: 100vh; /* 100% of the viewport height */
}
nav {
flex-basis: 50px; /* initial width */
background: lightblue;
}
.innerFlex {
flex: 1; /* takes the remaining width */
display: flex;
flex-direction: column; /* stacks flex-items vertically */
background: lightgreen;
}
main {
flex: 1; /* takes the remaining height */
}
<div class="outerFlex">
<nav>Nav</nav>
<div class="innerFlex">
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
</div>
</div>
You can use margin-left:50px on the flex area to make it start at 50px;
see code sample
body {
margin: 0;
height: 100vh;
}
.container {
height: 100%;
}
.nav {
position: absolute;
width: 50px;
background: green;
height: 100%;
}
.flex-container {
display: flex;
background: yellow;
height: 100%;
margin-left: 50px;
}
<div class="container">
<div class="nav"></div>
<div class="flex-container">text sample</div>
</div>
You just need to position your nav as absolute or fixed, then give padding/margin that equals the width of your nav to the main content.
Here's an example.
.container {
width: 100%;
}
.left-nav {
position: fixed;
width: 50px;
height: 100%;
background: black;
}
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 50px;
background: rgba(255,0,0,0.1);
}
.main-header {
background: red;
}
.main-body {
background: green;
}
.main-footer {
background: blue;
}
<div class="container">
<div class="left-nav">Nav</div>
<div class="main">
<div class="main-header">Header</div>
<div class="main-body">Body</div>
<div class="main-footer">Footer</div>
</div>
</div>

Flexible width divs next to a fixed width div

Today I'm facing a challenging situation (at least for me).
Actually I have to make some divs flexible inside a parent div and having another fixed div as a 'brother'. These flexible divs must be 100% according to the width of their parent.
Here you go a picture made to explain my situation:
I was thinking something like:
.parent {
width: 500px; /* this value can change any time */
padding: 10px;
border: 1px solid red;
float: left;
}
.parent div {
float: left;
border: 1px solid #ccc;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
.flexible {
width: calc(100% - 100px); /* IT IS NOT WORKING AS I WOULD LIKE */
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2</div>
</div>
Someone could help me?
Thanks
You can use flexbox for this. You should wrap your two flexible divs in a container so that they will stack. Then you can set the parent to display: flex; flex-direction: row;. Then set your flexible wrapper to display: flex; flex-direction: column; and set flex-grow: 1 on the flexible divs and the flexible wrapper so they expand to fill both the vertical and horizontal space.
.parent {
width: 500px;
padding: 10px;
border: 1px solid red;
display: flex;
flex-direction: row;
}
.parent div {
border: 1px solid #ccc;
}
.flexcontainer {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
.flexible {
flex-grow: 1;
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class="flexcontainer">
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2</div>
</div>
</div>
You can use flexbox to achieve this layout.
.parent {
display: inline-flex; /* 1 */
padding: 10px;
border: 1px solid red;
}
.sub-container { /* 2 */
display: flex;
flex-direction: column;
align-items: stretch; /* 3 */
}
.flexible {
flex: 1; /* 4 */
border: 1px solid black;
}
.sub-container > div + div {
margin-top: 5px;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class='sub-container'>
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2 *flexible 2 *flexible 2</div>
</div>
</div>
Notes:
Inline-level flex container. (It adjusts to the width of its content.)
Create a sub-container for the flexible divs. Also uses flex properties.
An initial setting of a flex container is align-items: stretch. This means that flex items will automatically expand to cover the full length of the cross axis. In this case, that's the width.
Distribute the vertical space in the container evenly among the two flex items.
Taking your code as a base, you can add left and margin-left to .flexible. Also change the width as you need to calculate the padding and the container as well.
.flexible {
left: 0;
margin-left: 10px;
width: calc(100% - 120px); /* IT IS NOT WORKING AS I WOULD LIKE */
}

flexbox: stretching the height of elements with flex-direction: row

I want to stretch two div elements (.sideline and .main-contents) to reach the bottom of the page and stay at a certain height from the footer.
The two divs are nested inside a div (.row-elements) with the flex-direction: row since I wanted them to be on the same row.
/* body {
display:flex;
flex-direction:column;
} */
.one-above-all {
display: flex;
flex-direction: column;
/* flex: 1 0 auto; */
/* min-height: 1100px; */
border: solid black 1px;
}
.top-block {
margin: 0 auto;
border: solid black 1px;
width: 300px;
height: 30px;
margin-top: -15px;
}
.headline {
border: solid black 1px;
width: 90%;
align-self: flex-end;
margin-top: 40px;
margin-right: 10px;
height: 160px;
display: flex;
box-sizing: border-box;
}
.row-elements {
display: flex;
flex-direction: row;
margin-top: 40px;
align-items: stretch;
/* min-height: 900px;
flex: 1 0 auto;
*/
}
.sideline {
width: 160px;
border: solid 1px;
margin-left: calc(10% - 10px);
box-sizing: border-box;
flex-shrink: 1
}
.main-contents {
border: solid 1px;
margin-left: 40px;
/* align-self: stretch; */
flex: 1 1 auto;
margin-right: 10px;
box-sizing: border-box;
}
.bottom-block {
align-self: flex-end;
margin-top: auto;
border: black solid 1px;
margin: auto;
width: 300px;
height: 30px;
margin-bottom: -10px;
/* margin-top: 880px; */
}
/* .stretch-test {
border:solid, 1px;
display: flex;
flex-direction: column;
flex: 1 0 auto;
} */
<div class="one-above-all">
<div class="top-block"></div>
<div class="headline"></div>
<!-- <div class="stretch-test"> -->
<div class="row-elements">
<div class="sideline"></div>
<div class="main-contents">jhjkdhfjksdhafjksdahfl</div>
<!--</div> -->
</div>
</div>
<div class="bottom-block">footer</div>
Codepen
The commented out code in the css is the things I have tried.
I tried to set the body as flex and give the row-elements class flex property of 1 0 auto which didn't work.
I tried nesting the row-elements class (which has the flex-direction of row) in another div with a flex-direction of column and setting .row-elements to flex:1 0 auto which also didn't work.
I tried totally removing the the row-elements class but the two divs won't come on the same row.
Any solution will be appreciated.
To stick the footer to the bottom, here are two methods:
Method #1: justify-content: space-between
Align the container vertically with flex-direction: column. Then pin the last element to the bottom with justify-content: space-between.
revised codepen
Method #2: auto margins
Also with the container in column-direction, apply margin-top: auto to the footer, which spaces it away from the other flex items. (Seems you're already familiar with this method.)
Here's a detailed explanation for both: Methods for Aligning Flex Items
Make sure to define a height for your container, unless you simply want content height. In my example I've used height: 100vh on body.