Home > Software engineering >  How can I constrain the a flexbox to the width of its first child?
How can I constrain the a flexbox to the width of its first child?

Time:09-14

I have a simple layout with two rows. The top row should determine the width (based on its content, not a css value), and the two elements in the bottom row should expand to match that width:

---------------------------------
| row one is exactly this wide  |
---------------------------------
| [...thing1...] [...thing2...] |
---------------------------------
<div.parent style='display: flex; flex-direction: column'>
  <div.row1>row 1 is exactly this wide</div>
  <div.row2 style='flex: 1; display: flex'>
    <span style='flex: 1'>thing1</span>
    <span style='flex: 1'>thing2</span>
  </div>
</div>

The problem is that thing1 and thing2 expand up to their grandparent's width, not row1's:

----------------------------------------------------------------------
| row one is exactly this wide                                       |
----------------------------------------------------------------------
| [..........thing1.............] [............thing2..............] |
----------------------------------------------------------------------

How can I constrain the parent div's width to be that of row1? Or, how do I achieve a layout like this?

CodePudding user response:

To my surprise that was easy enough, set both .parent.width and .row1.width equal to max-content and leave the rest as-is.

This way .parent is not allowed to exceed its content, which in turn is restricted by the width of .row1:

body * { outline: 1px dashed } /* for demo */
<div style='display: flex; flex-direction: column; width: max-content'>
  <div style="width: max-content">row 1 is exactly this wide</div>
  <div style='flex: 1; display: flex'>
    <span style='flex: 1'>thing1</span>
    <span style='flex: 1'>thing2</span>
  </div>
</div>

CodePudding user response:

I'm assuming that row 1 width must be preserved under all circumstances. The problem with this is that if thing1 or thing2 text gets too large it causes the parent div to increase in size. This can be solved by setting the things div to max-width: min-content and min-width: 50% so both divs occupy the same width but then we set word-break: break-all; so that any block of text will break. See example below

div {
  border: 1px dashed black;
}

.container {
  display: flex;
  flex-direction:column;
  width: max-content;
}

.things {
  display: flex;
  flex-direction: row;
}

.things > div {
  word-break: break-all;
  max-width: min-content;
  min-width: 50%;
}
<div class='container'>
  <div style="header">row 1 is exactly this wide</div>
  <div class='things'>
    <div>thing1IsAVeryLongStringSoItWillCauseTheParentDivToWidenUp</div>
    <div>thing2</div>
  </div>
</div>

CodePudding user response:

No padding or additional styling, just a basic idea using JS.

const papa = document.getElementById('papa');
const row1 = document.getElementById('row-1');

const maxWidth = row1.offsetWidth;
papa.style.maxWidth = `${maxWidth   1}px`;
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#papa {
  box-sizing: content-box;
  display: flex;
  flex-direction: column;
  border: 1px solid #423232;
}

#row-1 {
  align-self: flex-start; /* Prevent from stretching */
}

#content-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
<div id="papa">
  <div id="row-1">Shorter content here. Lorem ipsum epsem</div>
  <div id="content-grid">
    <span >Some Long content that should split based on row 1.</span>
    <span >Some Long content that should split based on row 1.</span>
  </div>
</div>

CodePudding user response:

Create a new parent div and set it as display:inline-block

<div style="display: inline-block">
  <div style="display: flex; flex-direction: column">
    <div>row 1 is exactly this wide</div>
    <div style="display: flex">
      <div style="flex: 1">thing1</div>
      <div style="flex: 1">thing2</div>
    </div>
  </div>
</div>
  • Related