Flexbox body and main min-height - css

https://jsfiddle.net/vz7cLmxy/
I'm trying to have the body to expand but the min-height does not work. I've read other related topics but can't get my head around it.
CSS and html
body,
html {
padding: 0;
margin: 0;
min-height: 100%;
}
body {
display: flex;
background: #eee;
flex-direction: column;
}
.menu {
background: red;
color: #fff;
padding: 10px;
}
.wrap {
display: flex;
}
.sidebar {
background: #ddd;
width: 300px;
}
.main {
background: #ccc;
flex: 1;
}
.footer {
background: #000;
color: #fff;
padding: 10px;
}
<div class="menu">Menu</div>
<div class="wrap">
<div class="sidebar">Sidebar</div>
<div class="main">Main</div>
</div>
<div class="footer">Footer</div>
Expected result is that main is streched to fill the height if it's less than 100%.

Use flex: 1 on the centered element:
.Site {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.Site-content {
flex: 1;
background-color:#bbb;
}
<body class="Site">
<header>This is the header text ☺</header>
<main class="Site-content">…</main>
<footer>This is the footer text ☻</footer>
</body>

To get min-height with relative units working even in IE11 it needs just a tiny trick.
The nature of min-height is to overwrite the height when height is smaller then min-height. Very clear! But the pitfall is when min-height has a realitve unit (% or vh) and height is not set. Since it is relative it has no basis to relay on.
For all major browsers except Internet Explorer one possibility is to change the unit from % to vh:
body {
min-height: 100vh;
}
For Internet Explorer it needs a height (will be overwritten from min-height):
body {
height: 1px;
min-height: 100vh;
}
or to keep % the rules has to be applied to html too:
html, body {
height: 1px;
min-height: 100%;
}
A cross browser solution for the OP needs height: 1px on body and of course flex-grow: 1 for .wrap to let it grow faster then menu and footer:
body,
html {
padding: 0;
margin: 0;
height: 1px; /* added */
min-height: 100%;
}
body {
display: flex;
background: #eee;
flex-direction: column;
}
.menu {
background: red;
color: #fff;
padding: 10px;
}
.wrap {
display: flex;
flex-grow: 1; /* added */
}
.sidebar {
background: #ddd;
width: 300px;
}
.main {
background: #ccc;
flex: 1;
}
.footer {
background: #000;
color: #fff;
padding: 10px;
}
<div class="menu">Menu</div>
<div class="wrap">
<div class="sidebar">Sidebar</div>
<div class="main">Main</div>
</div>
<div class="footer">Footer</div>

Related

How to force a div to top/bottom of viewport while not taking it out of document flow?

I'm wondering how I can make the blue div 'stick' to the top and bottom of the page (so you can't scroll beyond it) without breaking the document flow (I don't want it to overlap the content div). A crude version is here in the code snippet. If I set 'absolute' on it, it breaks flow and the content goes under the menu. If I leave it relative, you can scroll beyond it (I want it to stay at top: 0, bottom: 0 for a full 100vh with its own scrolling).
Is there something that I'm missing?
* {
box-sizing: border-box;
}
.main {
display: flex;
flex-direction: row;
}
.sideNav {
width: 100px;
height: 100vh;
border: 5px solid red;
}
.sidePanel {
width: 50px;
height: 100vh;
border: 5px solid blue;
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 200vh;
margin: auto;
width: auto;
border: 5px solid green;
}
<div class="main">
<div class="sideNav">Side Nav</div>
<div class="content">This is the content area</div>
<div class="sidePanel">Side Panel</div>
</div>
You really can't do it without removing it from the document flow.
But if you know the width of the side panel, you can apply it as a right margin to the content div.
.main {
display: flex;
flex-direction: row;
}
.sideNav {
width: 100px;
height: 100vh;
border: 5px solid red;
}
.sidePanel {
width: 50px;
height: 100vh;
border: 5px solid blue;
position: fixed; /* new */
right: 0; /* new */
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 200vh;
margin: auto;
width: auto;
border: 5px solid green;
margin-right: 50px; /* new */
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
<div class="main">
<div class="sideNav">Side Nav</div>
<div class="content">This is the content area</div>
<div class="sidePanel">Side Panel</div>
</div>

Make child div fill parent div with scroll

I am having problems with flexbox layout parenting a child control.
html, body, .frame{
margin: 0;
height: 100%;
}
* {
box-sizing: border-box;
}
.frame{
display: flex;
flex-flow: column;
}
.header{
background-color: yellow;
height: 40px;
}
.body-outer{
background-color: green;
flex: 1;
display: flex;
flex-flow: column;
}
.body-inner{
border: 1px solid red;
flex: 1;
}
.big-text{
height: 2000px;
border: 1px solid lightblue;
overflow: auto;
margin: 5px;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner>">
<div class="big-text">big text</div>
</div>
</div>
</div>
The 'body-inner' div is meant to fill the remaining space with flex: 1 and the 'big-text' is supposed to fill the whole space of 'body-inner' without expanding it but showing scroll bars.
You have the overflow applied to the content. It should be applied to the container that will be overflowed.
Also, you need a fixed height, so that the overflow property has something to overflow.
Try this:
.frame {
display: flex;
flex-flow: column;
height: 100vh;
}
.header {
background-color: yellow;
height: 40px;
}
.body-outer {
height: calc(100vh - 40px); /* new */
background-color: green;
/* flex: 1; */
display: flex;
flex-flow: column;
}
.body-inner {
border: 1px solid red;
flex: 1;
overflow: auto; /* moved here */
}
.big-text {
height: 2000px;
border: 1px solid lightblue;
/* overflow: auto; */
margin: 5px;
}
body {
margin: 0;
}
* {
box-sizing: border-box;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner">
<div class="big-text">big text</div>
</div>
</div>
</div>

Flexbox container is not including margin-bottom

doI have just started learning flexbox layout and implemented one example of it but got stuck when I set margin 20px to my flexbox container. The top, left, and right margin is working as expected but I don't know the bottom margin is not set unexpectedly.
I have set the container's height to 100% which takes the height of the parent(body element) which is also 100%.
Though It works fine when I set padding to 20px to my body and removed the 20px margin from the container.
Just wanted to know about this behavior.
Why the margin doesn't work here instead of padding?
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
background: #011627;
height: 100%;
}
.container {
margin: 20px;
border: solid 2px #f9f871;
}
.container > div:nth-child(odd) {
padding: 10px;
background: #ff6a67;
}
.container > div:nth-child(even) {
padding: 10px;
background: #007277;
color: azure;
}
/* overwrite css */
.container {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="home">Home</div>
<div class="search">Search</div>
<div class="view">View</div>
<div class="logout">Logout</div>
</div>
The box-sizing property does not include the margin for calculation:
https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
The box-sizing CSS property sets how the total width and height of an element is calculated.
You may turn the margin into a padding of the parent
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
background: #011627;
height: 100%;
}
body {
padding: 20px;
}
.container {
/* margin: 20px; */
border: solid 2px #f9f871;
}
.container>div:nth-child(odd) {
padding: 10px;
background: #ff6a67;
}
.container>div:nth-child(even) {
padding: 10px;
background: #007277;
color: azure;
}
/* overwrite css */
.container {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="home">Home</div>
<div class="search">Search</div>
<div class="view">View</div>
<div class="logout">Logout</div>
</div>
or remove it from the height of the parent with calc()
https://developer.mozilla.org/en-US/docs/Web/CSS/calc()
The calc() CSS function lets you perform calculations when specifying CSS property values. It can be used anywhere a <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> is allowed.
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
background: #011627;
height: 100%;
}
body {
height:calc( 100% - 40px );
}
.container {
margin: 20px;
border: solid 2px #f9f871;
}
.container>div:nth-child(odd) {
padding: 10px;
background: #ff6a67;
}
.container>div:nth-child(even) {
padding: 10px;
background: #007277;
color: azure;
}
/* overwrite css */
.container {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="home">Home</div>
<div class="search">Search</div>
<div class="view">View</div>
<div class="logout">Logout</div>
</div>
Because of height:100% set on both body and html, you won't see that empty space below. You can give an height to body only to allow html to scroll.
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
background: #011627;
}
body {
height:100vh;
}
.container {
margin: 20px;
border: solid 2px #f9f871;
}
.container>div:nth-child(odd) {
padding: 10px;
background: #ff6a67;
}
.container>div:nth-child(even) {
padding: 10px;
background: #007277;
color: azure;
}
/* overwrite css */
.container {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="home">Home</div>
<div class="search">Search</div>
<div class="view">View</div>
<div class="logout">Logout</div>
</div>

Element to take remaining height of viewport

Please consider this style:
.root {
display: flex;
flex-direction: column;
height: 100%;
}
.header {
width: 100%;
background-color: red;
display: flex;
height: 100px;
justify-content: space-between;
.logo-pane {
width: 100px;
height: 100px;
background-color: green;
}
.user-actions {
width: 100px;
height: 100px;
background-color: blue;
}
}
.content {
flex-grow: 1;
background-color: pink;
}
What I want to achieve is that the content element will take the remaining height of the viewport, but it takes only his content height.
HTML:
<div class="root">
<div class="header">
<div class="logo-pane">Logo</div>
<div class="user-actions">User Actions</div>
</div>
<div class="content">
content
</div>
</div>
Codepen
The problem is the surrounding .root. You have to increase the height of the .root to the remaining space. So you have to set the height:100vh; on .root. Try the following solution:
body, html {
margin:0;
padding:0;
}
.root {
display: flex;
flex-direction: column;
height: 100vh;
align-items:stretch;
align-content:stretch;
}
.header {
width: 100%;
background-color: red;
display: flex;
height: 100px;
justify-content: space-between;
}
.logo-pane {
width: 100px;
height: 100px;
background-color: green;
}
.user-actions {
width: 100px;
height: 100px;
background-color: blue;
}
.content {
flex-grow:1;
background-color: pink;
}
<div class="root">
<div class="header">
<div class="logo-pane">Logo</div>
<div class="user-actions">User Actions</div>
</div>
<div class="content">content</div>
</div>
.content {
flex-grow: 1;
background-color: pink;
height: 100vh;
}
Set the :root to 100vh (100% of the viewport height) instead 100%
You can simply add
height: 100% to html, body
add height to 20% for root div
add height to 80% for content div
will solve your problem
html,body {
height: 100%;
}
Here is the jsFiddle
Hope it helps :)
I think your misunderstanding what flex does. Flex is used to align its children, not to fill a viewport. Heres another solution.
https://jsfiddle.net/rob_primacy/1wnpr50s/
<div class="root">
<div class="header">
<div class="logo-pane">Logo</div>
<div class="user-actions">User Actions</div>
</div>
</div>
<div class="content">
content
</div>
and the css
.root {
display: flex;
flex-direction: column;
height: 100%;
position: relative;
}
.header {
width: 100%;
background-color: red;
display: flex;
height: 100px;
justify-content: space-between;
position: relative;
}
.user-actions {
width: 100px;
height: 100px;
background-color: blue;
}
.logo-pane {
width: 100px;
height: 100px;
background-color: green;
}
.content {
background-color: pink;
position: absolute;
height: 100%;
left: 8px;
right: 8px;
}
Use like this
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Untitled 1</title>
<style type="text/css">
body{
margin:0;
}
.root {
display: flex;
flex-direction: column;
height: 100%;
}
.header {
width: 100%;
background-color: red;
display: flex;
height: 100px;
justify-content: space-between;
.logo-pane {
width: 100px;
height: 100px;
background-color: green;
}
.user-actions {
width: 100px;
height: 100px;
background-color: blue;
}
}
.content {
flex-grow: 1;
background-color: pink;
height:100%;
width:100%;
position: fixed;
}
</style>
</head>
<body>
<div class="root">
<div class="header">
<div class="logo-pane">Logo</div>
<div class="user-actions">User Actions</div>
</div>
<div class="content">
content
</div>
</div>
</body>
</html>
Your codepen linked works fine. I do not understand where you get stuck.
You could basicly build your template from 2 containers :example with header and main
html,
body {
height: 100%;/* or just : 100vh; for body only */
margin: 0;
}
body {
display: flex;
flex-direction: column;
/* width and margin:auto is avalaible */
}
header {
/* height: 50px;or do not set any and let grow from its content */
background: gray;
}
main {
flex: 1;/* will fill up all space left */
background: lightblue;
/* overflow:auto; optionnal if you do not want html to scroll and keep header fixed */
}
<header>
whatever <br/> sizes me
</header>
<main>
content
</main>
Make it simple to start with :)

Stopping flexbox from collapsing child width when auto margins are set

I'm using flexbox to create a sticky footer.
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
header, footer {
background-color: #c9c9c9;
padding: 20px;
}
main {
flex: 1;
margin: 0 auto;
max-width: 300px;
border: 1px solid red;
}
<header></header>
<main>This is some content</main>
<footer></footer>
JsFiddle
This works okay, but the width of <main> now collapses to fit the content, rather than expand to the max-width. This only happens when auto margins are set.
Is there any way to make <main> expand to the max-width when auto-margins are set?
Adding width: 100%; to <main> seems to fix this.
Fiddle link.
*, *:before, *:after {
box-sizing: border-box;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
header, footer {
background-color: #c9c9c9;
padding: 20px;
}
main {
flex: 1;
margin: 0 auto;
max-width: 300px;
width: 100%;
border: 1px solid red;
}
<header></header>
<main>This is some content</main>
<footer></footer>

Resources