How do I control the order in which flexbox items grow/shrink?

Viewed 127

I have a flex container with three children. Each child has a min and max width and I would like to have them grow/shrink in a specific order. So, as the window width decreases, Item1 should shrink to its min width, and then Item2 should decrease to its min width, followed by Item3. Can someone help me figure out what I'm doing wrong? I've tried to discern from the documentation how to get the order set up, but I'm just not understanding.

<div className="MainContainer">
  <div className="Item1">
    I should shrink first/expand last!
  </div>
  <div className="Item2">
    I should shrink & expand second!
  </div>
  <div className="Item3">
    I should shrink last/expand first!
  </div>
</div>

And my CSS:

.MainContainer {
  display: flex;
  flex-direction: row;
  justify-content: center;
  padding-left: 15px;
  padding-right: 15px;
}
//Should shrink first/expand last
.Item1{
  min-width: 350px;
  max-width: 816px;
  flex: 1;
  flex-grow: 0;
}
//Should shrink/expand second
.Item2{
  max-width: 816px;
  flex: 1;
  flex-grow: 1;
}
//Should shrink last/expand first
.Item3{
  min-width: 300px;
  max-width: 224px;
  flex: 1;
  flex-grow: 2;
}
2 Answers

That's not the way flexbox works, you can't say "shrink last" - all you can say is "shrink/grow at a rate in proportion to other items shrink/growth rates"

I imagine you're also generally setting too many widths and confusing yourself about which properties are actually taking effect. Just let things happen naturally and see where they end up.

This is an example with commentary that will hopefully paint a clearer picture:

.Item1{
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 350px;
  // this means it will not shrink, have a min width of 350px, and grow at a rate of "1" (proportional to the other children in it's container) to fill up the remaining space
  // flex: 1 0 350px; <- the above is the same as this
}

//Should shrink/expand second
.Item2{
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: auto; // this means it will not shrink, have a min width of it's "intrinsic size" and grow AT THE SAME RATE (1) as Item1 to fill up the remaining space
  // flex: 1; <- this is the shorthand for the above
}

The best reference on the internet for flexbox is https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Using this SO question as a starting point, I was able to achieve my goal.

I have slightly simplified the sizes to make it easier to read, but I have gotten my project working in the same way.

Check out this codesandbox to see my fully working implementation using React and TypeScript (popping the preview out to a new window will help see what's going on). I have created a custom component that will show the current size of each element as the window is resized. This is not necessary for doing this yourself, of course.

The main thing to look at is the wrappers that hold my resizing elements and the styles in the scss, specifically how the 'first-to-shrink' and 'second-to-shrink' classes are combined with the max-width, min-width, and flex-basis set on individual components. One other 'gotcha' is that I had to set the flex-basis of the container that housed two elements as the sum of the children's max-widths.

I have 3 objects that need to shrink/expand in a specific order. In display order, they are:

Secondary Document - Primary Document - Answer Pane

Secondary Document has a min width of 250px, a max width of 500px, and should shrink first.

Primary Document has a min width of 250px, a max width of 500px, and should shrink last.

Answer Pane has a min width of 150px, a max width of 300px, and should shrink second.

After all 3 objects have shrunk to their minimum, there is overflow that happens, but that is ok with my implementation.

The 'trick' here is that I had to use wrapper/container objects in twos: SecondaryDocument-container houses the Secondary Document while PrimaryDocument-AnswerPane-container houses both the Primary Document and Answer Pane.

enter image description here

Related