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
Explainer: Flexbox Sizing
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 viewport 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.
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 class="container"> <div class="item item-1">1</div> <div class="item item-2">2</div> <div class="item item-3">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; }
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 part of my Comprehensive Guide to Flexbox series. To fully understand how flexbox works, be sure to check out the other parts:
No comments:
Post a Comment