How to use flexbox to fill remaining height? - html

html,
body {
height: 100%;
}
.site-main {
height: calc(100% - 72px);
display: flex;
}
.site-main > div {
min-width: 85%;
height: 100%;
}
.site-main > aside {
min-width: 15%;
height: 100%;
background-color: $darkest-blue-grey;
}
<header>
<h1>Title</h1>
</header>
<div class="site-main">
<div></div>
<aside></aside>
</div>
I have the header at a fixed height of 72px.
I have given .site-main div a width of 85%.
I have given .site-main aside a width of 15%.
What I want is for .site-main div and .site-main aside to be side by side, and have .site-main fill the remaining white space after the header.
And have .site-main div and .site-main aside fill .site-main's height.
Any help would be greatly appreciated!

You can use flex-direction: column on body and flex: 1 on site-main.
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
padding: 0;
}
header {
height: 75px;
}
.site-main {
display: flex;
flex: 1;
}
.site-main div {
flex: 0 0 85%;
background: lightblue;
}
aside {
flex: 0 0 15%;
background: lightgreen;
}
<header>
<h1>Title</h1>
</header>
<div class="site-main">
<div></div>
<aside></aside>
</div>

For you who need to support IE11 (and 10), this one solves the IE min-height bug
Note, for this to work on IE10, prefixed flexbox properties needs to be added
html, body {
margin: 0;
}
body {
display: -ms-flexbox; /* IE 10 */
display: flex; /* IE11/10 bug fix */
}
.wrapper {
-ms-flex: 1; /* IE 10 */
flex: 1; /* fill 100% width */
display: -ms-flexbox; /* IE 10 */
display: flex;
-ms-flex-direction: column; /* IE 10 */
flex-direction: column;
min-height: 100vh;
}
header {
height: 72px;
}
.site-main {
-ms-flex: 1; /* IE 10 */
flex: 1; /* fill 100% height */
display: -ms-flexbox; /* IE 10 */
display: flex;
}
.site-main > div {
width: 85%;
background-color: lightgreen;
}
.site-main > aside {
width: 15%;
background-color: lightblue;
}
<div class="wrapper">
<header>
<h1>Title</h1>
</header>
<div class="site-main">
<div></div>
<aside></aside>
</div>
</div>

Related

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>

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;
}

How to do a sticky footer and still be able to do scrollable flexbox content?

I'm trying to achieve the sticky footer (flexbox version). However, I'm unable to find a working solution if I also want the ability to have scrollable content inside a flex: 1 div (which requires parents to have height: 100%).
Here's a fiddle to demonstrate the problem:
https://jsfiddle.net/gfaqLh42/6/
As you can see, the red area is scrollable (with a min-height: 300px). Notice the footer is offscreen even though the viewport is not less than the red area's min-height + blue area.
Is there a way to do a sticky footer and still use flexbox flex: 1 with scrollable content?
Update
Here's another picture to represent the other big problem I face in trying to make this work:
Is there a way to do a sticky footer and still use flexbox flex: 1
with scrollable content?
Yes, and what you need is to use Flexbox all the way.
So instead of using min-height/height on article-1/card, change their CSS to this:
.article-1 {
flex: 1;
display: flex;
min-height: 0; /* added, i.a Firefox need this */
}
.card {
overflow: auto;
}
Note, I also remove some properties not needed, mainly as they were set to their defaults, and added some. And why the need of min-width, is well explained here:
Why don't flex items shrink past content size?
Updated fiddle
Stack snippet
html, body{
height: 100%;
margin: 0;
font-weight: bold;
}
.header {
position: absolute;
height: 40px;
background-color: grey;
z-index: 1;
width: 100%;
}
.content {
display: flex;
flex-direction: column;
height: 100%;
padding-top: 40px;
box-sizing: border-box; /* added */
}
.wrap {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0; /* added, i.a Firefox need this */
}
.container {
flex: 1;
padding: 10px;
box-sizing: border-box; /* added */
display: flex;
flex-direction: column;
min-height: 0; /* added, i.a Firefox need this */
}
.article-1 {
flex: 1;
display: flex;
min-height: 0; /* added, i.a Firefox need this */
}
.card {
overflow: auto;
}
.card-text {
height: 2000px;
width: 2000px;
background-color: red;
}
.article-2 {
flex: none;
height: 40px;
background-color: blue;
}
.footer {
position: relative;
height: 40px;
background-color: grey;
}
<div class="header">Header</div>
<div class="content">
<div class="wrap">
<div class="container">
<div class="article-1">
<div class="card">
<div class="card-text">
scrollable flex: 1 div<br>
1. scrollable<br>
2. scrollable<br>
3. scrollable<br>
4. etc...
</div>
</div>
</div>
<div class="article-2">
flex: none div
</div>
</div>
</div>
<div class="footer">Footer</div>
</div>
Updated based on a comment
If there is a need for the article-1 to have a minimum height, and to avoid absolute positioning on it, a minimum height could be set on content as well, to push the footer further down on smaller screens.
Updated fiddle 2
Stack snippet
html, body{
height: 100%;
margin: 0;
font-weight: bold;
}
.header {
position: absolute;
height: 40px;
background-color: grey;
z-index: 1;
width: 100%;
}
.content {
display: flex;
flex-direction: column;
height: 100%;
min-height: 450px; /* added */
padding-top: 40px;
box-sizing: border-box; /* added */
}
.wrap {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0; /* i.a Firefox need this */
}
.container {
flex: 1;
padding: 10px;
box-sizing: border-box; /* added */
display: flex;
flex-direction: column;
min-height: 0; /* i.a Firefox need this */
}
.article-1 {
flex: 1;
display: flex;
min-height: 300px; /* changed */
}
.card {
overflow: auto;
}
.card-text {
height: 2000px;
width: 2000px;
background-color: red;
}
.article-2 {
flex: none;
height: 40px;
background-color: blue;
}
.footer {
position: relative;
height: 40px;
background-color: grey;
}
<div class="header">Header</div>
<div class="content">
<div class="wrap">
<div class="container">
<div class="article-1">
<div class="card">
<div class="card-text">
scrollable flex: 1 div<br>
1. scrollable<br>
2. scrollable<br>
3. scrollable<br>
4. etc...
</div>
</div>
</div>
<div class="article-2">
flex: none div
</div>
</div>
</div>
<div class="footer">Footer</div>
</div>

HTML/CSS div alignment

When resized, I need the div order changed to move two logos next to each other at 50% width each and the third div (title) 100% width below. Can anyone please direct me with where I am going wrong.
.logo1 {
width: 50%;
float: left;
top: 0px;
}
.logo2 {
width: 50%;
float: right;
top: 0px;
}
.title {
width: 100%;
clear: both;
}
<header>
<div class="logo1">
<img src="Pictures/logo.png" width="189" height="61" border="0">
</div>
<div class="title">
<h1 class="map_title">Infrastructure Web Map</h1>
</div>
<div class="logo2">
<img src="Pictures/Picture1.png" width="310" height="70" border="0">
</div>
</header>
You can do it with the Flexbox:
body {margin: 0}
h1 {
text-align: center;
}
header {
display: flex; /* displays flex-items (children) inline */
flex-wrap: wrap; /* enables their wrapping */
}
header > div {
flex: 1; /* each takes 33.33% of the parent's width */
display: flex; /* addition */
justify-content: center; /* addition */
}
img {
display: block; /* removes bottom margin/whitespace */
width: 100%; /* responsiveness */
}
#media (max-width: 568px) {
header > div {
flex: 0 1 50%; /* flex-grow = default, flex-shrink = default, flex-basis = 50% (initial width) */
}
.title {
flex: 1; /* stretches to fill the parent's width (100%) */
order: 1; /* changes the order, i.e. puts it below/after the #logo2 (by default its "order: 0") */
}
}
<header>
<div class="logo1">
<img src="http://placehold.it/300x200" alt="logo1">
</div>
<div class="title">
<h1 class="map_title">Infrastructure Web Map</h1>
</div>
<div class="logo2">
<img src="http://placehold.it/300x200" alt="logo2">
</div>
</header>
Thanks to all for the help, after some further research and a combination of all the suggestions, this is what I used to get it working:
header {
background-color: #cccccc;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
img {
margin: auto;
display: block;
}
.logo1, .logo2 {
width: 50%;
flex: 1 1 0;
}
.title {
color: #336699;
flex: 100%;
order: 3;
text-align: center;
}
}

How to stretch sidebar in flexbox while having footer and a main content that is not filled?

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; }