3

I want all 100% height elements to expand when the size of the body expands.

In the example pressing the button will add a red div - the two columns adjacent should stretch to account for this. In the end all columns should reach the bottom completely, one with blue then red, the other two just blue.

I'm looking into flex, and it doesn't seem like this would work, but any suggestions are appreciated.

In any case best solution is CSS, but if this is impossible pure JS is also fine.

span = document.getElementsByTagName("span")[0];
function addelem() {
  span.appendChild(document.createElement('div'));
};
html, body{
  height: 100%;
}

span {
  display: inline-block;
  background-color: blue;
  width: 30px;
  height: 100%;
  vertical-align: top;
}

div {
  background-color: red;
  width: 30px;
  height: 30px;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>

This is what I expect the frame to look like at the bottom after button is pressed and scrolled down:

enter image description here

EDIT

I changed the snippet so the button appends the div to an existing child and causes overflow, as per the comments below suggest.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
kabanus
  • 24,623
  • 6
  • 41
  • 74
  • 1
    Don't understand what should happen when clicking on the `+`? – Asons May 14 '17 at 11:30
  • The blue spans next to the one where the div was added should increase their size to the bottom, all the way to where the red div ends. – kabanus May 14 '17 at 11:33
  • not too sure this is really what you need : https://codepen.io/anon/pen/pPKzON not much flexible and reliable. I think i understood the first part ... :) – G-Cyrillus May 14 '17 at 12:40
  • @Michael_B This is similar to my actual layout. A button calls Javascript that appends an element. I wouldn't mind appending it as a child element to one of the blue columns, thus causing a current element to expand. I'm not sure that's easier, but if so, go for it. – kabanus May 14 '17 at 19:55
  • Yes, it makes a difference. If the elements are added inside the container, then your layout is possible without much complication using pure CSS. I posted an answer. – Michael Benjamin May 15 '17 at 17:53

2 Answers2

2

An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.

In a container with flex-direction: row, the cross axis is vertical, so items will expand to full height.

In your demo code, the divs (red) are being added as children of a span column (blue). These divs are being added to the end, forcing the column to grow.

In a row-direction flex container, with no heights specified that would override align-items: stretch, the other columns will follow suit.

span = document.getElementsByTagName("span")[0];
function addelem() {
  span.appendChild(document.createElement('div'));
};
body {
  display: flex;
  min-height: 100vh;
}

body > span {
  width: 30px;
  margin-right: 5px;
  background-color: blue;
  display: flex;
  flex-direction: column;
}

body > span:first-child span {
  flex: 0 0 100vh;
}

div {
  background-color: red;
  width: 30px;
  height: 30px;
}

button {
  margin-bottom: auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    Thanks, and nice catch. – kabanus May 16 '17 at 07:37
  • Quick question - what's the advantage of using viewport height (vh) units instead of percent? Is this a must for this solution? – kabanus May 16 '17 at 07:42
  • Using a percentage height requires you to [**define a height on the parent**](http://stackoverflow.com/a/31728799/3597276), and some [**browsers handle this differently**](http://stackoverflow.com/q/33636796/3597276). With vh units, heights are much simpler. But no, it's not a requirement for the solution to work. – Michael Benjamin May 16 '17 at 11:24
0

You should use Flexbox twice, once in the outer container, and once in the container containing the appended child elements.

Here is your modified code:

span = document.getElementsByTagName("span")[0];
function addelem() {
  span.appendChild(document.createElement('div'));
};
html, body{
  height: 100%;

  /* new */
  display: flex;
}

/* new */
body > span{margin-right: 4px;}

span {
  /*display: inline-block;*/
  background-color: blue;
  width: 30px;
  height: 100%;
  vertical-align: top;

  /* new */
  display: flex;
  flex-flow: column;
  align-items: flex-end;
}

div {
  background-color: red;
  width: 30px;
  height: 30px;

  /* new */
  flex: 1 0 auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
Gabe Hiemstra
  • 269
  • 1
  • 14
  • 1
    This solution doesn't work. It just fills the blue column with red divs. Once the space runs out, it expands the column, but leaves the other two behind. (Watch the scrollbar, or check the heights in dev tools.) – Michael Benjamin May 15 '17 at 17:12
  • @Michael_B, I don't understand your downvote. Isn't this exactly what he wants, apart from the overflow side-effect? And if you think about it logically, is the solution not supposed to overflow? How else should you calculate the height of three containers, two of which are set to 100% and one is set to 100% plus any unknown value? – Gabe Hiemstra May 16 '17 at 07:19
  • @Michael_B I missed this bug. Gabe, click the button until the blue span is completely full red divs, then keep clicking. You'll see the red divs appended on top of the original size of the span, leaving the other two behind. Left the up-vote though, this may be what someone else is looking for. On the contrary, in Michal's solution I can keep clicking until my memory runs out or my finger is tired - columns remain equal. – kabanus May 16 '17 at 07:37