2

I have a 3rd party, scrollable, with 100% height element (that i don't want to modify). I would like to fit it inside a parent div, so it will fill all the space remaining.

I was attempted to do so using Flex. (see code snippet). The problem I've encounter is that because of the content of the 3rd part element, the child div become taller than the parent. Is there a way to make flex shrink the child to fit the remaining size of the parent?

EDIT: If possible, I would like to avoid any hard-coded numbers and let flex dynamically fit the size so the tall_child will fit the remaining parent size.

.parent {
  background-color : blue;
  height : 50vh;
  display : flex;
  flex-direction: column;
}


.header {
  background-color : red;
  height : 50px;
  width : 80%
}

.tall_child {
  background-color : green;
  width : 80%;

  /* 
  I want the height of the this child to be determined automaticlly by flex to fit remaining space of parent 
  */
}

.scrollable_3rd_party_element {
  height : 100%;
  overflow : scroll;
  border-style: solid;
  border-width: 5px;
}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
amit
  • 2,171
  • 4
  • 31
  • 50

4 Answers4

3

add a max-height:50px to .scrollable_3rd_party_element

.parent {
  background-color : blue;
  height : 100px;
  display : flex;
  flex-direction: column;
}


.header {
  background-color : red;
  height : 50px;
  width : 80%
}

.tall_child {
  background-color : green;
  width : 80%;

  /* 
  I want the height of the this child to be determined automaticlly to fit parent
  height : 50px; 
  */
}

.scrollable_3rd_party_element {
  height : 100%;
  overflow : scroll;
  border-style: solid;
  border-width: 5px;
  max-height: 50px
}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>

for this specific example parent size, 50px works. but i want something that works no matter the parent size

Then you need to use flex:1 and min-height: 0 in tall_child

I've just noticed that it works on chrome but not on safari under OS-X.

bottom border is now truncated while in chrome it looks perfect

A quick fix for safari OSX is adding a overflow-x:hidden in .tall_child and changing border from .scrollable_3rd_party_element to .tall_child

* {
  box-sizing: border-box
}

.parent {
  background-color: blue;
  height: 100px;
  display: flex;
  flex-direction: column;
}

.header {
  background-color: red;
  height: 50px;
  width: 80%
}

.tall_child {
  background-color: green;
  width: 80%;
  flex: 1;
  min-height: 0;
  /* safari fix*/
  overflow-x: hidden;
  border: 5px solid
}

.scrollable_3rd_party_element {
  height: 100%;
  overflow-y: scroll;

}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>
dippas
  • 58,591
  • 15
  • 114
  • 126
  • then why this? `/* I want the height of the this child to be determined automaticlly to fit parent height : 50px ;*/` and this: `.header { height : 50px; }` – dippas Sep 12 '17 at 13:25
  • for this specific example parent size, 50px works. but i want something that works no matter the parent size.. – amit Sep 12 '17 at 13:27
  • 1
    I'm just busy at work , so when I could see OP's comment I knew what to do, so I improved/updated the answer to match OP requirements. Simple as that – dippas Sep 12 '17 at 13:59
  • Thanks @dippas. In your solution the the 3rd element still spill out of the parent. My aim is to make it fit inside the parent (inside the blue part). because the 3rd party is scrollable, i should be able to see all the content by scrolling inside the green area. – amit Sep 12 '17 at 14:13
  • same issue as @kukkuz answer. I've just noticed that it works on chrome but not on safari under OS-X. – amit Sep 12 '17 at 14:23
  • 2
    @amit A quick fix for safari OSX is adding a `overflow-x:hidden` in `.tall_child`, see updated answer – dippas Sep 12 '17 at 14:34
  • it is almost there!! :) but the bottom border is now truncated while in chrome it looks perfect – amit Sep 12 '17 at 14:37
  • @amit add `box-sizing: border-box`? – kukkuz Sep 12 '17 at 14:38
  • still truncated :( https://www.dropbox.com/s/27506ia6q8glj5u/Screenshot%202017-09-12%2017.40.06.png?dl=0 – amit Sep 12 '17 at 14:40
  • @amit change `border` to `.tall_child` instead. see updated answer – dippas Sep 12 '17 at 14:43
  • this will force me to modify the 3rd party element which i really don't want to do. however, maybe it is the best solution possible due to safari bug (?). if no better solution will come around i'll accept this as an answer.. – amit Sep 12 '17 at 14:54
1

Add flex: 1 (to allow the tall_child to take the available vertical space) and min-height: 0 (to override min-height: auto which is the default) to the .tall_child.

Also add box-sizing: border-box to the .scrollable_3rd_party_element to include the border in the height. And maybe its better to use overflow: auto instead of scroll.

See demo below:

.parent {
  background-color : blue;
  height : 50vh;
  display : flex;
  flex-direction: column;
}


.header {
  background-color : red;
  height : 50px;
  width : 80%
}

.tall_child {
  background-color : green;
  width : 80%;

  /* 
  I want the height of the this child to be determined automaticlly to fit parent
  height : 50px; 
  */
  flex: 1;
  min-height: 0;
}

.scrollable_3rd_party_element {
  height : 100%;
  overflow : auto;
  border-style: solid;
  border-width: 5px;
  box-sizing: border-box;
}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • Thanks @kukkuz. In your solution the the 3rd element still spill out of the parent. My aim is to make it fit inside the parent (inside the blue part). because the 3rd party is scrollable, i should be able to see all the content by scrolling inside the green area. – amit Sep 12 '17 at 14:14
  • @amit it works for me in chrome and firefox, which browser are you using? – kukkuz Sep 12 '17 at 14:16
  • yes. i'm using safari OS X. it indeed works for chrome.. any ideas how to make it work for saferi as well? – amit Sep 12 '17 at 14:21
  • @amit maybe prefixes is the issue... use `-webkit-flex:1` for instance along with `flex: 1`? and what is the safari version? – kukkuz Sep 12 '17 at 14:28
  • it is Version 10.1.2 (12603.3.8). -webkit-flex:1 does not produce the same result as in the chrome browser – amit Sep 12 '17 at 14:33
1

For this to work without any fixed height elements, you must at least keep some proportions between header and the rest of the elements, it is not a matter of using flexbox:

.parent {
  background-color : blue;
  height : 50vh;
  display : flex;
  flex-direction: column;
}


.header {
  background-color : red;
  height : 15%;
  width : 80%
}

.tall_child {
  background-color : green;
  width : 80%;
  height: 85%;
}

.scrollable_3rd_party_element {
  height : 100%;
  overflow-y : scroll;
  border-style: solid;
  border-width: 5px;
  box-sizing: border-box;
}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>

Codepen demo

Kostas Siabanis
  • 2,989
  • 2
  • 20
  • 22
  • I wonder.. flex is able to fill a shorter child into a larger parent without "knowing the proportions" by using flex-grow. can't it do so for a taller child? – amit Sep 12 '17 at 14:17
0

another option i've found inspired by How to make flexbox children 100% height of their parent?

Not perfect as it requires to modify the 3rd party element "position" and "width". but it seems to almost work at chrome and safari (few pixels misalignment). Maybe someone will find it as another useful alternative.

.parent {
  background-color : blue;
  height : 50vh;
  display : flex;
  flex-direction: column;
}


.header {
  background-color : red;
  height : 50px;
  width : 80%
}

.tall_child {
  background-color : green;
  width : 80%;
  flex-grow : 1;
  position: relative;
}

.scrollable_3rd_party_element {
  position: absolute;
  width : 100%;
  height : 100%;
  overflow : scroll;
  border-style: solid;
  border-width: 5px;
}
<div class="parent">
  <div class="header">header</div>
  <div class="tall_child">
    <div class="scrollable_3rd_party_element">
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
      <div>content</div>
    </div>
  </div>
</div>
amit
  • 2,171
  • 4
  • 31
  • 50