Reputation: 9682
Consider the following HTML/css code sample:
<div id="container">
<div id="up">Text<br />Text<br />Text<br /></div>
<div id="down">Text<br />Text<br />Text<br /></div>
</div>
#container { width: 300px; height: 300px; border:1px solid red;}
#up { background: green; }
#down { background:pink;}
where I have a container div
with two children (also here: http://jsfiddle.net/S8g4E/). The first child has a given height. How can I make the second child to occupy the "free space" of the container div
without giving a specific height?
In the example, the pink div
should occupy also the white space.
Similar to this question: How to make div occupy remaining height?
But I don't want to give position absolute.
Upvotes: 169
Views: 233174
Reputation: 17487
Expanding the #down
child to fill the remaining space of #container
can be accomplished in various ways depending on the browser support you wish to achieve and whether or not #up
has a defined height.
Note (2024): CSS now has max-content
property value for sizing as well, so if you don't have a fixed height (e.g. 100px) then you might be able to use that.
Samples
.container {
width: 100px;
height: 300px;
border: 1px solid red;
float: left;
}
.up {
background: green;
}
.down {
background: pink;
}
.grid.container {
display: grid;
grid-template-rows: 100px;
}
.flexbox.container {
display: flex;
flex-direction: column;
}
.flexbox.container .down {
flex-grow: 1;
}
.calc .up {
height: 100px;
}
.calc .down {
height: calc(100% - 100px);
}
.overflow.container {
overflow: hidden;
}
.overflow .down {
height: 100%;
}
<div class="grid container">
<div class="up">grid
<br />grid
<br />grid
<br />
</div>
<div class="down">grid
<br />grid
<br />grid
<br />
</div>
</div>
<div class="flexbox container">
<div class="up">flexbox
<br />flexbox
<br />flexbox
<br />
</div>
<div class="down">flexbox
<br />flexbox
<br />flexbox
<br />
</div>
</div>
<div class="calc container">
<div class="up">calc
<br />calc
<br />calc
<br />
</div>
<div class="down">calc
<br />calc
<br />calc
<br />
</div>
</div>
<div class="overflow container">
<div class="up">overflow
<br />overflow
<br />overflow
<br />
</div>
<div class="down">overflow
<br />overflow
<br />overflow
<br />
</div>
</div>
Grid
CSS's grid
layout offers yet another option, though it may not be as straightforward as the Flexbox model. However, it only requires styling the container element:
.container { display: grid; grid-template-rows: 100px }
The grid-template-rows
defines the first row as a fixed 100px height, and the remain rows will automatically stretch to fill the remaining space.
I'm pretty sure IE11 requires -ms-
prefixes, so make sure to validate the functionality in the browsers you wish to support.
Flexbox
CSS3's Flexible Box Layout Module (flexbox
) is now well-supported and can be very easy to implement. Because it is flexible, it even works when #up
does not have a defined height.
#container { display: flex; flex-direction: column; }
#down { flex-grow: 1; }
It's important to note that IE10 & IE11 support for some flexbox properties can be buggy, and IE9 or below has no support at all.
Calculated Height
Another easy solution is to use the CSS3 calc
functional unit, as Alvaro points out in his answer, but it requires the height of the first child to be a known value:
#up { height: 100px; }
#down { height: calc( 100% - 100px ); }
It is pretty widely supported, with the only notable exceptions being <= IE8 or Safari 5 (no support) and IE9 (partial support). Some other issues include using calc in conjunction with transform or box-shadow, so be sure to test in multiple browsers if that is of concern to you.
Other Alternatives
If older support is needed, you could add height:100%;
to #down
will make the pink div full height, with one caveat. It will cause overflow for the container, because #up
is pushing it down.
Therefore, you could add overflow: hidden;
to the container to fix that.
Alternatively, if the height of #up
is fixed, you could position it absolutely within the container, and add a padding-top to #down
.
And, yet another option would be to use a table display:
#container { width: 300px; height: 300px; border: 1px solid red; display: table;}
#up { background: green; display: table-row; height: 0; }
#down { background: pink; display: table-row;}
Upvotes: 232
Reputation: 1228
<div class='parent'>
<div class='child'>
<div class='child last'>
</div>
<style>
.parent {
display: flex;
flex-direction: column;
.child {
&.last {
flex-grow: 1;
}
}
}
</style>
Upvotes: 2
Reputation: 4166
My answer uses only CSS, and it does not use overflow:hidden or display:table-row. It requires that the first child really does have a given height, but in your question you state that only the second child need have its height not specified, so I believe you should find this acceptable.
#container {
width: 300px;
height: 300px;
border: 1px solid red;
}
#up {
background: green;
height: 63px;
float: left;
width: 100%
}
#down {
background: pink;
padding-top: 63px;
height: 100%;
box-sizing: border-box;
}
<div id="container">
<div id="up">Text<br />Text<br />Text<br /></div>
<div id="down">Text<br />Text<br />Text<br /></div>
</div>
Upvotes: 6
Reputation: 4071
I didn't find a fully satisfying answer so I had to find it out myself.
My requirements:
calc()
should not be used as the remaining element shouldn't know anything about another element sizes;flex-grow: 1
to all direct parents with computed height (if any) and the element so they will take up all remaining space when the element content size is smaller;flex-shrink: 0
to all flex items with fixed height so they won't become smaller when the element content size is bigger than the remaining space size;overflow: hidden
to all direct parents with computed height (if any) to disable scrolling and forbid displaying overflow content;overflow: auto
to the element to enable scrolling inside it.JSFiddle (element has direct parents with computed height)
JSFiddle (simple case: no direct parents with computed height)
Upvotes: 35
Reputation: 9682
Its been almost two years since I asked this question. I just came up with css calc() that resolves this issue I had and thought it would be nice to add it in case someone has the same problem. (By the way I ended up using position absolute).
http://jsfiddle.net/S8g4E/955/
Here is the css
#up { height:80px;}
#down {
height: calc(100% - 80px);//The upper div needs to have a fixed height, 80px in this case.
}
And more information about it here: http://css-tricks.com/a-couple-of-use-cases-for-calc/
Browser support: http://caniuse.com/#feat=calc
Upvotes: 24
Reputation: 28665
Unless I am misunderstanding, you can just add height: 100%;
and overflow:hidden;
to #down
.
#down {
background:pink;
height:100%;
overflow:hidden;
}
Edit: Since you do not want to use overflow:hidden;
, you can use display: table;
for this scenario; however, it is not supported prior to IE 8. (display: table;
support)
#container {
width: 300px;
height: 300px;
border:1px solid red;
display:table;
}
#up {
background: green;
display:table-row;
height:0;
}
#down {
background:pink;
display:table-row;
}
Note: You have said that you want the #down
height to be #container
height minus #up
height. The display:table;
solution does exactly that and this jsfiddle will portray that pretty clearly.
Upvotes: 2
Reputation: 12190
check the demo - http://jsfiddle.net/S8g4E/6/
use css -
#container { width: 300px; height: 300px; border:1px solid red; display: table;}
#up { background: green; display: table-row; }
#down { background:pink; display: table-row;}
Upvotes: 2
Reputation: 14626
You can use floats for pushing content down:
You have a fixed size container:
#container {
width: 300px; height: 300px;
}
Content is allowed to flow next to a float. Unless we set the float to full width:
#up {
float: left;
width: 100%;
}
While #up
and #down
share the top position, #down
's content can only start after the bottom of the floated #up
:
#down {
height:100%;
}
Upvotes: 1
Reputation: 13800
I'm not sure it can be done purely with CSS, unless you're comfortable in sort of faking it with illusions. Maybe use Josh Mein's answer, and set #container
to overflow:hidden
.
For what it's worth, here's a jQuery solution:
var contH = $('#container').height(),
upH = $('#up').height();
$('#down').css('height' , contH - upH);
Upvotes: -2