I´m building a sidebar using CSS flex and I need it to grow vertically to fill the whole screen vertical height. Here is a skeleton of what I´m doing.
JSFiddle here
.app {
display: flex;
flex-direction: row;
. align-items: flex-start;
height: 100%;
width: 100%;
}
.sidebar {
background-color: red;
height: 100%;
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
flex: 1;
background-color: grey;
}
.content-main {
flex: 1;
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
I think I got it pretty close by assigning the full viewport height to your container and then removing flex: 1 from .content children.
.app {
display: flex;
flex-direction: row;
. align-items: flex-start;
height: 100vh;
width: 100%;
}
.sidebar {
background-color: red;
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
background-color: grey;
}
.content-main {
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
body, html {
height: 100%;
}
And the fiddle
https://jsfiddle.net/gxkezny9/
One of the parent containers wasn't 100% height
The proper usage of Flexbox, is to make the app take full height by either use height: 100vh, or give html/body a height, html, body { height: 100% } so the app's height work as expected.
Second, as you use align-items: flex-start all items will initially align at the top, but by adding align-self: stretch to the sidebar, it will fill its parent's height.
Note, for flex row item you should not use height: 100%, you should use the align-* properties.
Note 2, the set flex: 1 on content-header and content-main doesn't have any affect, unless their parent content has a height higher than their summed height. i.e. if to change the app's align-items to stretch (and if, the align-self on sidebar can be removed)
Note 3, the flex: 1 won't work properly in IE, use flex-grow: 1 instead, or assign all values, where flex-basis should be auto, i.e. flex: 1 1 auto
Stack snippet
body {
margin: 0;
}
.app {
display: flex;
flex-direction: row;
align-items: flex-start;
height: 100vh; /* changed */
width: 100%;
}
.sidebar {
background-color: red;
align-self: stretch; /* added */
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
flex: 1; /* for IE, "flex-grow: 1" or "flex: 1 1 auto"
*/
background-color: grey;
}
.content-main {
flex: 1; /* for IE, "flex-grow: 1" or "flex: 1 1 auto"
*/
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
Related
This question already has answers here:
How can I make my flexbox layout take 100% vertical space?
(4 answers)
Closed 2 years ago.
I have a page that I want to style in such a way that I have a nav bar, a fixed height div underneath it and a flexible div underneath that, the flexible div contains two elements arranged horizontally and the flexible div should take up the remaining width of the page.
I followed this tutorial however I am not achieving the effect they describe: https://css-tricks.com/boxes-fill-height-dont-squish/
I'd like the area-2 div to take up the remaining height of the page.
How can I achieve this?
Stackblitz: https://stackblitz.com/edit/js-bnrfcu?file=style.css
<div class="nav">
<h1>Nav</h1>
</div>
<div class="area1">
<h4>Area1</h4>
</div>
<div class="fill-height">
<div class="area-2">
<div class="area-2-a">
<p>Area-2a</p>
</div>
<div class="area-2-b">
<p1>Area-2b</p1>
</div>
</div>
</div>
.nav {
height: 5rem;
background-color: aqua;
}
.nav-spacer {
margin-top: 5rem;
}
.area1 {
height: 10rem;
background-color: brown;
}
.fill-height {
display: flex;
flex-direction: column;
}
.fill-height > div {
flex: 1;
}
.area-2 {
display: flex;
flex-direction: row;
width: 100%;
}
.area-2-a {
width: 20%;
background-color: #4f90ff;
}
.area-2-b {
width: 80%;
background-color: #2b41ff;
}
Make the fill-height div use all the available space min-height: 100%;, but hey, there is no space to fill, well, height: 100vh; takes care of that.
body {
height: 100vh;
}
.fill-height {
display: flex;
flex-direction: column;
min-height: 100%;
}
You can set body as a flex column container too:
body {
margin:0;
min-height: 100vh;
display: flex;
flex-flow: column;
}
.nav {
height: 5rem;
background-color: aqua;
}
.nav-spacer {
margin-top: 5rem;
}
.area1 {
height: 10rem;
background-color: brown;
}
.fill-height {
display: flex;
flex-direction: column;
flex: 1
}
.fill-height>div {
flex: 1;
}
.area-2 {
display: flex;
flex-direction: row;
}
.area-2-a {
width: 20%;
background-color: #4f90ff;
}
.area-2-b {
width: 80%;
background-color: #2b41ff;
}
<div class="nav">
<h1>Nav</h1>
</div>
<div class="area1">
<h4>Area1</h4>
</div>
<div class="fill-height">
<div class="area-2">
<div class="area-2-a">
<p>Area-2a</p>
</div>
<div class="area-2-b">
<p1>Area-2b</p1>
</div>
</div>
</div>
see probably a duplicate of your question : Fill remaining vertical space with CSS using display:flex How can I make my flexbox layout take 100% vertical space?
For some reason, a div whose parent has a display: flex property is having a height of 228px even though there's no content inside of it.
Image example
.sights-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
flex: 1;
background-color: #ffffff;
}
.sights-list div {
flex-basis: 48%;
flex-shrink: 0;
display: flex;
padding: 10px;
}
<div class='sights-list'>
<div>
</div>
<div>
</div>
</div>
you can use
{
min-height: 100%;
}
First I create a layout using flexbox:
<html>
<body>
<div id="header"></div>
<div id="main"></div>
</body>
</html>
header div has a fixed height: 60px, and main div takes the remaining height of screen:
html, body{
100%;
}
body{
display: flex;
flex-direction: column;
}
#header{
height: 60px;
flex-grow: 0;
}
#main{
flex-grow: 1;
}
I got what I want:
Then I want to display three boxes inside #main div: box_1, box_2 and box_3.
box_1 and box_3 has the same height value, and box_2 expand itself to take the remaining height of #main:
I add the following codes:
<html>
<body>
<div id="header"></div>
<div id="main">
<div id="box_1"></div>
<div id="box_2"></div>
<div id="box_3"></div>
</div>
</body>
</html>
#main{
flex-grow: 1;
flex-direction: column;
}
#box_1, #box_3{
height: 60px;
flex-grow: 0;
background-color: red;
}
#box_2{
flex-grow: 1;
background-color: blue;
}
The #box_2 is invisible unless I set a height value to #main div. If height value is required, why should I still use flexbox...
The main problem in your code is that you didn't specify display: flex on the #main container.
Therefore, the element is not a flex container, flex-direction: column is ignored, and the children are not flex items.
Keep in mind that flex properties work only between parent and child elements. So your display: flex on the body element applies only to the children, but not other descendants.
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
}
header {
flex: 0 0 60px; /* flex-grow, flex-shrink, flex-basis */
background-color: lightgray;
}
main {
flex-grow: 1;
background-color: aqua;
display: flex; /* key addition */
flex-direction: column;
}
#box_1, #box_3 {
flex: 0 0 60px;
background-color: red;
}
#box_2 {
flex-grow: 1;
background-color: blue;
}
<header></header>
<main>
<div id="box_1"></div>
<div id="box_2"></div>
<div id="box_3"></div>
</main>
I want to create a simple layout for my SPA where I have a header component, which should be shown all the time. A footer component, which should be either at the bottom of the screen or if the main content component is bigger than the screen, it should be below the content component. And a main content component which should get the rest of the space if the screen is bigger than the content, so the footer component gets rendered at the bottom.
Currently I've reproduced my layout in this codepen. But if you shrink the result window of the codepen enough, you'll get to a point where I can't see the Test2 text because the footer component is on top of it. The behaviour I would expect is, that I can see the Test2 text and I'm able to scroll down to the footer component.
It works if the content component is not a flex box with flex-direction: row. Any ideas why this doesn't work?
In my SPA I'm using React, so I don't want to use any JavaScript for this.
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
overflow: scroll;
}
.main {
flex: 1;
background: red;
display: flex;
flex-direction: row;
min-height: 30px;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
<div class="footer">Footer</div>
</div>
</div>
Just add flex: 1 0 auto to .main class. Flex properties are flex-grow, flex-shrink, and the flex-basis. So with 0 it is told to not shrink.
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
overflow: scroll;
}
.main {
flex: 1 0 auto;
background: red;
display: flex;
flex-direction: row;
min-height: 30px;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
<div class="footer">Footer</div>
</div>
</div>
I got it working. I needed to add a div with display: block; around my content and I added justify-content: space-between; to my container component. Little hacky but it works...
That's my final code:
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
justify-content: space-between;
overflow: scroll;
}
.block {
display: block;
}
.main {
background: red;
display: flex;
flex-direction: row;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="block">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
</div>
<div class="footer">Footer</div>
</div>
</div>
Here is the screenshot: http://imgur.com/mNJNJ2t
I want the right sidebar to stretch the footer. Here is my markup:
<header>
Fixed position header
</header>
<main>
<article>
<form method="post" class="row">
<div class="col-l-2 padding-20">
Table here
</div>
<div class="col-l-2 sidebar">
Checkout stuff here
</div>
</form>
</article>
</main>
<footer>
Footer here
</footer>
And here is the CSS:
body {
display: flex;
flex-direction: column;
min-height: 100vh;
padding-top: 80px /* header height: 80px */
}
main {
flex: 1;
}
.row {
display: flex;
flex-direction: row;
}
.col-l-1 {
flex: 1;
}
.col-l-2 {
flex: 2;
}
.padding-20 {
padding: 20px;
}
.sidebar {
background: #f8f8f8;
}
div, article { display: block; }
I didn't add vendor prefixes here for readability. The min-height and flex model in the body is to make the footer to stick to the bottom. I don't mind if the table/cart area also stretches. All I need is to make the sidebar go min-height: 100% and to not to push the footer to the bottom but instead stretch till it touches the footer, which is at the bottom. I know it sounds crazy but using main { flex: 1} was able to put the footer at the bottom and all I need is to make the row class min-height 100% height of main.
EDIT: Pen/Fiddle
main should have display: flex too and div, article and form should have display: flex and flex: 1
body {
display: flex;
flex-direction: column;
min-height: 100vh;
padding-top: 80px /* header height: 80px */
}
main {
display: flex;
flex: 1;
}
.row {
display: flex;
flex-direction: row;
}
.col-l-1 {
flex: 1;
}
.col-l-2 {
flex: 2;
}
.padding-20 {
padding: 20px;
}
.sidebar {
background: #f8f8f8;
}
div, article, form { display: flex; flex:1 }
http://jsfiddle.net/1rLzf95d/
if you add a height to your .row class it will stretch its children to the same height. For example .row { display: flex; min-height: 100vh; flex-direction: row; }