0

I have a parent container main-wrapper. It's a row flex box that has two div flex items.

The second div item has flex-grow: 1 so the item takes up the remaining space. The text inside each div item takes up less than a line. When I increase the text length of the second div item to take up multiple lines, it causes the first div item to shrink in width and break the text.

Here's a snippet showing this. When you click the button it'll increase the text length.

function changeText(){
    const col2Text = document.getElementById("column-2");
    col2Text.textContent = "I'm a very long text that will cause the first column text to break and text to shift downwards making the box smaller";
}
#main-wrapper{
  background: black;
  margin: 0px auto;
  width: 400px;
  height: 800px;
  display: flex;
}

#column-1{
  background: red;
  text-align: left;
}

#column-2{
  background: yellow;
  text-align: left;
  flex-grow: 1;
}
<button onclick="changeText()">Change text</button>
<div id="main-wrapper">
  <div id="column-1">I'm column 1.</div>
  <div id="column-2">I"m column 2.</div>
</div>

Can someone explain why this occurs? I would have assumed the first div item would have taken all the space it needed. Then the second div item would have stayed the same width due to flex-grow: 1 and break when the text reached the end.

What are some common ways of handling this? One fix I had was just setting a fixed width on the first div item.

roverred
  • 1,841
  • 5
  • 29
  • 46

1 Answers1

1

This is happening the same way as you expected. Since the second element #column-2 has flex-grow: 1 it tries to taks maximum width as it can.

Why the #column-1 splits into multiple line?

Since the #column-2 tries to grow to maximum width due to flex-grow: 1;, the #column-1 will start shrinking and break into multiple lines.

Setting fixed width might solve the problem temporarly. But the best solution is to set the width of the first column dynamically depending on its content. Since we are making use of flex layout, the width of the first column will be the maximum depending on its content. You just need to avoid the line breaks.

To avoid that you have to use white-space: nowrap; for #column-1. white-space specifies whether and how white-space is collapsed.

You could find the reference for white-space here

Working example:

function changeText() {
  const col2Text = document.getElementById("column-2");
  col2Text.textContent = "I'm a very long text that will cause the first column text to break and text to shift downwards making the box smaller";
}
#main-wrapper {
  background: black;
  margin: 0px auto;
  width: 400px;
  height: 800px;
  display: flex;
}

#column-1 {
  background: red;
  text-align: left;
  /* Added */
  white-space: nowrap;
}

#column-2 {
  background: yellow;
  text-align: left;
  flex-grow: 1;
}
<button onclick="changeText()">Change text</button>
<div id="main-wrapper">
  <div id="column-1">I'm column 1.</div>
  <div id="column-2">I"m column 2.</div>
</div>
Nitheesh
  • 19,238
  • 3
  • 22
  • 49
  • 1
    Thanks that makes sense. I thought flex-grow would take remaining space and not the maximum space. So I guess in this case the minimum space for div item 1 is the longest word. – roverred Jul 19 '21 at 08:46
  • 1
    @roverred this answer is not 100% accurate, there is no *maximum space* concept. It's about flex-basis and shrink effect. You can remove flex-grow:1 from your question and you will get the same result so flex-grow play no role here – Temani Afif Jul 19 '21 at 09:09