Flexbox
Demo starter files
Flexbox is a powerful tool for modern layout. The feature in its current form has had good cross browser support since 2013, a few years before CSS grid (2017). Because it had features that were difficult to achieve by older methods, it has been used for whole page layouts. However, it's usually best to use flexbox for smaller components now that we have CSS grid.
What is Flexbox?
flex
is a CSS display mode that turns an element into a flex container. All of its direct child elements become flex items. Rather than following normal block formatting rules, the items can be stretched and aligned in relation to one another in many different ways within the parent flex container.
Flexbox is one dimensional. This means that alignment and distribution of items can only be controlled on one axis (in one direction), even if the items wrap onto multiple lines.
While it's possible to make flex items arrange into a grid using percentage widths and margins, this forfeits the ability to use some of flexbox's features (flex-grow
and flex-shrink
). If you need to be able to draw lines in both directions through the content, CSS grid is generally a better option.
When to Use Flexbox
Some of the most common places where flexbox is good to use include:
- Navigation and split navigation
- Form controls
- Arranging media like pictures with associated text
- Super simple vertical centering
- Card items with equal height
How to Make a Flexbox
The demo illustrates almost all of the many things you can do with flexbox, but the minimum basic setup is pretty simple. Here are the steps:
- Set up HTML
- Turn on flexbox
- Set the flow
- Set the sizing of the flex items
- Justify and align, if needed
Set up HTML
HTML to set up a flexbox is very straightforward. You need a parent container which will become the flex container, and child elements that will become flex items. This could be a list with list items, a combination of semantic tags and/or divs, etc.
<ul class="flex-container">
<li>flex item</li>
<li>flex item</li>
<li>flex item</li>
<li>flex item</li>
</ul>
Turn on Flexbox
Set display: flex
on the parent container. This causes the element to become a flexbox, and all of the child elements to automatically become flex items with several default properties. The flex items will immediately be laid out in a row, with partially flexible sizing!
.flex-container {
display: flex;
}
Set the Flow
Next you should set the flex-flow
. The default settings below are often what you want, but it's important to understand what they do and how they can be changed.
.flex-container {
display: flex;
flex-flow: row nowrap;
}
By default the flex items are laid out horizontally, in a row
. This direction can be switched to a vertical column
. It can also be reversed (e.g. row-reverse
), if you want the items to flow right to left while keeping their logical HTML order.
The nowrap
setting means that the items must all fit in one row or column, and that they cannot wrap. You may need to change this if you have several flex items, or the flex items are fairly large. If the flex items can't wrap and the viewport is too small, they will overflow out of the flexbox container.
Set the Sizing of the Flex Items
Often times you'll also need to set the flex
property, which controls the size and "squishiness" of the flex items. This property gets applied to the flex child items, not the container where you set display: flex
.
.flex-container {
display: flex;
flex-flow: row nowrap;
}
.flex-container > li {
flex: 0 1 auto;
}
The order is flex-grow
, flex-shrink
, flex-basis
. The default values here mean "0
don't grow, 1
do shrink if needed, and try to be auto
width".
The grow and shrink settings should always be an integer (no decimals), and they should not have units. These form a set of ratios, meaning that if you apply different flex
settings to the items, they will grow or shrink at different rates when the viewport changes size. This is fully illustrated in the demo.
The flex-basis
is the size a flex item "wants" to be, before any growing or shrinking happens. Since most of the time we use flexbox to set up a row, this usually refers to the item's width.
The figure below is not actually code, but it shows how the base size of flex items is determined.
Justify and Align, If Needed
If the flex-grow
and other settings don't fill all the available space in your flexbox, the final thing you may need to set is the justification and alignment of the flex items. By default, all of the items will sit at the start of the row, and they'll all stretch to the height of the tallest item. This can be changed with justify-content
and align-items
. The demo illustrates the different options for these properties.
Flexbox Properties
Here for reference are the most common properties for flexbox. Several combinations of these are illustrated in the demo!
Properties for the Parent Element (Container)
Property | Default value | Description |
---|---|---|
display: flex |
Turns the element into a flexbox, triggering flexbox layout rules for the element and its direct child elements. Applies to the parent container. | |
flex-direction |
row |
Direction of the main axis. |
flex-wrap |
nowrap |
Controls whether the flex items are allowed to wrap. |
flex-flow |
row nowrap |
Shorthand for flex-direction and flex-wrap . These properties work together, so you should usually use this shorthand to set them both at once. |
justify-content |
flex-start |
Sets the justification of the flex items along the main axis (usually horizontal). |
align-items |
stretch |
Controls the alignment of items along the cross axis (usually vertical). The default stretch will cause all flex items to match the size of the largest one. |
align-content |
normal (like stretch ) |
Controls the alignment of rows along the cross axis (usually vertical) when there are multiple rows. This property is only visible when wrapping is turned on. |
Properties for the Child Elements
Property | Default value | Description |
---|---|---|
flex-grow / flex-shrink |
0 / 1 |
Sets the rate at which flex items grow or shrink. These values form a ratio, so they should always be an integer (no decimals), and they do not accept units (just bare numbers). |
flex-basis |
auto |
The base size of the flex items, before any growing or shrinking happens. |
flex |
0 1 auto |
Shorthand for flex-grow , flex-shrink , and flex-basis . These properties work together, so you should usually use this shorthand to set them all at once. |
order |
0 |
Allows for one flex item to be moved to a different display order. The default 0 for all items means "follow the order of the HTML". |
Axis and Direction
The most difficult thing about flexbox is probably understanding the direction and axes of the content being laid out. The properties will feel a lot more intuitive to use and memorize once you have a handle on this.
By default, flexbox lays items in a row. In this case, the main axis is horizontal and the cross axis is vertical. Since our web pages are written in english, the direction of the main axis is left to right.
If we switch the flex direction to column, the axes switch. The main axis becomes vertical and the items are displayed from the top down. This is not as common because it's similar to regular block layout, but it can be useful for certain kinds of components.
Why don't we use physical directions like top, bottom, left, and right everywhere? Because CSS is moving toward the use of logical properties instead of physical properties. Logical properties like "start" and "end" take the writing mode into account. This allows our designs to adapt for internationalization with far less work. A page written in English that uses logical properties can be automatically reversed for right-to-left or even vertical languages, and the CSS will automatically lay our content out in the proper direction and axis.
Flexbox is easiest to understand by seeing it in action. Let's look at some of the common properties and use cases in the demo files!