Nick H
Nick H

Reputation: 2035

Three vertically stacked Divs, dynamic height

I want to have three vertically stacked divs.

The first div is at the top, it has a fixed height of 60px.

The middle div may or may not contain content, it will often contain content vertically larger than it, so it is set to overflow: auto. Regardless of if it contains content or not, it must consume the rest of the window's height minus the first div's height and the last div's height.

The last div has a minimum height of 40px. This div accepts user input, and can have a height between and up to 400px. This div expands upwards as the user inputs text, once it has reached the max height, it scrolls.

Here is a diagram:

+-----------+
|  Header   |
+-----------+
|          ^|
|          ||
|  Scroll  ||
|          ||
|          v|
+-----------+
|          ^|
|  Footer  ||
|          v|
+-----------+

I am having trouble getting the second (middle div) to shrink as the third div expands. I would like to accomplish this without js if possible.

Upvotes: 0

Views: 1541

Answers (3)

nepeo
nepeo

Reputation: 509

I've actually implemented something like this before for a chat client. I don't have it to hand but this was the gist of it! I added a few styling niceties and the text entry mechanics so you can get an idea of how it would work.

I'm afraid it doesn't make the middle section shrink persay, but it does appear to get smaller. As the footer expands with its text it extends over the top of the middle block.

var inputBox = document.getElementsByClassName("footer")[0];
var contentBox = document.getElementsByClassName("content")[0];

inputBox.addEventListener('keydown', function(e) {
    if (e.keyCode == 13) {
        e.preventDefault();
        createMessage(inputBox.textContent);
        inputBox.textContent = "";
    }
}, false);

function createMessage (str) {
     var message = document.createElement('div');
     message.style.cssText = "background: #3AF; padding: 10px; border-radius: 5px; margin: 10px 0; color: white;";
     message.textContent = str;
     contentBox.appendChild(message);
}

createMessage("Sent messages appear here!")
createMessage("Type a message in the footer and press enter to send")
createMessage("This list will become scrollable if there is enough content")
createMessage("The text entry will also dynamically resize as you type")
/* border box reset, as per http://www.paulirish.com/2012/box-sizing-border-box-ftw/ */

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
/*
  base container class, height can be relative or absolute (but it must have height
  requires position relative or absolute so we can position the header and footer
  finally requires vertical padding the same height as the the header/footer
*/

.container {
  height: 600px;
  background-color: rgb(220, 220, 220);
  position: relative;
  padding: 50px 0;
}
/*
  header class, must have a height and width
  should be top 0 and left 0 so that it positions inside the containers padding
  must be positioned absolute
*/

.container .header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 50px;
  background-color: rgb(120, 120, 120);
  text-align: center;
  line-height: 30px;
  padding: 10px;
  color: white;
  font-size: 22px;
}
/*
  content box, the easiest really
  height to 100% (so it will be the container minus the padding, which the header/footer sits in)
  overflow-y: auto; so if we exceed the size of the content box we scroll instead
*/

.container .content {
  height: 100%;
  overflow-y: auto;
  padding: 10px;
}
/*
  positioned absolutely again, but bottom left this time.
  use min height to specify the basic height then as the user types it will grow accordingly
  set max-height to prevent it growing too tall, overflow: auto; again so we can scroll in that situation
  VERY IMPORTANTLY MUST HAVE THE CONTENT EDITABLE FLAG ON THE HTML ELEMENT
*/

.container .footer {
  position: absolute;
  bottom: 0;
  left: 0;
  min-height: 50px;
  max-height: 300px;
  width: 100%;
  overflow-y: auto;
  background-color: rgb(120, 120, 120);
  padding: 15px;
  line-height: 20px;
  color: white;
}
<div class="container">
  <div class="header">HEADER</div>
  <div class="content"></div>
  <div class="footer" contenteditable></div>
</div>

The JS section isn't required, I've added it to the example to give it a bit more life.

It attaches a listener for the "enter" key on the text entry and uses the text to create a new "message" inside the content box. The actual layout is all done in CSS.

Upvotes: 0

Michael S
Michael S

Reputation: 141

*See new fiddle below

additional footer CSS:

.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  max-height: 400px; 
  background: #efefef;
}

Is that what you are going for?

EDIT:

NEW FIDDLE

Upvotes: 0

CSS Tricks: A guide to Flexbox in combination with max-height.

Upvotes: 2

Related Questions