55

I have two sibling elements which each contain dynamic content.

<div class="flex">
    <div class="sibling-1"></div>
    <div class="sibling-2"></div>
</div>

In some cases sibling-1 will have more content then sibling-2 and vice versa. I would like the height of the second element sibling-2 always equal the height of the first sibling-1. If the height of sibling-2 is greater then the height of sibling-1 it will overflow the flex div and thus be scrollable.

Is there any way to accomplish this with Flexbox?

Paulie_D
  • 107,962
  • 13
  • 142
  • 161
uneducatedguy
  • 1,331
  • 1
  • 10
  • 27

6 Answers6

69

Yes, it is possible. Leave the sibling setting the max height alone and set the others' flex-basis: 0 and flex-grow: 1, which according to the spec will expand them to their sibling's height. No absolute positioning. No setting height on any elements.

main {
  display: flex;
}

section {
  display: flex;
  flex-direction: column;
  width: 7em;
  border: thin solid black;
  margin: 1em;
}

:not(.limiter)>div {
  flex-basis: 0px;
  flex-grow: 1;
  overflow-y: auto;
}
<main>
  <section>
    <div>I'm longer and will scroll my overflow. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text
      in flow text in flow text in flow text in flow text in flow text in flow text in</div>
  </section>

  <section class="limiter">
    <div>Every parent's siblings match my height. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text</div>
  </section>

  <section>
    <div>I'm shorter but still match the height. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text</div>
  </section>
</main>
Lucent
  • 1,614
  • 1
  • 19
  • 22
  • 6
    This works if `flex-direction` is column, but I think the original question concerned the default of `flex-direction` being row. – Sean Mackesey Jun 13 '18 at 23:35
  • 2
    Actually, @SeanMackesey, I think this works becuase of extra markup. If you are ok with wrapping another section around your div, this is a good solution. the
    is also a row
    – Palash Karia Oct 11 '18 at 20:33
  • Made an example with less markup change (just adds a non-flex parent) https://jsfiddle.net/h7s590az/229/ – Palash Karia Oct 11 '18 at 20:44
  • @Lucent Great answer! I have a slightly different scenario where I have a nav panel on left and a scrolling "body" on right the height of the left nav. Is there a better way than my current solution: https://jsfiddle.net/76thszpx/1/ – sandraqu Jun 05 '19 at 13:40
  • This works! I also notice I can set flex-grow to any number > 0, can explain more? – Yiping Aug 07 '20 at 12:06
  • 1
    I made a similar which has been closed as a duplicate while it isn't exactly one: https://stackoverflow.com/questions/66527005/how-to-have-a-vertical-scroll-bar-in-a-flex-layout-without-fixed-height In my case, I don't have a element which has to limit the others, I have one element which should be limited by the tallest of the others. Can you help me? – Fla Mar 10 '21 at 17:07
  • @PalashKaria Your example uses fixed dimensions on the parent. With fixed dimensions, you can adjust child items just with `height: 100%;` and don't need the magic of this answer at all. – stackprotector Aug 09 '22 at 17:14
21

Is there any way to accomplish this with Flexbox?

Basically, no. The flex equal heights feature is based on the height of the container, not any particular sibling.

So sibling-1 and sibling-2 can always be equal height.

But flexbox has no built-in mechanism to limit the height of items to the height of one sibling.

Consider JavaScript or CSS positioning properties.

Here's an example using absolute positioning:

.flex {
  display: flex;
  width: 200px;
  position: relative;
}

.flex>div {
  flex: 0 0 50%;
  border: 1px solid black;
  box-sizing: border-box;
}

.sibling-2 {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  right: 0;
  overflow: auto;
}
<div class="flex">
  <div class="sibling-1">text<br>text<br>text<br>text<br>text<br>text<br></div>
  <div class="sibling-2">text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
</div>

jsFiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 2
    It is possible with Flexbox, the 3rd sample here shows that: https://stackoverflow.com/questions/47628082/flexbox-layout-with-two-equal-height-children-one-containing-nested-flexbox-wit/47628145#47628145 – Asons Dec 05 '17 at 07:04
  • @LGSon, that's an answer to a different problem. Here we're dealing with two flex siblings. There you're dealing with nested containers in the second column. If you can make it work without the nested containers, then I would agree that a solution is possible with flex. – Michael Benjamin Dec 05 '17 at 16:30
  • 1
    I will reluctantly agree to that :) ... Thanks for reply – Asons Dec 05 '17 at 18:19
  • @Michael_B what do you think of this? Made an example with less markup change (just adds a non-flex parent) https://jsfiddle.net/h7s590az/229/ – Palash Karia Oct 11 '18 at 20:45
3

Yes you can accomplish this by making siblings 1 and 2 also flex containers, then on sibling-2 make an absolute div (also flex container) inside that will be the parent of your scroller

<div class="sibling-1 flex sibling"></div>
<div class="sibling-2 flex sibling">
    <div class="absolute flex scroller-wrap">
        <div class="relative vertical-scroller">
            your content here
        </div> 
    </div>
</div>

css:

.relative{
  position:relative;
}

.absolute{
  position:absolute;
}

.flex{
  display:flex;
}

.sibling-2{
  flex:1; 
}

.scroller-wrap{
  height:100%;
}

on sibling 2 just set a minimum height on pixels - useful on responsive cases if siblings 1 and 2 stack each other on mobile

Twirlman
  • 1,109
  • 2
  • 12
  • 30
2

As I mentioned in the comments and has been continued in other answers, there is no flexbox method.

It is possible using position:absolute on the second sibling though...but since that's not actually a flexbox solution, this is here for information only.

.flex {
  margin: 1rem auto;
  position: relative;
  display: flex;
}
.sibling-1 {
  flex: 0 0 50%;
}
.sibling-2 {
  position: absolute;
  right: 0;
  width: 50%;
  height: 100%;
  overflow: auto;
}

* {
  margin: 0;
  outline: 0;
}
.flex {
  width: 80%;
  margin: 1rem auto;
  border: 1px solid grey;
  position: relative;
  display: flex;
}
.sibling-1 {
  flex: 0 0 50%;
}
.sibling-2 {
  position: absolute;
  right: 0;
  width: 50%;
  height: 100%;
  overflow: auto;
}
<div class="flex">
  <div class="sibling-1">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore quia, voluptatum! Perspiciatis praesentium nemo, labore mollitia numquam recusandae voluptatem consectetur amet deleniti cum nesciunt blanditiis, esse quis doloremque vero! Reiciendis
      porro impedit perspiciatis. Amet in praesentium molestias ipsum ad quis quia doloribus, veniam unde, ea ducimus rerum porro tenetur voluptatem, a laudantium. Accusantium provident voluptatibus perferendis hic blanditiis laborum amet consequatur
      esse, fugiat doloremque consectetur ullam sequi, ratione perspiciatis, voluptatem eaque vitae rem repellendus in architecto vel nulla animi neque. Accusantium animi voluptatum, suscipit possimus,</p>
  </div>
  <div class="sibling-2">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque modi quibusdam aliquam officia illo itaque ratione, iste architecto ad blanditiis fugiat sequi laborum cupiditate voluptatum, autem non? Quibusdam ad eius hic rem id. Libero, tempora
      dicta reiciendis placeat nihil quia fuga iste aliquid quo minus labore sapiente fugit, similique non aliquam, beatae pariatur nobis fugiat! Ipsam nobis fugit maxime aliquam accusamus explicabo nostrum ab nemo adipisci dolorem qui porro ea pariatur
      corporis aut reiciendis optio, sint eum nam suscipit itaque aspernatur recusandae. Cumque qui quod doloremque. Ut voluptates, asperiores, laborum excepturi quam odit, quos rerum assumenda sapiente saepe nisi? Numquam placeat repellat eum dolorem
      reprehenderit dolores culpa id explicabo consequuntur. Quas nobis veritatis tempora animi similique earum commodi, laborum blanditiis dolor illo, eaque accusamus aliquid nam a ex, velit, maiores natus. Id totam ullam corporis. Repellat aperiam,
      distinctio maxime, dolorum illum labore recusandae. Sequi repellendus provident deserunt amet culpa, ratione dignissimos! Quibusdam delectus mollitia, ducimus. Error id architecto, ea molestias voluptate impedit inventore amet ducimus modi repellat
      in. Asperiores soluta veritatis id eius, distinctio nisi voluptates voluptatibus iste iusto error officia tempore! Ducimus sed commodi quisquam provident iure voluptatum aliquam, nobis rem dolore, consectetur, dolor rerum eum nam adipisci, libero
      beatae eaque aliquid sapiente? Eius, earum quas nostrum quasi reiciendis officia quaerat omnis. Cupiditate suscipit et tempora quibusdam perspiciatis eius cum, nisi facere animi. Delectus magnam inventore ipsum, veritatis reiciendis. Ipsum adipisci
      recusandae, similique quas labore voluptas animi eaque velit, alias eveniet qui libero obcaecati suscipit, quam nihil quos placeat.</p>
  </div>
</div>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
2

From your code and to avoid extra wrapping , sticky on a side, height:0 on the other then overflow:auto on the parent can also do the job with flex:

example (you will easily understand it)

.flex {
  display: flex;
  
  /* demo purpose */
  width: 500px;
  border: solid;
  overflow: auto;/* make the parent scroll */
  gap:0.5em;
}



.flex .sibling-1 {
  position: sticky;/* stick the reference for the height */
  top: 0;
}

.flex .sibling-2 {
  height: 0;/* give it no height to start from and let the parent show the scrollbar */
}
<div class="flex">
  <div class="sibling-1">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
      lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
      facilisis luctus, metus</p>
  </div>
  <div class="sibling-2">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
      lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
      facilisis luctus, metus</p>
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
      lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
      facilisis luctus, metus</p>
  </div>
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
-1

My simplified (to me at least) code snippet based on Lucent's answer:

main {
  display: flex;
  font-family: "nunito"
}

section1 {
  display: flex;
  flex-direction: column;
  width: 15rem;
  border: thin solid gray;
}

section2 {
  display: flex;
  flex-direction: column;
  width: 15rem;
  border: thin solid gray;
}

section1 > div {
  flex-basis: 0px;
  flex-grow: 1;
  overflow-y: auto;
}
<main>
  <section1 class="scroll">
    <div>I'm a div in section 1 ---
      I have extra css rules of flex-basis 0px (making me as small as possible), flex 1 (making me fill up available space), and overflow y auto (making me scroll the extra content) --- My parent section 1 is a flex column --- My grandparent main is a flex row ---</div>
  </section1>

  <section2>
    <div>I'm a div in section 2. --- My parent section 2 is a flex column --- My grandparent main is a flex row --- The height of the div in section 1 will adjust to my height.</div>
  </section2>

</main>
lami
  • 1,410
  • 12
  • 16