Layout with 2 columns and 2 rows - html

I have a .container
with 2 columns and in the second column .right I want to have 2 rows
but the first row .content should use the remaining space
this is the HTML markup
<div class="container">
<div class="left">left</div>
<div class="right">
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</div>
this is the CSS
.container {
display: flex;
flex-direction: row;
height: 400px; /* the remaining space in the screen will be nice */
}
.left {
width: 300px;
}
.right {
flex-grow: 1;
}
.content {
align-self: stretch; /* this is not doing anything*/
}
.footer {
}
and this is how it should look
+--------+----------------------+
| | |
| | |
| | content |
| left | |
| | |
| +----------------------+
| | footer |
+--------+----------------------+

You can use a full height flexbox container:
nest a column flexbox inside for the right element,
use flex-grow: 1 on content to occupy remaining space.
See demo below:
body {
margin: 0;
}
.container {
display: flex;
/* flex-direction: row; <-- omit this, its default */
height: 100vh; /* full height */
}
.left {
width: 300px;
border: 1px solid;
}
.right {
flex-grow: 1; /* occupy remaining space */
display: flex;
flex-direction: column; /* column flexbox */
border: 1px solid;
}
.content {
flex-grow: 1; /* occupy remaining space */
border-bottom: 1px solid;
}
<div class="container">
<div class="left">left</div>
<div class="right">
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</div>

Flexbox works just fine here but I wanted to point out this is also a perfect situation for CSS Grid. With grid you can get rid of the extra container div.right.
<div class="container">
<div class="left">left</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>
.container {
display: grid;
grid-template-columns: 300px 1fr;
grid-template-rows: 1fr 100px; /* change the 100px to your desired height of the footer*/
grid-template-areas:
'left content'
'left footer';
height: 400px; /* height OP selected */
}
.left {
grid-area: left;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}
A CodePen just for fun.

Working example jsfiddle
.container {
display: flex;
flex-direction: row;
height: 100VH;
}
.left {
width: 200px;
border: 1px solid;
}
.right {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.content {
border: 1px solid #333;
border-bottom: 0;
flex-grow: 1;
}
.footer {
border: 2px solid;
height: 100px;
}

Related

Three divs in row, last one in another column horizontally centered - Flexbox or Grid

I have a grid container and I want to align three divs like this, also doing them responsive (all stacked). I don't have the heights of the divs.
It would be two columns, in one two rows (two divs one below another), in another column a div centered vertically having in mind the height of the two first divs.
I can use grid or flexbox.
Thanks
Using Flexbox:
.wrapper {
width: 400px;
border: 2px solid black;
height: 300px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
align-items: center;
}
.child {
height: 100px;
width: 150px;
border: 1px solid black;
margin-top: 20px;
margin-bottom: 20px;
}
<div class="wrapper">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
and also grid :
Example from2 columns and the third element spanning through 2 rows and margin itself in the middle.
section {
display: grid;
grid-template-columns: repeat(2, minmax(270px, 1fr));/* or any value you need */
grid-gap: 2em;/* or any value you need */
padding: 2em;/* or any value you need */
counter-reset: divs; /*demo*/
width:max-content;/* or any value you need */
margin:auto;/* or any value you need */
}
div {
border: solid red;
min-height: 30vh;/* or any value you need */
width: 270px;/* or any value you need */
display: flex; /* demo*/
}
div {
margin-left: auto;
}
div:nth-child(3) {
grid-column: 2;
grid-row: 1 / span 2;
margin: auto 0;
}
/*demo*/
div:before {
counter-increment: divs;
content: counter(divs);
margin: auto;
font-size: 3em;
}
<section>
<div></div>
<div></div>
<div></div>
</section>
To play with the grid system, you can use : https://css-tricks.com/snippets/css/complete-guide-grid/ / http://gridbyexample.com/ and https://codepen.io/pen/ for the playground.
Here's a jsfiddle: https://jsfiddle.net/5csL2dqy/
.container {
display: flex;
flex-direction: row;
width: 100%;
}
.right {
display: inherit;
align-items: center;
}
.a, .b, .c {
box-sizing: border-box;
width: 150px;
margin: 20px;
border: 1px solid black;
}
<div class="container">
<div class="left">
<div class="a">
<p>
First div
</p>
</div>
<div class="b">
<p>
second div
</p>
</div>
</div>
<div class="right">
<div class="c">
<p>
Third div
</p>
</div>
</div>
</div>
You use the following inline-flex styles
#media only screen and (min-width: 600px) {
.container {
display: inline-flex;
}
.container div {
border: 1px solid red;
padding: 1em;
margin: 1em;
}
.container>div+div {
margin: auto;
}
}
#media only screen and (max-width: 600px) {
.container div:not(first-child) {
border: 1px solid red;
}
}
<div class="container">
<div>
<div>
1
</div>
<div>
2
</div>
</div>
<div>
3
</div>
</div>
This is one of only two answers with equal width/height gaps. G-Cyr's is the other:
.grid{
display: grid;
grid-template-columns: repeat(9,1fr);
grid-template-rows: repeat(7, 1fr);
height: 90vh;
width: 120vh;
}
.grid > div{
border: solid 3px orangered;
font: 26px sans-serif;
display: flex;
align-items:center;
justify-content:center;
}
.grid > div:nth-child(1){
grid-row: 1/span 3;
grid-column: 1/span 4;
}
.grid > div:nth-child(2){
grid-row: 3/span 3;
grid-column: 6/span 4;
}
.grid > div:nth-child(3){
grid-row: 5/span 3;
grid-column: 1/span 4;
}
<div class="grid">
<div>1</div>
<div>2</div>
<div>3</div>
</div>

How to stretch div to full height with flex

How do I stretch the divs with a yellow background to full height? It should cover up the green but it is not working. I tried adding height: 100% on it but then it adds up the height from the search bar?
https://jsfiddle.net/nuy20j1h/
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
First you should add a style reset, I'm using this now * {} as you can se below. The trick here is to run flex-direction: column; on .home and you can tell .content-wrap to take up the rest of that space after the search with flex-grow: 1;
box-sizing: border-box; is, if you add let's say width: 200px; to a element, and add padding: 20px;, the element will stay 200px with the padding included. If you don't have that, it will take up 200px + 40px.
if you want the fiddle, here it is
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-grow: 1;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
As mentioned in other answers, there is one main issue here:
flex-direction: column;, which I added to home, to enable the usage of flex properties instead of height, to make the .content-wrap fill the available space left in home
That will make the .search-bar and .content-wrap stack vertical, and enable the use of flex: 1 on .content-wrap, which will make it fill the remaining space/height.
So even if you got answers already, and since there are some properties with wrong value, or not needed, I decided to post an answer to clarify the changes made.
See my notes made in the CSS for further clarifications and what I changed.
Stack snippet
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column; /* added */
/*flex-wrap: wrap; removed, not needed */
/*align-items: flex-start; removed, items should fill parent's,
in this changed case, width */
width: 75%;
background: green;
}
.search-bar {
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
padding: 25px;
background: blue;
}
.content-wrap {
flex: 1; /* added, take the remaining space left
left of its parent (height in this case) */
display: flex;
flex-wrap: wrap;
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
/*align-items: flex-stretch; wrong value, should be "stretch",
though since that is the default,
it is not needed */
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
flex-direction: column; is your friend. Here is a reworked fiddle of your code: https://jsfiddle.net/vsjktmms/1/
Using the same HTML structure you provided:
.block {
display: flex;
width: 80%;
margin: 0 auto;
background-color: gray;
align-items: stretch;
}
.sidebar {
width: 25%;
height: 600px;
background-color: red;
}
.home {
display: flex;
flex-direction: column;
align-items: stretch;
width: 75%;
background-color: green;
}
.search-bar {
padding: 25px;
background-color: blue;
}
.content-wrap {
flex: 1 1 auto;
display: flex;
flex-wrap: wrap;
width: 100%;
background-color: pink;
}
.content,
.single {
width: 50%;
background: yellow;
}

Flexbox inside another flexbox?

I'm trying to get a flexbox working inside a flexbox. While the first (wrapping) flexbox works, the one inside does nothing. Is there anyway to get this to work?
What I'm looking to do is effectively have two sticky footers and have the height of both reach the the footers.
html, body {
height: 100%;
margin: 0; padding: 0; /* to avoid scrollbars */
}
#wrapper {
display: flex; /* use the flex model */
min-height: 100%;
flex-direction: column; /* learn more: http://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ */
}
#header {
background: yellow;
height: 100px; /* can be variable as well */
}
#body {
flex: 1;
border: 1px solid orange;
height: 100%:
}
#wrapper2 {
display: flex; /* use the flex model */
min-height: 100%;
flex-direction: column;
}
#body2 {
border: 1px solid purple;
flex: 1;
}
#footer2 {
background: red;
flex: 0;
}
#footer{
background: lime;
}
<div id="wrapper">
<div id="body">Bodyof<br/>
variable<br/>
height<br/>
<div id="wrapper2">
<div id="body2">
blah
</div>
<div id="footer2">
blah<br />
blah
</div>
</div>
</div>
<div id="footer">
Footer<br/>
of<br/>
variable<br/>
height<br/>
</div>
</div>
JS Fiddle
You were almost there. Just two steps away:
Make #body a flex container.
Give .wrapper2 full height with flex: 1.
(I also got rid of percentage heights. You don't need them.)
body {
margin: 0;
}
#wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#header {
background: yellow;
height: 100px;
}
#body {
flex: 1;
border: 1px solid orange;
display: flex; /* new */
flex-direction: column; /* new */
}
#wrapper2 {
display: flex;
flex-direction: column;
flex: 1; /* new */
}
#body2 {
border: 1px solid purple;
flex: 1;
}
#footer2 {
background: red;
}
#footer {
background: lime;
}
<div id="wrapper">
<div id="body">
Bodyof
<br>variable
<br>height
<br>
<div id="wrapper2">
<div id="body2">blah</div>
<div id="footer2">
blah
<br>blah
</div>
</div>
</div>
<div id="footer">
Footer
<br>of
<br>variable
<br>height
<br>
</div>
</div>
jsFiddle
Once the adjustments above are made, you can pin the inner (red) footer to the bottom with:
flex: 1 on #body2, which is what you have, or
margin-bottom: auto on #body2, or
margin-top: auto on #footer2, or
justify-content: space-between on the container (#wrapper2)

A responsive two-column layout using flexbox

I have a small layout of sections
.collection {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.collection section {
width: 50%;
}
<div class="collection">
<section>
<h2>bar</h2>
</section>
<section>
<h3>baz</h3>
</section>
<section>
<h1>FOO</h1>
</section>
</div>
Then everything is positioned in one column. I'd expect such a layout
___________
| h2 | |
|____| h1 |
|_h3_|____|
I know that the layout would wrap if I set max-width. But I don't know the div size in advance. My intent is to wrap in such a way that both columns have equal height.
How can I achieve it?
By giving the h1 section a 100% height, it will be forced into a new column.
* {
margin: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
}
.collection {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
}
.collection section {
width: 50%;
flex: 1;
border: 1px dashed black;
}
.collection section:last-child {
flex-basis: 100%;
}
#media ( max-width: 700px ) {
.collection section { width: 100%; }
.collection section:last-child { flex-basis: auto; }
}
<div class="collection">
<section><h2>bar</h2></section>
<section><h3>baz</h3></section>
<section><h1>FOO</h1></section>
</div>
jsFiddle

Right-align items in a flex container

I have a div container (black outline) which contains 4 divs of equal length and height.
I want the 4 colored divs to be aligned right with equal spaces between them (assuming that each colored div is about 49.5% the height of container and width of each div is about 25% of container).
I tried to do this with flex but I'm not getting what I want.
Can someone please help me? Thank you so much in advance.
<div class="container">
<div class="blue"></div>
<div class="red"></div>
<div class="purple"></div>
<div class="green"></div>
</div>
.container { }
.blue { }
.red { }
.purple { }
.green { }
Because it seems that you have two columns inside a row, I suggest you use three flexboxes for this occasion.
Here is how this works:
.container (outer flexbox, flex-direction: row)
-------------------------------------------------------------------
| .innerContainer | .innerContainer | .innerContainer |
-------------------------------------------------------------------
.innerContainer (inner flexbox, flex-direction: column)
--------------- --------------- --------------
| (empty) | | .blue | | .red |
--------------- | .purple | | .green |
--------------- --------------
Also, all flex-box children were set to flex-grow: 1 so that they are all equal dimensions and they fill up the entire space.
.container {
display: flex;
flex-direction: row;
background-color: #e9e9e9;
height: 100px;
}
.innerContainer {
display: flex;
flex-direction: column;
}
.blue, .red, .purple, .green, .innerContainer {
flex-grow: 1;
margin: 2px 1px;
}
.blue {
background-color: blue;
}
.red {
background-color: red;
}
.purple {
background-color: purple;
}
.green {
background-color: green;
}
<div class="container">
<div class="innerContainer"></div>
<div class="innerContainer">
<div class="blue"></div>
<div class="purple"></div>
</div>
<div class="innerContainer">
<div class="red"></div>
<div class="green"></div>
</div>
</div>
* { box-sizing: border-box; }
.container {
display: flex; /* create flex container */
flex-direction: column; /* align children vertically */
flex-wrap: wrap; /* allow multiple columns */
align-content: flex-end; /* shift columns to container end */
height: 100px;
width: 400px;
border: 2px solid black;
}
.container > div {
margin: 5px; /* equal spacing between divs */
width: calc(25% - 10px); /* width less margin */
height: calc(50% - 10px); /* height less margin */
}
.blue { background-color: blue; }
.purple { background-color: purple; }
.red { background-color: red; }
.green { background-color: green; }
<div class="container">
<div class="blue"></div>
<div class="purple"></div>
<div class="red"></div>
<div class="green"></div>
</div>
jsFiddle