9 min read

CSS Mastery: Understand Flexbox in 5 Steps

Flex Container

To get started, you need a wrapper element with some children. This wrapper can be a div, section, header, footer or even a ul. Here is an example of a common structure:

<div class="grid">
    <div class="column"></div>
    <div class="column"></div>
    <div class="column"></div>
    <div class="column"></div>
    <div class="column"></div>
</div>

Then set the display property of the parent class to flex:

.grid{ 
	display: flex;
	display: -webkit-flex; /* Support for older browsers */
}

The flex declaration is the only one you need to turn all the direct child elements into flex items and makes your wrapper element a flex contatiner.

There are five primary ways to manipulate how the items are layed out inside the flex container. Two involve properties you can declare on the flex container, and the other three on the flex item selector. I’ve broken them down into five steps coinciding with the process of creating layout to make it easy to remember.

1 – Flow

By default, your flex items will flow from left to right in a row starting at the top-left corner of your flex container. You can control this with the flex-flow property.

flex-flow takes two values, the flex-direction and the flex-wrap.

flex-flow: flex-direction || flex-wrap;
  • Use flex direction to send items horizontally in a row or vertically in a column
  • Use flex wrap to make items wrap or fit themselves in one row or column (works like words in a paragraph)

flex-direction

row, column, row-reverse or column-reverse

row lays out the flex items horizontally from left to right.

row-reverse lays them out horizontally from right to left.

column lays out the flex items vertically from top to bottom

column-reverse lays them out from bottom to top

flex-wrap

nowrap (default), wrap or wrap-reverse

wrap will bump flex items into a new row or column automatically if the parent elements or screen size constrict the flex container width beyond the calculated total of your flex items, just like words wrap in a paragraph. This frees you from having to use clumsy :nth-child clears when building grids, as flexbox will handle the content responsively for you.

In simple terms, if you have five flex items on a row and each one is 125px wide, but your screen size is only 480px wide, the following flex-flow will display the flex items in two rows:

flex-flow: row wrap;

wrap-reverse will just reverse the flow so the next row’s items use an opposite flex-direction. In most cases, you would only use it to solve a specific problem.

nowrap forces all flex items to stay on one line or in one column and is the same as not declaring a flex-wrap value. In most cases, you will want to use wrap.

  • clear has no effect on a flex item.
  • float causes the display property of the element to compute to block.


Here is how the whole rule would look:

.grid{
    display: flex;
    flex-flow: row wrap;
}

Note: row and row-reverse are dependent of the writing mode so in rtl context, their starting points will be reversed.

2 – Alignment of Rows and Columns

Flexbox gives us two ways of controlling alignment inside the flex container, justify-content and align-items.

  • justify-content controls the horizontal position for rows, or the vertical position for columns.
  • align-items controls the vertical position for rows, or the horizontal position for columns.

Sound confusing? The values are quite semantic, but it is much easier if you think in terms of rows, then turn the flex container once to understand the column logic.

justify-content

justify-content: flex-start | flex-end | center | space-between | space-around;
  • flex-start lays out flex items from the left (row) or top (column) of the flex container, and is the default (assuming the read-mode is ltr)
  • flex-end lays out flex items from the right (row) or bottom (column) of the flex container.
  • center will center flex items horizontally (rows) or vertically (columns)
  • space-between will distribute the flex items with equal spacing between them, placing the first flex item at the left/top edge of the flex container and the last flex item to the right/bottom, similar to justifying text.
  • space-around distrubutes the flex items equally with space around them, including the first and last item.

align-items

align-items: flex-start | flex-end | center | baseline | stretch;
  • flex-start lays out flex items from the top (row) or left (column) of the flex container with the top or left edges of the flext items aligned.
  • flex-end lays out flex items from the bottom (row) or right (column) of the flex container with the bottom or right edges of the flex items aligned
  • center will center flex items horizontally (columns) or vertically (rows)
  • baseline is best used when your flex items are varying heights (rows) or widths (columns) and will center the flex items on the baseline
  • stretch is incredibly useful and will make all flex-items equal size and is set by default.

align-content

If you need a way to distribute entire rows or columns equally within a flex container, you can do so with align-content.

align-content: flex-start | flex-end | center | space-between | space-around | stretch

These values work just like justify-content, but are applied to the rows or columns rather than individual flex items.

Notes

  • The alignment is done after the lengths and auto margins are applied, so it is important to note the following:
  • space-around and space-between only work when there is extra space in the flex-container, ie it is taller or wider than your rows/columns.
  • justify-content and align-items will not have any effect on flex items that are sized using the flex property, which we’ll explore next.
  • vertical-align has no effect on the alignment of flex items.

3 – Flex Item Sizing

Moving on to how flexbox properties are applied to the flex item selector, the first thing to consider is the sizing. By default, the width and height of flex items is determined by its content. There are a number of ways to size flex items. You can either set a height and width using a typical unit like percentages or pixels, or can harness the power of the flex property to let flexbox handle sizing for you.

Sizing With Units

You will want to define a height and width of your flex items in cases where you need them to stay consistent. The most common sizing unit to use with flex is percentages, to keep things somewhat responsive.

.column {    
	margin: 10px;    
	width: 33.33%;     	  
}

This example makes each flex item take up about 1.3 of the flex container.

Flex

Flex is a shorthand property that takes three numerical values:

flex: flex-grow || flex-shrink || flex-basis;
  • flex-grow will grow the flex item to take up additional space, if needed. 
  • flex-shrink will shrink the flex-item if needed.

The values for flex-grow and flex-shrink are proportional, meaning they change relative to other items in the flex container. Flexbox adds the values for the properties and then divides each flex-item’s value by that sum. If we have three flex items and want them to take up ⅓ of the total space, we would set the flex-grow and flex-shrink to 1.

 1 ÷ (1 + 1 + 1) = ⅓

.column {    
	margin: 10px;    
	flex: 1 1 0;     	  
}

If we have 6 flex items, then using the above will make them each take up one-sixth or the equivalent of 16.66% of the flex-container’s width.

The flex property becomes really magical when we start mixing values or applying different flexes on individual flex items. See how Landon Shropp uses it in this demo to create a grid with only a few lines of CSS:

flex basis defines how much space each flex item starts with, allowing the remaining space to be used up by the other two values. Setting this to 0 is effectivley an auto setting. This value is special as it accepts a percentage or pixel value. Pixel values are helpful to adjust your flex sizing to account for things like margins and borders. For example, if you have a flex item with a 20px margin and 2px border, you can set the flex-basis value to 22px:

.column {    
	margin: 10px;    
	flex: 1 1 22px;     	  
}

Making Columns Equal Height

You might be tempted to do something like set a height value on your flex items, but this is not neccessary! align-items: stretch; is the default for flexbox and will take care of this for you as long as it has not been set to something else. Here is a simple example:

See the Pen Flexbox Columns by Vail Joy (@vailjoy) on CodePen.27486

Notes

  • Flex items sized with flex will probbaly ignore wrapping since this property make them take up available space on the row.
  • Flex items do not need clears or right-margin tricks.

4 – Alignment of Flex Items

Where justify-content and align-items help us align flex items relative to the flex container, align-self allows us to align a single flex item relative to its sibling flex items.

align-self: auto | flex-start | flex-end | center | baseline | stretch
  • flex-start aligns it to the top (row) or left (column)
  • flex-end aligns it to the bottom (row) or right (column)
  • center centers it, as shown in the below image. If the cross-size of the item is larger than the flex container, it will overflow equally in both directions.
  • All flex items are aligned such that their baselines align. baseline is helpful when one flex item’s size is different, and keeps the baseline consistent.
  • stretch will stretch the flex item to fill the height of the flex-container (if it can)

5 – Order

In cases where the markup has to be in a certain order, or you don’t have control over re-ordering items in the source, you can manipulate them using order.  This is an especially useful trick if you need to do something like rearrange the order of elements in a page of a WordPress theme.

order: number;

It is important to assign an order to all the flex item’s siblings or this property has no idea what to order the flex-item relative to. In this example, we have a flex container with five flex items:

You can use order a variety of ways, depending on the CSS selectors you use to target the flex items. The following is just one example that is the most illustrative, using our original example of each flex item having a class of column:

.column:nth-of-type(1){
	order: 5;
}
.column:nth-of-type(2){
	order: 1;
}
.column:nth-of-type(3){
	order: 2;
}
.column:nth-of-type(4){
	order: 3;
}
.column:nth-of-type(5){
	order: 4;
}

Flexbox Playground

You can experiment with the effects of various properties using this handy flexbox tool. Enjoy!

See the Pen Flexbox Playground by Vail Joy (@vailjoy) on CodePen.27486

Resources

Hopefully you’ve found flexbox easier to understand and use with this overview. Below are some of the best resources around the web for learning more about the details and use-cases of this amazing CSS tool.