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.

Flex items can be laid out in a row
Flex items distributed in a row.

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.

Flexbox only handles one dimension
Each line of flex items is distributed independently of the other lines.

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:

  1. Set up HTML
  2. Turn on flexbox
  3. Set the flow
  4. Set the sizing of the flex items
  5. 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.

flex-basis value 
    ⤷ if set to auto, use css width
        ⤷ if no width is set, use content size
Flex basis is the natural size the flex item "wants" to be. This may be effectively covered up by the grow and shrink factors. If set to auto, the default, the element drops down to refer to its width value. If that's also unset, it drops down again to the intrinsic size of the contents.

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.

The main and cross axis on a row flexbox
The main and cross axes for flex-direction: row

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.

The main and cross axis on a column flexbox
The main and cross axes for flex-direction: column

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!