Child inside parent with min-height: 100% not inheriting height
CssHtmlCss Problem Overview
I found a way to make a div container to occupy at least full height of a page, by setting min-height: 100%;
. However, when I add a nested div and set height: 100%;
, it doesn't stretch to container's height. Is there a way to fix it?
html, body {
height: 100%;
margin: 0;
}
#containment {
min-height: 100%;
background: pink;
}
#containment-shadow-left {
height: 100%;
background: aqua;
}
<div id="containment">
<div id="containment-shadow-left">
Hello World!
</div>
</div>
Css Solutions
Solution 1 - Css
Add height: 1px
to parent container. Works in Chrome, FF, Safari.
Solution 2 - Css
This is a reported webkit (chrome/safari) bug, children of parents with min-height can't inherit the height property: https://bugs.webkit.org/show_bug.cgi?id=26559
Apparently Firefox is affected too (can't test in IE at the moment)
Possible workaround:
- add position:relative to #containment
- add position:absolute to #containment-shadow-left
The bug doesn't show when the inner element has absolute positioning.
See http://jsfiddle.net/xrebB/
Edit on April 10, 2014
Since I'm currently working on a project for which I really need parent containers with min-height
, and child elements inheriting the height of the container, I did some more research.
First: I'm not so sure anymore whether the current browser behaviour really is a bug. CSS2.1 specs say:
> The percentage is calculated with respect to the height of the > generated box's containing block. If the height of the containing > block is not specified explicitly (i.e., it depends on content > height), and this element is not absolutely positioned, the value > computes to 'auto'.
If I put a min-height on my container, I'm not explicitly specifying its height - so my element should get an auto
height. And that's exactly what Webkit - and all other browsers - do.
Second, the workaround I found:
If I set my container element to display:table
with height:inherit
it acts exactly the same way as if I'd give it a min-height
of 100%. And - more importantly - if I set the child element to display:table-cell
it will perfectly inherit the height of the container element - whether it's 100% or more.
Full CSS:
html, body {
height: 100%;
margin: 0;
}
#container {
background: green;
display: table;
height: inherit;
width: 100%;
}
#content {
background: red;
display: table-cell;
}
The markup:
<div id="container">
<div id="content">
<p>content</p>
</div>
</div>
Solution 3 - Css
thought I would share this, as I didnt see this anywhere, and is what I used to fix my solution.
SOLUTION: min-height: inherit;
I had a parent with a specified min height, and I needed a child to also be that height.
.parent {
min-height: 300px;
background-color: rgba(255,255,0,0.5); //yellow
}
.child {
min-height: inherit;
background-color: rgba(0,255,0,0.5); //blue
}
p {
padding: 20px;
color: red;
font-family: sans-serif;
font-weight: bold;
text-align: center;
}
<div class="parent">
<div class="child">
<p>Yellow + Blue = Green :)</p>
</div>
</div>
This way the child now acts as height 100% of the min-height.
I hope some people find this useful :)
Solution 4 - Css
This was added in a comment by @jackocnr but I missed it. For modern browsers I think this is the best approach.
It makes the inner element fill the whole container if it's too small, but expands the container's height if it's too big.
#containment {
min-height: 100%;
display: flex;
flex-direction: column;
}
#containment-shadow-left {
flex: 1;
}
Solution 5 - Css
Kushagra Gour's solution does work (at least in Chrome and IE) and solves the original problem without having to use display: table;
and display: table-cell;
. See plunker: http://plnkr.co/edit/ULEgY1FDCsk8yiRTfOWU
Setting min-height: 100%; height: 1px;
on the outer div causes its actual height to be at least 100%, as required. It also allows the inner div to correctly inherit the height.
Solution 6 - Css
Although display: flex;
has been suggested here, consider using display: grid;
now that it's widely supported. By default, the only child of a grid will entirely fill its parent.
html, body {
height: 100%;
margin: 0;
padding: 0; /* Don't forget Safari */
}
#containment {
display: grid;
min-height: 100%;
background: pink;
}
#containment-shadow-left {
background: aqua;
}
Solution 7 - Css
In addition to the existing answers, there is also viewport units vh
to use. Simple snippet below. Of course it can be used together with calc()
as well, e.g. min-height: calc(100vh - 200px);
when page header and footer have 200px
height together.
body {
margin: 0;
}
.child {
min-height: 100vh;
background: pink;
}
<div class="parent">
<div class="child"></div>
</div>
Solution 8 - Css
I don't believe this is a bug with browsers. All behave the same way - that is, once you stop specifying explicit heights, min-height is basically a "last step".
It appears to be exactly how the CSS 2.1 spec suggests: http://www.w3.org/TR/CSS2/visudet.html#the-height-property
> The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.
Therefore, as the min-height
parent does not have an explicit height
property set, it defaults to auto.
There are some ways around this possibly by using display: table-cell
, or newer styles such as flexbox, if that is possible for your targeted audience's browsers. You can also subvert this in certain situations by using the top
and bottom
properties on an absolutely positioned inner element, which gives you 100% height without specifying so.
Solution 9 - Css
This usually works for me:
.parent {
min-height: 100px;
background-color: green;
display: flex;
}
.child {
height: inherit;
width: 100%;
background-color: red;
}
<!DOCTYPE html>
<html>
<body>
<div class="parent">
<div class="child">
</div>
</div>
</body>
</html>
Solution 10 - Css
For googlers:
This jquery-workaround makes #containment get a height automatically (by, height: auto), then gets the actual height assigned as a pixel value.
<script type="text/javascript">
<!--
$(function () {
// workaround for webkit-bug http://stackoverflow.com/a/8468131/348841
var rz = function () {
$('#containment')
.css('height', 'auto')
.css('height', $('#containment').height() + 'px');
};
$(window).resize(function () {
rz();
});
rz();
})
-->
</script>
Solution 11 - Css
Another JS solution, that is easy and can be used to avoid a non-easy CSS-only or extra markup / hacky solution.
function minHeight(elm, percent) {
var windowHeight = isNaN(window.innerHeight) ?
window.clientHeight : window.innerHeight;
var height = windowHeight * percent / 100;
elm.style.minHeight = height + 'px';
}
W/ jQuery :
function minHeight($elm, percent) {
var windowHeight = $(window).height();
var height = windowHeight * percent / 100;
$elm.css('min-height', height + 'px');
}
Angular directive :
myModule.directive('minHeight', ['$window', function($window) {
return {
restrict: 'A',
link: function(scope, elm, attrs) {
var windowHeight = isNaN($window.innerHeight) ?
$window.clientHeight : $window.innerHeight;
var height = windowHeight * attrs.minHeight / 100;
elm.css('min-height', height + 'px');
}
};
}]);
To be used like this :
<div>
<!-- height auto here -->
<div min-height="100">
<!-- This guy is at least 100% of window height but grows if needed -->
</div>
</div>
Solution 12 - Css
The best way to achieve this nowadays is to use display: flex;
. However you might run into an issue when trying to support IE11. According to https://caniuse.com using flexbox :
> IE 11 does not vertically align items correctly when min-height is used
Internet Explorer compatible solution
The solution is to use display: table;
on the parent and display: table-row;
on the child both with height: 100%;
as a replacement for min-height: 100%;
.
Most of the solutions listed here use display:
table
, table-row
and/or table-cell
, but they don't replicate the same behaviour as min-height: 100%;
, which is:
- Inherit the computed height of the parent (as opposed to inheriting its
height
property); - Allow the parent's height to exceed its
min-height
;
While using this solution, the behaviour is the same and the property min-height
is not needed which allows to get around the bug.
Explanation
The reason why it works is because, unlike most elements, elements using display:
table
and table-row
will always be as tall as their content. This makes their height
property behave similarly to min-height
.
Solution in action
html, body {
height: 100px;
margin: 0;
}
#containment {
display: table;
height: 100%;
background: pink;
width: 100%;
}
#containment-shadow-left {
display: table-row;
height: 100%;
background: aqua;
}
#content {
padding: 15px;
}
#demo {
display: none;
background-color: red;
height: 200px;
}
#demo-checkbox:checked ~ #demo {
display: block;
}
<div id="containment">
<div id="containment-shadow-left">
<div id="content">
<input id="demo-checkbox" type="checkbox">
<label for="demo-checkbox">Click here for overflow demo</label>
<div id="demo">This is taller than #containment</div>
</div>
</div>
</div>
Solution 13 - Css
Adding this to parent component fixed it for me:
display: flex;
flex-direction: column;
Solution 14 - Css
Just to keep this subject complete, I found a solution not explored Here using Fixed position.
No Overflow
html, body, .wrapper, .parent, .child {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
height: 100%;
}
.child {
overflow: auto;
background: gray;
}
.height-50 {
height: 50%;
width: 5em;
margin: 10px auto;
background: cyan;
}
<div class="wrapper">
<div class="parent">
<div class="child">
<div class="height-50"></div>
</div>
</div>
</div>
With Overflow
html, body, .wrapper, .parent, .child {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
height: 100%;
}
.child {
overflow: auto;
background: gray;
}
.height-150 {
height: 150%;
width: 5em;
margin: 10px auto;
background: cyan;
}
<div class="wrapper">
<div class="parent">
<div class="child">
<div class="height-150"></div>
</div>
</div>
</div>
Solution 15 - Css
after trying for ours! chrome understands that I want the child element to be 100% height when I set the display value to inline block. btw setting float will causing it.
display:inline-block
update
this is not working. the solution is to get the parentnode offsetheight and use it at the and of the page with javascript.
<script>
SomedivElement = document.getElementById('mydiv');
SomedivElement.style.height = String(nvleft.parentNode.offsetHeight) + 'px';
</script>
Solution 16 - Css
This is what works for me with percentage-based height and parent still growing according to children height. Works fine in Firefox, Chrome and Safari.
.parent {
position: relative;
min-height: 100%;
}
.child {
min-height: 100vh;
}
<div class="parent">
<div class="child"></div>
</div>