Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Height: Fill available space. No fixed heights

Tags:

html

css

So i have the following structure

<div id="container">
  <div id="head"></div>
  <div id="body"></div>
  <div id="foot"></div>
</div>

I am only using the ids for illustration purposes so this is not even necessarily for a full page.

I want my container to specify a fixed size... or a relative size, does not matter. Lets for argument sake say 300px height. Also overflow: hidden

I want head/foot to expand to fit the content within itself, so height: auto is sufficient.

I want the body to expand to fit the remaining space in between head and foot. If the content is too big, then scroll (overflow: auto).

height: 100% on #body does not work because then it gains the height of 300px like the parent and pushes part of itself and the footer out of the parent.

Having head and foot position: absolute does not work because by taking them out of the document flow, some content of #body is hidden. To fix that we can use padding-top/bottom but we can't set a padding-top: xxpx/padding-bottom: xxpx on the #body because we don't know the necessary height of the head/foot hence why they are height: auto.

Edit:

I tried converting the container/head/body/foot into a table where the #body is height: 100%. This works great except that #body won't scroll if the content gets too big, instead the entire table expands to show all content. This is not the desired behavior as I need #body to scroll, not #content or it's parent.

Any suggestions?

like image 403
Dmitriy Likhten Avatar asked Jun 30 '10 21:06

Dmitriy Likhten


People also ask

How do I fill a remaining space in CSS?

The width property is used to fill a div remaining horizontal space using CSS. By setting the width to 100% it takes the whole width available of its parent.

How do you make a div fill the height of the remaining space?

For anything inside the content div, setting top: 0; will put it right underneath the header. Sometimes the content will be a real table, with its height set to 100%. Putting header inside content will not allow this to work.

How do you get the flex element to take all available space?

Use the flex-grow property to make a flex item consume free space on the main axis. This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.


2 Answers

The only solution that immediately comes to mind is display:table-cell, though you run into the problem of lack of support in ie6 & ie7. Perhaps providing the rule for good browsers, and some javascript to calculate differences in height for ie?

Edit:

Here's another approach - using jQuery to calculate the offset. Bear in mind this is just a quick & dirty attempt - it would need to be browser tested and you'd want some simple error handling etc., but it could be a starting point.

Not sure if javascript is the way you want to go but I can't see it being done in pure css.

I changed the ids to classes so that you can have multiple 'fixedHeight' boxes:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'></script>

<script>

$(function() {   
   $(".fixedHeight").each(function() {
    var head = $(this).find(".head");
    var body = $(this).find(".body");
    var foot = $(this).find(".foot");   
    body.css("margin-top", head.height()).css("margin-bottom", foot.height());      
   });   
 });


</script>

<style>

.head {
    background-color: red;
    position: absolute;
    top: 0;
    width:100%;
}
.body {
    background-color: blue;
    color: white;
    overflow: auto;
    position:absolute;
    top:0;
    bottom:0;
    width:100%;
    margin:2.5em 0;
}
.foot {
    background-color: green;    
    position: absolute;
    bottom: 0;
    width:100%;
}
.container {
    background-color: #aaa; 
    border: 10px solid orange; 
    height: 300px; 
    width: 30%;
    position: absolute;
}


</style>

</head>

<body>

<div class="container fixedHeight">
  <div class="head">
    <h1>Header Content</h1>
  </div>
  <div class="body">
    <p>Body Content</p>
    <p>Body Content</p>
    <p>Body Content</p>
    <p>Body Content</p>
    <p>Body Content</p>
    <p>Body Content</p>
  </div>
  <div class="foot">
    <p>Footer Content</p>
  </div>
</div>


</body>
</html>
like image 124
DHuntrods Avatar answered Sep 21 '22 00:09

DHuntrods


Ok so heres a bit of research I got through to sort-of get this working.

#head {
    background-color: red;
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
#body {
    background-color: blue;
    color: white;
    border: 0 none;
    overflow: auto;
    height: 100%;
    padding-top: 2.5em;
    padding-bottom: 2.5em;
    box-sizing: border-box; 
    webkit-box-sizing: border-box; 
    -moz-box-sizing: border-box; 
}
#foot {
    background-color: green;
    width: 100%;
    position: absolute;
    bottom: 0;
    left: 0;
}
#container {
    background-color: #aaa; 
    border: 10px solid orange; 
    height: 300px; 
    width: 30%;
    overflow: show;
    position: absolute;
}

This assumes I can calculate the sizes of #head and #foot and set the total size to the padding of the appropriate location of #body. This will push the content of body out of the area which #head/#foot occupy due to their absolute positioning. The problem here is that the scroll bar winds up being cut off partially on the top/bottom because only the content is shifted, the scroll bar is not.

For width, this is not really an issue.

like image 45
Dmitriy Likhten Avatar answered Sep 19 '22 00:09

Dmitriy Likhten