Flexbox fill remaining height of 100% - html

Why doesn't "Box 2" fill the full (available) space? The height:100% is ignored...
HTML:
<div id="container">
<div id="box1">Box 1</div>
<div id="box2">Box 2</div>
<div id="box3">Box 3</div>
</div>
CSS:
body {
margin: 0 auto;
}
#container {
width: 100%;
height: 100%;
background: #cccccc;
display: -webkit-flex;
display: flex;
flex-direction: column
}
#box1 {
background: red;
height: 50px
}
#box2 {
background: yellow;
-webkit-flex: 1;
flex: 1
}
#box3 {
background: green;
height: 50px
}
http://jsfiddle.net/618axkjy/2/
Thanks!

It's because the parent #container element doesn't have a height of 100%. At the moment, the height of the body element is determined by the height of the #container element (since it's the only child). Since you're defining the height of the #container element using percentages, the height will remain the same since the parent's height is also the same.
You need to set the height of the html/body elements to 100%:
Updated Example
html, body, #container {
height: 100%;
}
..or you could define the height of the #container element in viewport-percentage units, vh:
Updated Example
#container {
height: 100vh; /* 100% of the viewport height */
}

Related

setting fixed width with 100% height of the parent

In the following HTML, I want to set the height of left and right 100% of the parent element. In addition, the left div has fixed width. The right should use all of the remaining width.
I think because of using display: flex; in the parents div, the width of the left div doesn't stay constant. How can I set fixed width for it and allocate all of the remaining space to the right.
Edit: the calc(100-52px) is the height of the parent. The question is only about setting fixed width of 100px to the left so that it doesn't change on resizing the window.
Here's what I'm trying:
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
width: 100px;
background: yellow;
}
.right {
background: orange;
width: 100%;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
parent { display: -webkit-box;display:-webkit-flex;display: -ms-flexbox;display:flex;flex-wrap: wrap; }
.parent > [class*='col-'] { display: flex; flex-direction: column; }
You can use width: calc(100% - 100px) or flex: 1 for the right div.
Percentage values are calculated from the parent element, therefore you need to extract static values from 100% to get the remaining area.
But as you are already using a flex container here, you can just set flex: 1, which is the shorthand for flex-grow: 1, that will allow your container to take all the extra space in the parent container, since no other items are available.
Add a flex declaration to the .left selector:
flex: 0 0 100px;
flex syntax:
none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
So this declaration is stating: "don't grow, don't shrink, define the initial size as 100px"
Read more: flex (MDN)
If right is to stand 52px away from the far right, then a margin will do . Please clarify your question.
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
width: 100px;
background: yellow;
}
.right {
flex-grow: 1;
background: orange;
margin-right: 52px;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
Set flex: 0 0 100px; on your .left div (you can remove width: 100px) if you want it to be a constant 100px - so no growing or shrinking.
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
flex: 0 0 100px;
background: yellow;
}
.right {
background: orange;
width: 100%;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
see if this helps you, comment if you need any changes
stackblits link for 1 fixed width, 1 relative column

Height is not correct in flexbox items in Chrome [duplicate]

This question already has answers here:
Chrome / Safari not filling 100% height of flex parent
(5 answers)
Closed 6 years ago.
I've got a delicate problem for any CSS guru out there.
My green div has a flexible height, taking up the remaining.
And now I want to put a div inside that div which should be the half of the green div. But it seems like if Chrome treats it like half of the whole page rather than the flex item.
http://jsfiddle.net/unh5rw9t/1/
HTML
<body>
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
</body>
CSS
html,body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
background-color: green;
}
#half_of_content {
height: 50%;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
#Michael_B explained why Chrome behaves like this:
You gave the body a height: 100%. Then gave its child (.wrapper)
a height: 100%. Then gave its child (.content) a height: 100%.
So they're all equal height. Giving the next child (#half_of_content) a height: 50% would naturally be a 50% height
of body.
However, Firefox disagrees because, in fact, that height: 100% of .content is ignored and its height is calculated according to flex: 1.
That is, Chrome resolves the percentage with respect to the value of parent's height property. Firefox does it with respect to the resolved flexible height of the parent.
The right behavior is the Firefox's one. According to Definite and Indefinite Sizes,
If a percentage is going to be resolved against a flex item’s
main size, and the flex item has a definite flex
basis, and the flex container has a definite main
size, the flex item’s main size must be treated as
definite for the purpose of resolving the percentage, and the
percentage must resolve against the flexed main size of the
flex item (that is, after the layout algorithm below has been
completed for the flex item’s flex container, and the flex
item has acquired its final size).
Here is a workaround for Chrome:
#content {
display: flex;
flex-direction: column;
}
#content::after {
content: '';
flex: 1;
}
#half_of_content {
flex: 1;
height: auto;
}
This way the available space in #content will be distributed equally among #half_of_content and the ::after pseudo-element.
Assuming #content doesn't have other content, #half_of_content will be 50%. In your example you have a 2 in there, so it will be a bit less that 50%.
html,
body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
background-color: green;
display: flex;
flex-direction: column;
}
#content::after {
content: '';
flex: 1;
}
#half_of_content {
flex: 1;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
You could absolutely position div id="half_of_content".
#content {
flex: 1;
height: 100%;
background-color: green;
position: relative; /* new */
}
#half_of_content {
height: 50%;
background-color: yellow;
position: absolute; /* new */
width: 100%; /* new */
}
DEMO
With regard to your statement:
But it seems like if Chrome treats it like half of the whole page
rather than the flex item.
You gave the body a height: 100%. Then gave its child (.wrapper) a height: 100%. Then gave its child (.content) a height: 100%. So they're all equal height. Giving the next child (#half_of_content) a height: 50% would naturally be 50% height of body.
With absolute positioning, however, you don't need to specify parent heights.
Nesting flexboxes is a little buggy. I reworked your markup a little by adding an inner wrapper with display: flex; which seems to do the job. Here is the fiddle (also using class names instead of ids).
<div class="content">
<div class="wrapper-inner">
2
<div class="half">
2.1
</div>
</div>
</div>
.wrapper-inner {
position: absolute;
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
Fix:
on #content set
display: flex;
flex-flow: column nowrap;
justify-content: flex-end
on #half_of_content set flex: 0 0 50%;
Caveat: you need to add an extra div as a child of #content.
Here's the full example:
html,body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
display:flex;
flex-flow: column nowrap;
justify-content: flex-end;
background-color: green;
}
#half_of_content {
flex: 0 0 50%;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
<body>
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
</body>

Fluid three column layout with fixed width center column

I want to obtain this layout:
<------------ Browser Width 100% ------------>
[left][----- center: fixed width -----][right]
The center column has a fixed pixel width
The left and right columns fill in the remaining viewport width equally
The example below breaks when the viewport width is not wide enough, and getting the correct percentage width is hard because of the fixed width center column.
div {
display: inline-block;
background: #F90;
height: 100px;
width: 20%;
}
.center {
width: 500px;
background: #FF0;
}
<div class="left">left (fill available space)</div>
<div class="center">fixed width</div>
<div class="right">right (fill available space)</div>
Three ways to achieve a fluid / fixed column layout
Method #1 - with display: table
This is one of the easiest methods and has good browser support.
Compatibility: IE8 + and all modern browsers
body gets display: table - this could also be applied to a div wrapper instead.
table-layout: fixed ensures the middle column remains fixed width
the direct div children of body get display: table-cell
the body gets a min-width to ensure the left and right columns do not get too small
the middle column is fixed at your desired width (500px in this example)
the left and right columns inherit the remaining page width
#1 - Working Example
html {
height: 100%;
}
body {
display: table;
height: 100%;
margin: 0;
width: 100%;
table-layout: fixed;
min-width: 800px;
}
body > div {
display: table-cell;
}
.left {
background: #000;
}
.middle {
background: #F00;
width: 500px;
}
.right {
background: #F90
}
<div class="left">
</div>
<div class="middle">
</div>
<div class="right">
</div>
Method #2 - with display: inline-block and width: calc(x - y)
Compatibility: Calc is compatible in IE 9 + and most modern browsers. There are javascript fallbacks available as well.
The direct div children of body are given display: inline-block and vertical-align: top. They will align themselves to the top of the browser window on the same line
The middle column gets its fixed width
The left and right columns are given calc(50% - 250px); this calculates 50% of the page width minus half of the width of the fixed middle column.
box-sizing: border-box incorporates padding and borders into the width and height
#2 - Working Example
Note how the closing and opening divs tags have no gaps between them; this is to prevent an inline gap between elements.
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
}
body {
min-width: 800px;
}
body > div {
display: inline-block;
width: calc(50% - 250px);
height: 100%;
vertical-align: top;
}
.left {
background: #000;
}
.middle {
background: #F00;
width: 500px;
}
.right {
background: #F90
}
<div class="left"></div><div class="middle"></div><div class="right"></div>
Method #3 - with display: flex
This is a really awesome method, but is not supported with older browsers :(
Compatibility: IE11 and most modern browsers
The body gets display: flex and height: 100vh (100% of the viewport height)
The direct children get flex: 1 and will grow and shrink
The middle column gets its fixed width and flex: 0 0 auto; it will not grow or shrink
Here is a useful guide to Flexbox.
#3 - Working Example
body {
display: flex;
height: 100vh;
margin: 0;
min-width: 800px;
}
body > div {
flex: 1;
}
.left {
background: #000;
}
.middle {
background: #F00;
width: 500px;
flex: 0 0 auto;
}
.right {
background: #F90
}
<div class="left">
</div>
<div class="middle">
</div>
<div class="right">
</div>

css flex layout fit child into flex box

I want to have a child fill the exactly entire flex box of a flex layout.
If I use the following HTML:
<div class="parent">
<div class="child1">
should have 100px height
</div>
<div class="child2">
<div class="intermediatechild2">
<div class="subchild2">should have 200px height and padding</div>
</div>
</div>
</div>
and apply the following css:
.parent {
display: flex;
flex-direction : column;
height: 300px;
width: 200px;
}
.child1 {
height: 100px;
background: #008800;
flex: 0 0 auto;
}
.child2 {
height: 100%;
background: #003300;
flex: 0 0 auto;
}
.subchild2 {
height : 100%;
background: #ff0000;
}
.intermediatechild2 {
padding: 20px;
height : 100%;
width : 100%;
box-sizing: border-box;
border: 2px solid blue;
}
I get an overflowing intermediatechild. The height 100% seems to be relative to .parent
A fiddle can be found here:
http://jsfiddle.net/8znFV/4/
I did not understand exactly what you want, but if what you want is only leave. Subchild2 100% and follow the father's height (intermediatechild2), you'll have to add the father's height (intermediatechild2) with px and remove the height. child2.
Recalling that, you have to count the padding in father's height (intermediatechild2), so if you want. Subchild2 has 200px in height, will have to leave her father (intermediatechild2) with 240px, leaving 20 padding-top and 20 padding-bottom height of more than 200.
A note, only work in chrome as your css code is nonstandard, if you want I can breastfeed him at another time =)
Hope it helps
Here's an example: http://zip.net/bsmZgF
Just Remove height:100% from .child2and it will work. this will give 100% height to child2 element so it's going outside of parent.
It should be auto adjusted that's the purpose of flexbox and 100% height is giving more height(same as parent) to child2.
I fixed the problem. The solution lies in staying "display:flex". Once you started flex layout, you seem not to be able to step back to "display:block" with "height:100%".
<div class="parent">
<div class="child1">
should have 100px height
</div>
<div class="child2">
<div class="intermediatechild2">
<div class="subchild2">should have 200px height including padding</div>
</div>
</div>
</div>
css:
.parent {
display: flex;
flex-direction : column;
height: 300px;
width: 200px;
}
.child1 {
height: 100px;
background: #008800;
}
.child2 {
background: #003300;
flex: 1;
display: flex;
}
.subchild2 {
background: #ff0000;
flex: 1;
}
.intermediatechild2 {
padding: 20px;
display : flex;
box-sizing: border-box;
border: 2px solid blue;
}
working fiddle : http://jsfiddle.net/8znFV/6/

How to enforce the height of inner div to be equal to the height of the parent div, if the parent div has "min-height"?

Why in the following example the height of the inner div is not like wrapper's div ?
Live demo here.
HTML:
<div class="wrapper">
<div class="inner">Hello</div>
<div class="inner">Peace</div>
</div>
CSS:
.wrapper {
background-color: #000;
min-height: 100px;
}
.inner {
display: inline-block;
background-color: #777;
height: 100%;
}
If I change min-height: 100px; to height: 100px;, then it looks OK. But, in my case, I need min-height.
Some properties in CSS inherit the value of the parent automatically, some don't. Minimum height must be explicitly stated when you want it to inherit the parent's value:
min-height: inherit;
I believe this is the output you want: http://jsfiddle.net/xhp7x/
.wrapper {
display: table;
background-color: #000;
height: 100px;
width: 100%;
}
.wrapper2 {
height: 100%;
display: table-row
}
.inner {
height: 100%;
display: inline-block;
background-color: #777;
margin-right: 10px;
vertical-align: top;
}
Had to add a second DIV wrapper2.
Tested on chrome and firefox.
You want to specify both, CSS height is not the same as min-height. You want to specify both height and min-height.
height = When used as a %, this is a percent of the window height
min-height = as you drag the window smaller, the DIV with a % height will continue to reduce until it hits the min-height
max-height = as you drag the window larger, the DIV with a % height will continue to increase until it hits the max-height
http://jsfiddle.net/gpeKW/2/ I've added a sample here with borders.
Slight change to the answer from your comment, you are pretty much correct from your original CSS.
The below HTML will have a minimum div height of 100px. As the size of the inner DIV increases, the wrapper will automatically expand. I have demonstrated this by adding a style attribute to the first inner class.
<html>
<head>
<title>Untitled Page</title>
<style type="text/css">
.wrapper
{
background-color: #000;
min-height:100px;
}
.inner
{
display: inline-block;
background-color: #777;
height: 100%;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="inner" style="height:200px">test</div>
<div class="inner">Peace</div>
</div>
</body>
</html>
I know one way to set the div child height the same as its parent div height is to use relative for the parent and absolute position for the child.
.wrapper {
background-color: #000;
min-height: 100px;
position: relative;
}
.inner {
display: inline-block;
background-color: #777;
position: absolute;
height: 100%;
}
But this way will cause some problem, you have to adjust the child element so that it will be displayed properly
P/s: Why don't you set it to the same height as its parent height? I mean, 100% is not x%... just thinking..
Anyway, happy coding ;)
I certainly joined answers and the result using 'min-height' for the -main HTML tag- (class = "main-page-container"):
HTML:
<div id="divMainContent">
<!-- before or after you can use multiples divs or containers HTML elements-->
<div> </div>
<div> </div>
<main class="main-page-container">
<div class="wrapper">
1
<div class="wrapper2">
2
<div class="child">3</div>
</div>
</div>
</main>
<!-- before or after you can use multiples divs or containers HTML elements-->
<div class="footer-page-container bg-danger" > more relevant info</div>
</div>
CSS:
/*#region ---- app component containers ---- */
#divMainContent {
height: 100%;
display: flex;
flex-direction: column;
/*optional: max width for screens with high resolution*/
max-width: 1280px;
margin:0 auto;
}
.main-page-container {
display: inline-table;
height: 70%;
min-height: 70%;
width: 100%;
}
.footer-page-container{
flex:1; /* important in order to cover the rest of height */
/* this is just for your internal html tags
display: flex;
flex-direction: column;
justify-content: space-between; */
}
/*#endregion ---- app component containers ---- */
.wrapper {
background: blue;
max-width: 1280px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
}
.wrapper2 {
width: 90%;
margin: auto;
background: pink;
display: flex;
flex-wrap: wrap;
gap: 20px;
height: 90%;
}
.child {
min-height: 100px;
min-width: 300px;
background: orange;
position: relative;
width: 33%;
}