[css] Child inside parent with min-height: 100% not inheriting height

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?

_x000D_
_x000D_
html, body {_x000D_
  height: 100%;_x000D_
  margin: 0;_x000D_
}_x000D_
_x000D_
#containment {_x000D_
  min-height: 100%;_x000D_
  background: pink;_x000D_
}_x000D_
_x000D_
#containment-shadow-left {_x000D_
  height: 100%;_x000D_
  background: aqua;_x000D_
}
_x000D_
<div id="containment">_x000D_
  <div id="containment-shadow-left">_x000D_
    Hello World!_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

This question is related to css html

The answer is


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.


This usually works for me:


_x000D_
_x000D_
.parent {_x000D_
  min-height: 100px;_x000D_
  background-color: green;_x000D_
  display: flex;_x000D_
}_x000D_
.child {_x000D_
  height: inherit;_x000D_
  width: 100%;_x000D_
  background-color: red;_x000D_
}
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
  <body>_x000D_
    <div class="parent">_x000D_
      <div class="child">_x000D_
      </div>_x000D_
    </div>_x000D_
  </body>_x000D_
</html>
_x000D_
_x000D_
_x000D_

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

_x000D_
_x000D_
html, body {_x000D_
  height: 100px;_x000D_
  margin: 0;_x000D_
}_x000D_
_x000D_
#containment {_x000D_
  display: table;_x000D_
  height: 100%;_x000D_
  background: pink;_x000D_
  width: 100%;_x000D_
}_x000D_
_x000D_
#containment-shadow-left {_x000D_
  display: table-row;_x000D_
  height: 100%;_x000D_
  background: aqua;_x000D_
}_x000D_
_x000D_
#content {_x000D_
  padding: 15px;_x000D_
}_x000D_
_x000D_
#demo {_x000D_
  display: none;_x000D_
  background-color: red;_x000D_
  height: 200px;_x000D_
}_x000D_
_x000D_
#demo-checkbox:checked ~ #demo {_x000D_
  display: block;_x000D_
}
_x000D_
<div id="containment">_x000D_
  <div id="containment-shadow-left">_x000D_
    <div id="content">_x000D_
      <input id="demo-checkbox" type="checkbox">_x000D_
      <label for="demo-checkbox">Click here for overflow demo</label>_x000D_
      <div id="demo">This is taller than #containment</div>_x000D_
    </div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


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.

_x000D_
_x000D_
html, body {_x000D_
  height: 100%;_x000D_
  margin: 0;_x000D_
  padding: 0; /* Don't forget Safari */_x000D_
}_x000D_
_x000D_
#containment {_x000D_
  display: grid;_x000D_
  min-height: 100%;_x000D_
  background: pink;_x000D_
}_x000D_
_x000D_
#containment-shadow-left {_x000D_
  background: aqua;_x000D_
}
_x000D_
_x000D_
_x000D_


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>

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.

_x000D_
_x000D_
body {_x000D_
  margin: 0;_x000D_
}_x000D_
_x000D_
.child {_x000D_
  min-height: 100vh;_x000D_
  background: pink;_x000D_
}
_x000D_
<div class="parent">_x000D_
  <div class="child"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Add height: 1px to parent container. Works in Chrome, FF, Safari.


Just to keep this subject complete, I found a solution not explored Here using Fixed position.

No Overflow

_x000D_
_x000D_
html, body, .wrapper, .parent, .child {_x000D_
  position: fixed;_x000D_
  top: 0; _x000D_
  bottom: 0;_x000D_
  left: 0;_x000D_
  right: 0;_x000D_
  margin: 0;_x000D_
  padding: 0;_x000D_
  height: 100%;_x000D_
}_x000D_
_x000D_
.child {_x000D_
  overflow: auto;_x000D_
  background: gray;_x000D_
}_x000D_
_x000D_
.height-50 {_x000D_
  height: 50%;_x000D_
  width: 5em;_x000D_
  margin: 10px auto;_x000D_
  background: cyan;_x000D_
}
_x000D_
<div class="wrapper">_x000D_
  <div class="parent">_x000D_
    <div class="child">_x000D_
      _x000D_
      <div class="height-50"></div>_x000D_
      _x000D_
    </div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

With Overflow

_x000D_
_x000D_
html, body, .wrapper, .parent, .child {_x000D_
  position: fixed;_x000D_
  top: 0; _x000D_
  bottom: 0;_x000D_
  left: 0;_x000D_
  right: 0;_x000D_
  margin: 0;_x000D_
  padding: 0;_x000D_
  height: 100%;_x000D_
}_x000D_
_x000D_
.child {_x000D_
  overflow: auto;_x000D_
  background: gray;_x000D_
}_x000D_
_x000D_
.height-150 {_x000D_
  height: 150%;_x000D_
  width: 5em;_x000D_
  margin: 10px auto;_x000D_
  background: cyan;_x000D_
}
_x000D_
<div class="wrapper">_x000D_
  <div class="parent">_x000D_
    <div class="child">_x000D_
      _x000D_
      <div class="height-150"></div>_x000D_
      _x000D_
    </div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


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.


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>

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.

_x000D_
_x000D_
.parent {_x000D_
  position: relative;_x000D_
  min-height: 100%;_x000D_
}_x000D_
_x000D_
.child {_x000D_
  min-height: 100vh;_x000D_
}
_x000D_
<div class="parent">_x000D_
    <div class="child"></div>_x000D_
  </div>
_x000D_
_x000D_
_x000D_


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>

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.

_x000D_
_x000D_
.parent {_x000D_
  min-height: 300px;_x000D_
  background-color: rgba(255,255,0,0.5); //yellow_x000D_
}_x000D_
_x000D_
.child {_x000D_
  min-height: inherit;_x000D_
  background-color: rgba(0,255,0,0.5); //blue_x000D_
}_x000D_
_x000D_
p {_x000D_
  padding: 20px;_x000D_
  color: red;_x000D_
  font-family: sans-serif;_x000D_
  font-weight: bold;_x000D_
  text-align: center;_x000D_
}
_x000D_
<div class="parent">_x000D_
  <div class="child">_x000D_
    <p>Yellow + Blue = Green :)</p>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

This way the child now acts as height 100% of the min-height.

I hope some people find this useful :)


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;
}