CSS3 FlexBox

Understanding the Flex Layout Model

The Flexible Box, or flexbox, is a new layout system introduced in CSS3 that allows for the creation of adaptable user interfaces with multiple rows and columns without needing to use percentage or fixed length values. The CSS3 flexbox layout provides an easy and effective way to automatically manage space distribution and content alignment via stylesheets, without changing the actual HTML structure.

The following example shows how to make a three-column layout where each column has the same width and height using the flexbox model.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSS3 Three Equal Flex Column</title>
<style>
.flex-container {
width: 80%;
min-height: 300px;
display: -webkit-flex; /* Safari */     
display: flex; /* Standard syntax */
border: 1px solid #808080;
}
.flex-container div {
background: #dbdfe5;
-webkit-flex: 1; /* Safari */
-ms-flex: 1; /* IE 10 */
flex: 1; /* Standard syntax */
}
</style>
</head>
<body>
<div class="flex-container">
<div class="item1">Item 1</div>
<div class="item2">Item 2</div>
<div class="item3">Item 3</div>
</div>
</body>
</html>

When you look closely at the example code above, you'll notice that we didn't set any width for the inner <div> elements within the .flex-container. However, the output shows each column having a width exactly one-third of the parent .flex-container element.


How Flex Layout Works

Flexbox is made up of flex containers and flex items. You can create a flex container by setting the display property of an element to either flex (which creates a block-level flex container) or inline-flex (which creates an inline flex container similar to inline-block). All child elements within a flex container become flex items and are arranged using the flex layout model. The properties float, clear, and vertical-align do not affect flex items.

Flex items are arranged inside a flex container along a flex line, which is controlled by the flex-direction property. By default, there is only one flex line per flex container, which follows the same direction as the inline axis of the current writing mode or text direction. The illustration below will help you understand the terminology used in the flex layout.

Flexbox Illustration

Controlling Flow inside Flex Container

In the regular CSS box model, elements are usually displayed in the order they appear in the HTML markup. The flex layout allows you to control the flow direction inside a flex container so that elements can be laid out in any direction: left, right, down, or up.

You can set the flow of flex items in a flex container using the flex-direction property. The default value for this property is row, which is the same as the document's current writing mode or text direction, such as left-to-right in English.

.flex-container {
width: 80%;
min-height: 300px;
/* Safari */
display: -webkit-flex;
-webkit-flex-direction: row-reverse;
/* Standard syntax */
display: flex;
flex-direction: row-reverse;
border: 1px solid #666;
}

Similarly, you can display the flex items inside a flex container in columns instead of rows by setting the flex-direction property to column, like this:

.flex-container {
width: 80%;
min-height: 300px;
/* Safari */
display: -webkit-flex;
-webkit-flex-direction: column;
/* Standard syntax */
display: flex;
flex-direction: column;
}

Controlling the Dimensions of Flex Items

The key feature of the flex layout is that flex items can change their width or height to fit the available space. This is done using the flex property. It is a shorthand for the flex-grow, flex-shrink, and flex-basis properties.

A flex container allocates free space to its items based on their flex grow factor or shrinks them to avoid overflow according to their flex shrink factor.

.flex-container {
width: 80%;
min-height: 300px;
display: -webkit-flex; /* Safari */     
display: flex; /* Standard syntax */
}
.flex-container div {
padding: 10px;
background: #dbdfe5;
}
.item1, .item3 {
-webkit-flex: 1; /* Safari */
flex: 1; /* Standard syntax */
}
.item2 {
-webkit-flex: 2; /* Safari */
flex: 2; /* Standard syntax */
}

In the above example, the first and third flex items will each take up 1/4 or 1/(1+1+2) of the free space, while the second flex item will occupy 1/2 or 2/(1+1+2) of the free space. You can use this straightforward technique to create other flexible layouts as well.

Note: It's strongly advised to use the shorthand instead of individual flex properties because it ensures unspecified components are reset correctly.


Aligning Flex Items within Flex Container

There are four properties: justify-content, align-content, align-items, and align-self that control the alignment of flex items within a flex container. The first three apply to flex containers, while the last one applies to individual flex items.

Align Flex Items along Main Axis

Flex items can be aligned along the main axis (i.e., horizontally) of the flex container using the justify-content property. This is usually used when the flex items don't take up all the available space along the main axis.

The justify-content property can have the following values:

  • flex-start — Default value. Flex items are positioned at the start of the main axis.
  • flex-end — Flex items are positioned at the end of the main axis.
  • center — Flex items are centered along the main axis with equal free space on both sides. If the free space is negative (i.e., items overflow), they will overflow equally in both directions.
  • space-between — Flex items are spaced evenly along the main axis, with the first item at the start and the last item at the end. If items overflow or there's only one item, this behaves like flex-start.
  • space-around — Flex items are spaced evenly with half-sized spaces at the ends. If items overflow or there's only one item, this behaves like center.

The following example shows the effect of different justify-content values on a multi-column flex container with a fixed width.

.flex-container {
width: 500px;
min-height: 300px;
border: 1px solid #666;
/* Safari */
display: -webkit-flex;
-webkit-justify-content: space-around;
/* Standard syntax */
display: flex;
justify-content: space-around;
}
.item1 {
width: 75px;
background: #e84d51;
}
.item2 {
width: 125px;
background: #7ed636;
}
.item3 {
width: 175px;
background: #2f97ff;
}

Align Flex Items along Cross Axis

Flex items can be aligned along the cross axis (i.e., in the perpendicular direction) of the flex container using the align-items or align-self property. The align-items property applies to the flex container, while the align-self property applies to individual flex items, overriding align-items. Both properties accept the following values:

  • flex-start — Flex items are positioned at the start of the cross axis.
  • flex-end — Flex items are positioned at the end of the cross axis.
  • center — Flex items are centered along the cross axis with equal space on both ends. If the free space is negative (i.e., items overflow), they will overflow equally in both directions.
  • baseline — The text baseline (or inline axis) of each flex item aligns with the baseline of the flex item with the largest font-size.
  • stretch — Flex items stretch to fill the current row or column unless restricted by minimum and maximum width or height. This is the default value for the align-items property.

The following example demonstrates the effect of different align-items values on a multi-column flex container with a fixed height.

.flex-container {
width: 500px;
min-height: 300px;
border: 1px solid #666;
/* Safari */
display: -webkit-flex;
-webkit-align-items: center;
/* Standard syntax */
display: flex;
align-items: center;
}
.item1 {
width: 75px;
height: 100px;
background: #e84d51;
}
.item2 {
width: 125px;
height: 200px;
background: #7ed636;
}
.item3 {
width: 175px;
height: 150px;
background: #2f97ff;
}

You can also distribute free space along the cross axis of a multiple-row or multiple-column flex container. The align-content property aligns the lines of a flex container, such as rows in a multi-row flex container, when there is extra space in the cross axis. This works similarly to how justify-content aligns items along the main axis.

The align-content property accepts the same values as justify-content, but applies them to the cross axis instead of the main axis. It also includes one additional value:

  • stretch — The free space is evenly distributed among all rows or columns, increasing their cross size. If the free space is negative, this behaves like flex-start.

The following example shows the effect of different align-content values on a multi-row flex container with a fixed height.

.flex-container {
width: 500px;
min-height: 300px;
margin: 0 auto;
font-size: 32px;
border: 1px solid #666;
/* Safari */
display: -webkit-flex;
-webkit-flex-flow: row wrap;
-webkit-align-content: space-around;
/* Standard syntax */
display: flex;
flex-flow: row wrap;
align-content: space-around;
}
.flex-container div {
width: 150px;
height: 100px;
background: #dbdfe5;
}

Reordering Individual Flex Items

In addition to changing the arrangement within a flex container, you can also adjust the sequence in which individual flex items are shown using the order property. This property accepts a positive or negative integer as its value. By default, all flex items are displayed and arranged in the same order as they appear in the HTML markup, with the default value of order being 0.

The following example illustrates how to manage the sequence of an individual flex item.

.flex-container {
width: 500px;
min-height: 300px;
border: 1px solid #666;
display: -webkit-flex; /* Safari 6.1+ */
display: flex;
}
.flex-container div {
padding: 10px;
width: 130px;
}
.item1 {
background: #e84d51;
-webkit-order: 2; /* Safari 6.1+ */
order: 2;
}
.item2 {
background: #7ed636;
-webkit-order: 1; /* Safari 6.1+ */
order: 1;
}
.item3 {
background: #2f97ff;
-webkit-order: -1; /* Safari 6.1+ */
order: -1;
}

Note: Flex items with the lowest order value are positioned first, and those with the highest order value are positioned last. Items with the same order value are displayed in the order they appear in the source document.


Horizontal and Vertical Center Alignment with Flexbox

Traditionally, aligning a content block vertically involves using JavaScript or complex CSS workarounds. But with flexbox, you can easily achieve this without any additional adjustments.

The following example illustrates how to centrally align a content block both vertically and horizontally using the CSS3 flexbox feature.

.flex-container {
width: 500px;
min-height: 300px;
border: 1px solid #666;
display: -webkit-flex; /* Safari 6.1+ */
display: flex; /* Standard syntax */
}
.item {
width: 300px;
padding: 25px;
margin: auto;
background: #f0e68c;
}

Enable Wrapping of Flex Items

By default, flex containers display only a single row or column of flex items. However, you can use the flex-wrap property on the flex container to determine whether its flex items will wrap into multiple lines if there isn't enough space for them on one flex line.

The flex-wrap property accepts the following options:

  • nowrap — Default setting. Flex items are placed in a single line, which may cause overflow if there isn't enough space.
  • wrap — The flex container breaks its flex items across multiple lines, similar to how text wraps onto a new line when it's too wide to fit on the current line.
  • wrap-reverse — Flex items will wrap if necessary, but in reverse order, with the cross-start and cross-end directions swapped.

The following example demonstrates how to arrange flex items in a single or multiple lines within a flex container using the flex-wrap property.

.flex-container {
width: 500px;
min-height: 300px;
border: 1px solid #666;
/* Safari */
display: -webkit-flex;
-webkit-flex-wrap: wrap;
/* Standard syntax */
display: flex;
flex-wrap: wrap;  
}
.flex-container div{
width: 130px;
padding: 10px;    
background: #dbdfe5;
}

Note: You can also employ the shorthand CSS property flex-flow to define both the flex-direction and flex-wrap in a single declaration. It supports the same values as the individual properties, and you can place these values in any order.