Stopping flexbox from collapsing child width when auto margins are set - css

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>

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>

How to make full height sidebar with dynamic main content?

I have an angular2 app with left a sidebar and dynamic main content.
HTML:
<body>
<div class="full_height">
<div class="sidebar">Some content</div>
<div class="main">Some dynamic content</div>
</div>
</body>
CSS:
body{
width: 100%;
height: 100%;
margin: 0;
}
.full_height{
display: flex;
flex-direction: row;
align-items: stretch;
}
.sidebar{
background: black;
color: white;
width: 150px;
flex: 0 0 auto;
}
.main{
flex: 1 1 auto;
}
I need the sidebar grow to 100% height of the browser body if no information in the main block. And I need the sidebar and the main block have equal height when a big amount of information have been loaded to the main block via AJAX.
How to make the first part work?
JSFiddle
I think you just forgot to assign a 100% height to the HTML element. Is this what you tried to do ?
html, body{
width: 100%;
height: 100%;
margin: 0;
}
.full_height{
display: flex;
flex-direction: row;
align-items: stretch;
height: 100%;
}
.sidebar{
background: black;
color: white;
width: 150px;
flex: 0 0 auto;
}
.main{
flex: 1 1 auto;
}
<body>
<div class="full_height">
<div class="sidebar">Some content</div>
<div class="main">Some dynamic content</div>
</div>
</body>
If you want to make full height sidebar then sidebar will be fixed position and rest of the content will be relative position. Please check the below Snippet.
html{
box-sizing: border-box;
height: 100%;
width: 100%;
}
*,
*:after,
*:before{
box-sizing: inherit;
}
body{
margin: 0;
padding: 0;
}
.full_height{
background-color: white;
display: flex;
flex-direction: column;
}
#media (min-width: 992px){
.full_height{
padding-left: 330px;
}
}
.sidebar{
background-color: #5c5c5c;
color: white;
display: flex;
flex-direction: column;
margin-bottom: 30px;
padding: 20px;
width: 100%;
}
#media (min-width: 992px){
.sidebar{
height: 100%;
left: 0;
overflow-x: hidden;
overflow-y: auto;
position: fixed;
top: 0;
width: 310px;
z-index: 1030;
}
}
.main{
background-color: #009688;
color: white;
font-size: 20px;
margin-bottom: 30px;
padding: 20px;
width: 100%;
}
<div class="full_height">
<div class="sidebar">Some content</div>
<div class="main">Some dynamic content</div>
</div>
Snippet two This relative content
html{
box-sizing: border-box;
height: 100%;
width: 100%;
}
*,
*:after,
*:before{
box-sizing: inherit;
}
body{
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
.full_height{
background-color: black;
display: flex;
flex-direction: column;
padding: 20px;
}
#media (min-width: 992px){
.full_height{
align-items: stretch;
flex-direction: row;
flex-wrap: nowrap;
height: 100%;
width: 100%;
}
}
.sidebar{
background-color: #f5f5f5;
color: #009688;
flex-basis: 100%;
flex-grow: 0;
flex-shrink: 0;
max-width: 100%;
padding: 20px;
}
#media (min-width: 992px){
.sidebar{
flex-basis: 310px;
max-width: 310px;
}
}
.main{
background-color: white;
color: black;
padding: 20px;
width: 100%;
}
#media (min-width: 992px){
.main{
padding-left: 40px;
}
}
<div class="full_height">
<div class="sidebar">Sidebar content</div>
<div class="main">Main Content</div>
</div>
Check the Snippet in full width view. All snippet is responsive.
If you want both the .sidebar and .main to fill the entire screen, just add the 100vh height.
.sidebar,
.main {
height: 100vh;
}

Flexbox body and main min-height

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>

Resources