Flexbox sizing makes it possible to create flexible layouts that
fully adapt to the screen. If you set up everything correctly you
won’t have to rely on media queries to support different
viewports, layouts, and orientations.
In this guide I’ll show you how to use the following flexbox
sizing properties:
- flex-grow
- flex-shrink
- flex-basis
- flex
Filling up Free Space
One of the most challenging aspects of writing CSS is figuring
out how to allocate the free space that remains on the
screen after the page has been populated with content. At some
viewports sizes, you’ll often find there’s too much remaining
space and you want to fill it with something. At other viewport
sizes, you might find there’s not enough space, and the layout
breaks in one way or another.
Flexbox’s sizing properties allow you to make decisions about
three kinds of scenarios:
- flex-grow: how flex items should behave when there’s a
surplus of free space (how they should grow). - flex-shrink: how flex items should behave when there’s a
shortage of free space (how they should shrink). - flex-basis: how flex items should behave when there’s
exactly as much space as needed.
As flexbox is a one-dimensional layout, as opposed to CSS Grid
which is two-dimensional, you can allocate free space along the
main axis (whether that be top to bottom, bottom to top, left to
right, or right to left). You can set the direction of the main
axis using the flex-direction property. If you need a refresher on
how this works take a look at my tutorial about
flexbox alignment.
A
reminder of how the main axis and the cross axis interact.
The most common flex-direction used on left-to-right websites
is row, which means you can allocate free space on the
left-to-right axis. This also happens to be the default value
of flex-direction, so I’ll use it in the following
examples.
1. Positive Free Space: flex-grow
The flex-grow
property defines how any extra space in-between flex items should
be allocated on the screen. The most important thing to remember
about flexbox sizing is that flex-grow doesn’t divide up the
entire flex container, only the space that remains after the
browser renders all flex items. If there’s no surplus of
space, flex-grow has no effect.
Let’s start with the following HTML:
<div > <div >1</div> <div >2</div> <div >3</div> </div>
The .container class will be the flex container (defined by
display: flex;) and our .item elements will be the flex
items:
.container { background-color: darkslategrey; padding: 1rem; display: flex; flex-direction: row; } .item { font-size: 2rem; line-height: 1; text-align: center; width: 3rem; padding: 2rem 1rem; background: #e2f0ef; border: 3px solid #51aaa3; color: #51aaa3; margin: 0.375rem; }
Without telling the browser what to do with the remaining space,
this is how flex items are allocated on the screen:
The browser has used the default value of flex-grow, which is 0,
and gives us total inflexibility. This arrangement might be a good
solution for some layouts, however, you can also make the items
cover the whole space by setting flex-grow to 1:
.item { flex-grow: 1; }
As you can see below, the flex items have stretched out and
filled the whole available space:
In the above example, all flex items have the same flex-grow
value, so they grow at the same rate. However, you can also make
them grow according to different ratios. For instance, .item-1 can
take up twice as much of the available space as the other
items. We would write that as follows:
.item { flex-grow: 1; } .item-1 { flex-grow: 2; }
Similarly, you can set a different flex-grow value for each flex
item to make them grow relative to each other. Play around with the
values in this example and see how they affect the layout:
2. Negative Free Space: flex-shrink
The flex-shrink
property is the opposite of flex-grow. It defines how flex items
should behave when there’s not enough space on the screen. This
happens when flex items are larger than the flex container.
Without flex-shrink, the following CSS would result in a layout
where the items overflow the container, as the total width of the
items (3*10rem) is bigger than the container’s width
(20rem).
.container { width: 20rem; padding: 1rem; background-color: darkslategrey; display: flex; flex-direction: row; } .item { width: 10rem; padding: 2rem 1rem; font-size: 2rem; line-height: 1; text-align: center; background: #e2f0ef; border: 3px solid #51aaa3; color: #51aaa3; margin: 0.375rem; }
Hypothetical
world without flex-shrink..
Happily for us, flex-shrink is implied, taking on the default
value of 1, giving us a layout where the items fit into the
container even though there’s not enough space:
When flex-shrink is 1, flex items are fully flexible and when
there’s not enough space, they shrink together with the flex
container.
Following the same logic, you can make flex items fully
inflexible when there’s negative space on the screen. You only
have to set flex-shrink to 0 and the items will overflow the flex
container:
.item { flex-shrink: 0; }
Similarly to flex-grow, you can also set a different flex-shrink
value for each flex item so that they can shrink relatively to each
other. Play around with the values in this example and see what
impact they have:
Testing the above demo you might have noticed that larger
flex-shrink values lead to narrower flex items. For instance, the
following CSS results in a layout where .item-3 is the narrowest
item:
.item-1 { flex-shrink: 1; } .item-2 { flex-shrink: 1; } .item-3 { flex-shrink: 2; }
This is because flex-shrink defines how much a flex item should
shrink compared to other items. Thus, larger flex-shrink values
lead to smaller elements, which can make things pretty
confusing!
3. No Remaining Space: flex-basis
The last scenario of free space allocation is when there’s
exactly as much space on the screen as you need. This is when flex
items will take the value of flex-basis.
The flex-basis
property defines the initial size of flex items. The default value
of flex-basis is auto, which means that the size of the flex items
is calculated using either the width or height of the element
(depending on if it’s a row-based or column-based layout).
However, when the value of flex-basis is something other than
auto, it overrides the value of width (or height in case of
vertical layouts). For example, the following CSS overrides the
default width: 20rem; rule with a respective value for each flex
item:
.item { width: 20rem; padding: 2rem 1rem; font-size: 2rem; line-height: 1; text-align: center; background: #e2f0ef; border: 3px solid #51aaa3; color: #51aaa3; margin: 0.375rem; } .item-1 { flex-basis: 5rem; } .item-2 { flex-basis: 10rem; } .item-3 { flex-basis: 30rem; }
Besides length units, percentages, and auto, you can also use
the content keyword as a value for flex-basis. It will make a flex
item as wide as the content
it holds.
As flex-basis defines the initial value of flex items, it’s the
basis the browser uses to calculate flex-grow and flex-shrink.
Note that while flex-grow and flex-shrink have relative values (0,
1, 2, etc.), flex-basis always takes an absolute value (px, rem,
content, etc.).
The flex Shorthand
Flexbox’s sizing properties also have a shorthand called
flex.
The flex property abbreviates flex-grow, flex-shrink, and
flex-basis in the following way:
/* Longhand form of default values */ .item { flex-grow: 0; flex-shrink: 1; flex-basis: auto; } /* Shorthand form of default values */ .item { flex: 0 1 auto; }
You don’t necessarily have to list all the three values if you
don’t want. You can use flex with one or two values, according to
the following rules and assumptions:
/* One relative value: flex-grow */ flex: 1; /* One absolute value: flex-basis */ flex: 20rem; flex: 50px; /* One relative and one absolute value: flex-grow | flex-basis */ flex: 1 20rem; /* Two relative values: flex-grow | flex-shrink */ flex: 1 2; /* Three values: flex-grow | flex-shrink | flex-basis */ flex: 1 2 20rem; /* Fully inflexible layout: equivalent of flex: 0 0 auto */ flex: none;
It might take a while to get used to the flex shorthand, but
the W3C docs actually recommend using
it, instead of the longhand properties:
“Authors are encouraged to control flexibility using
the flex shorthand rather than with its longhand properties
directly, as the shorthand correctly resets any unspecified
components to accommodate common uses.”
Conclusion
There we have it: you can completely control flexibility with
flexbox’s sizing properties! In this tutorial, I used a
horizontal layout set by flex-direction: row, so space allocation
happened along the horizontal (left to right) axis and
flex-grow, flex-shrink, and flex-basis modified the width of the
flex items.
If you take what we covered and apply it to a vertical layout
set by flex-direction: column, allocation will happen along the
vertical (top-to-bottom) axis and the sizing properties will modify
the height of the flex items.
This tutorial is the third part of my Comprehensive Guide to
Flexbox series. To fully understand how flexbox works, be sure to
check out the two previous parts:
Recent Comments