James Scott James Scott - 24 days ago 8
CSS Question

CSS variable top fixed bottom has foxed me

Thanks for taking a look, I'm making a webapp that has a menu feature where there is an overlay with a title, description, options for adding a new component (think a form with a number of input fields) and a save or cancel button at the bottom. The Title has no linebreaks and always has a constant height, same for the button bar, these go at the top and bottomn (blue and pink in the example), the description can have a varying number of lines and as such the height is variable (green area). The input options can also have a varying number of lines but can only be placed in the remaining container area. So what I have is this:

enter image description here

And what I would like to have is this:

enter image description here

Where the height of the green field is variable, and the yellow field fills the remaining space with a fixed title and buttons at the bottom. Here is the fiddle (code pasted after the question) with a JS function that generates 1 - 5 lines of description (green field) to simulate the varying height.

I'm looking for a pure CSS solution and have spent a few days researching this . I've tried various combinations of CSS position, float and display commands, flex boxes, table layouts etc but unfortunately can't put my finger on the solution. I'm aware as described here that a javascript approach is possible but if I go this way i'd consider it over complex, likely to confuse future coders working on the tool and I'd like to improve my knowledge.

Thanks in advance,

James



var EHeader = document.getElementById("desc");
var DescLine = "desc<br/>";
var DescLines = Math.floor(Math.random() * 5) + 1;

EHeader.innerHTML = DescLine.repeat(DescLines);

#container {
position: absolute;
background-color: red;
width: 300px;
height: 200px;
}
#title {
background-color: blue;
}
#desc {
background-color: green;
}
#options {
position: relative;
background-color: yellow;
}
#button {
position: absolute;
width: 100%;
bottom: 0px;
background-color: pink;
}

<div id="container">
<div id="title">title</div>
<div id="desc"></div>
<div id="input">
<div id="options">option 0
<br/>option 1
<br/>option 2
<br/>option 3
<br/>option 4
<br/>option 5
<br/>option 6
<br/>option 7
<br/>
</div>
</div>
<div id="button">button bar</div>
</div>




Answer

All you need to to is:

  1. Set display: flex with flex-direction: column on container element.
  2. Set overflow-y: auto and flex: 1 on flop element.

Also if you want options or (yellow div) to always take rest of free space even if there are small number of options you can do THIS

var EHeader = document.getElementById("desc");
var DescLine = "desc<br/>";
var DescLines = Math.floor(Math.random() * 5) + 1;

EHeader.innerHTML = DescLine.repeat(DescLines);
#container {
  position: absolute;
  background-color: red;
  display: flex;
  flex-direction: column;
  border: 1px solid black;
  width: 300px;
  height: 200px;
}
#flop {
  overflow-y: auto;
  flex: 1;
}
#title {
  background-color: blue;
}
#desc {
  background-color: green;
}
#options {
  background-color: yellow;
}
#button {
  background-color: pink;
}
<div id="container">
  <div id="title">title</div>
  <div id="desc"></div>
  <div id="flop">
    <div id="options">option 0
      <br/>option 1
      <br/>option 2
      <br/>option 3
      <br/>option 4
      <br/>option 5
      <br/>option 6
      <br/>option 7
      <br/>option 8
      <br/>
    </div>
  </div>
  <div id="button">button bar</div>
</div>

Comments