Flexbox: How to make content take up remaining space after fixed sidebar
It's a classic scenario. You have a sidebar, and you have content. They are getting in the way of each other, and
float: left isn't going to cut it.
Flexbox was made for this kind of thing!
To begin, find the common element that contains both your sidebar and your content. Give it the following styling so that the elements within can make use of Flexbox rules.
As a general rule, when it comes to Flexbox, parent elements do not own the styles of their children. Elements tend to own their own styles.
Step 1 - Fix your sidebar!
Make sure you are applying this style to an element directly below the one with
display: flex on it.
This is a use case for
flex-basis is a little hard to describe without introducing its siblings:
flex-basis is the width (or height for column scenarios) that an element will take before it makes the decision to grow or shrink. It is the basis for flex behaviour.
flex-shrink define how the element may change in size relative to the basis it has. In this case, we can guess what we want for these values. Zero! We want the sidebar to be a particular size and to not grow or shrink. What this means is that we can ignore these attributes entirely; they will default to 0 if not specified.
In the end, all we need to do is give our css this line:
(The 20% can be 200px, 20vw, whatever you want it to be).
You can also make use of the
flex attribute, defining it like so:
flex: 0 0 20%;
This is shorthand, defining respectively
flex: 20% will also set your
flex-basis to 20%. However, it will default your
flex-shrink to values of 1, resulting in automatic shrinking or growing depending on the circumstances.
By the way, if you say
flex-basis: auto it means that
flex-basis should refer to the element's width or height property, whichever is relevant.
Part 2 - Stretch your content!
Now, here is a use case for
flex, depending on your preference.
In this case, you don't care how big or small your content is. Given the fixed size of your sidebar, you simply know that you want your content to take up all remaining space in the container. This means you don't need to specify a
flex-basis at all. To explain this, I will need to explain how
The value you give to
flex-grow is used as a proportion. All elements under the
display: flex container have to share the space that it contains. Each element will take up its
flex-basis and then will use
flex-grow to divide up what is left and decide who is really the favourite child.
If you have multiple elements all with
flex-grow: 1, then they will evenly distribute what is left. If you have three elements, two with
flex-grow: 1 and one with
flex-grow: 2 then you will find the first two taking quarters and the last taking a half. Basically an element with a
flex-grow value will take up its own value as a proportion of the sum of all
flex-grow values within the same flex container.
In this case, the sidebar has a
flex-grow value of 0. This means it gets no cut of the space remaining after
flex-basis has had its way. The result is that if we give the content element a
flex-grow value of 1, we are telling it that it can take up 100% of the remaining space. This is because it has no competition.
However, specifying it this way is considered somewhat bad practice. It is preferable to use the
flex attribute if possible. Instead we can write:
Which is equivalent to:
flex: 1 1 0%;
As previously stated, this means
flex-shrink are both 1, and
flex-basis is 0% (as we wanted). But what's with this
flex-shrink: 1 business?
In the same way that
flex-grow allowed the content element to take up remaining space after
flex-basis has its way, what if there isn't enough room in the element to contain the sum of all
flex-basis values? Then something will have to shrink, and
flex-shrink will decide the proportion at which elements reduce their size. This isn't necessarily needed here, but for more advanced sidebars, you could easily envision a scenario where
flex-shrink could come in handy.
Sorry about these screenshots lol. Anyway, happy coding!
I read the article and still hard for me to understand the difference between flex-basis, flex-grow and flex-shrink. Could you better explain it?
I would put it this way.
flex-basis is describing the original widths of the elements. If the combined width of all the elements is smaller than the available space, flex-grow becomes relevant. Elements will grow by an amount based on the proportion between their flex-grow value and the sum of all the flex-grow values. If the combined width of all the elements is larger than the available space, the elements will shrink by an amount based on the proportion between their flex-shrink value and the sum of all flex-shrink values.
There's no way for flex-grow and flex-shrink to be used at the same time. You can only know how much an element will grow or shrink by knowing the relevant values of all the neighbour elements.
Hope this is helpful!