As I learned flexbox, I was captivated by the way items grow to fit their container. But, recently I've realized its just as important to think about the way items shrink. Let me show you what I mean.
A typical usecase for flexbox is a set of items that we want to be spaced out evenly in a row. Something like this:
We create a flex context in a container with
display: flex. Flex items are spaced out evenly along the main axis with
justify-content: space-between. Everything looks great... until we start adding more items.
Ugh, the images are all squished up! This happens because by default, the value for
flex-shrink on items in a flex context is
1. That means that whenever the size of a set of flex items adds up to be larger than our flex context element, the items shrink down to fit.
(NOTE: Since this post, Chrome has changed the way it handles images in flex context. They now maintain their minimum instrinsic size. For this reason, the images are not shrunk to fit anymore. However, the ideas behind this post is still valid.)
The fix is simple: set
flex-shrink: 0 on the items that need to remain a fixed size. Setting
overflow: auto on the container clears up the issue of the images now overflowing their container.
A slightly more complex example is this typical native mobile application style:
A fixed size header and a footer are clamped to the top and bottom of the viewport and a flexible content area fills up the remaining space. The main area should scroll when the content overflows and the header and footer should remain a fixed size.
To achieve this pattern we set
.app to be the full size of the viewport, give it a flex context and set the
flex-direction to apply vertically. Our header and footer are a fixed height, and the main content area is set to grow or shrink to fit the remaining space. Unlike
flex-shrink, the default value for
flex-grow is 0, meaning flex items won't grow to fill space unless you tell them to.
But, we have a problem once we start putting in content. The elements we want to remain a fixed size start to shrink when the content in
This happens for two reasons. First, as we already know, all flex items have a
flex-shrink value of
1 by default. They will shrink if the content overflows the container setting the flex context. Secondly, the full size of the
.main container is used in the flex calculation, not just the visible portion. This is because by default, the
flex-basis value of a flex item is
flex-basis is the size basis that is used when calculating how items flex and a value of
auto means the full size is used. To fix this, we just stop the header and footer from shrinking with
You're going to run into problems like this often when working with flexbox. When I'm approaching a layout, I like to first think about what items need to remain a fixed size, and what items will flex. I also think about whether I need to handle overflow. With those two ideas in mind, flexbox layout becomes a matter of turning off shrinking on items that need to be a fixed size. Items that are flexible are set to grow and shrink, and overflow is handled if necesarry.