There’s certainly no shortage of CSS flexbox tutorials and similar content online promoting and teaching flexbox to beginners. The now-ubiquitous layout technique can be learned from a number of different resources. But I hope this CSS flexbox tutorial for beginners will be a little different.
In this CSS flexbox tutorial I’m aiming to teach you all of the features of the Flexbox Layout Module using fully interactive demonstrations that really drive home how flexbox features affect elements on an HTML page.

About the interactive demos
As mentioned, all the demos in this CSS flexbox tutorial will be fully interactive. Each one will illustrate a specific flexbox feature and you’ll be able to click one or more buttons in just about every demo to see the effects of those features.
In addition, most demos will include a “toggle direction” button that will toggle the direction
property on the container element between ltr
and rtl
. This will allow you to see how the particular feature works in both types of environments – using left-to-right languages like English and Spanish or right-to-left languages like Arabic or Hebrew.
In case you haven’t used this property before, here’s a demo with some example text that uses a right-to-left language:
There are a few ways to accomplish language definition in HTML or CSS, but in the above example I’m using direction: rtl
in the CSS for that paragraph element. In the flexbox demos, I won’t be using any language – just elements with dummy content – but the direction will be able to toggle via JavaScript.
Creating the flexbox container
The first feature it’s important to know when working with flexbox is how to define the flex container. Before you begin aligning, centering, and justifying elements inside a container, you first have to specify that the parent container is a flex container:
.flex-container {
display: flex;
}
Code language: CSS (css)
Once you have this in place, all the child elements inside .container
become flex items, because they now exist inside a flex formatting context. Below is an interactive CodePen demo that will allow you to see what happens when you toggle a container between display: flex
and display: block
.
In this example, the only flexbox-related CSS that’s applied is display: flex
. The space you see between the flex items is a small margin I’ve added for clarity. Later, I’ll discuss different ways to space flex items using flexbox features.
What do you see happening when you toggle the flex container on and off? First, it’s important to note that all the elements, including the container and its children, are <div>
elements. This means they’re all block-level elements by default. In this CSS flexbox tutorial, I’m mainly going to deal with the behavior of flexbox properties on block-level elements, because that’s the most common use case.
By default, block elements are placed below previous content, so the items are stacked vertically. When display: flex
is toggled on, however, the elements align horizontally while still maintaining their dimensions and the specified margins.
Understanding the flex container
As the initial demo shows, a flex container will by default display its flex children horizontally. This is what’s referred to as the main axis of a flex container. Later, I’ll show you how to display the elements vertically in a flex container. In that case, the items will be laid out on what’s referred to as the cross axis.
The following diagram shows these two axes:

As shown, the cross axis flows perpendicular to the main axis. And it’s important to note that although non-flex blocks are laid out visually in the same direction as the cross axis, technically that doesn’t qualify as a flexbox cross axis until the container is set to display: flex
.
Flexbox properties for the container
In this CSS flexbox tutorial, first, I’m going to discuss the different properties you can apply to the flex container. Later, I’ll show you how to target the flex items.
By dividing this CSS flexbox tutorial in this way, you’ll be able to easily reference the different features depending on if you want to do something more universal to all the items as a group via the flex container or if you want to target the flex items themselves.
Determining the direction of the flex container: flex-direction
As discussed, a flex container can have elements flowing either vertically (on the cross axis) or horizontally (along the main axis). To specify the direction you can use the flex-direction
property, which takes one of four values, the default being row
.
.flex-container {
display: flex;
flex-direction: row;
}
Code language: CSS (css)
Here’s a breakdown of each value for flex-direction
:
row
– Elements are aligned horizontally along the main axis in the document’s current writing mode.row-reverse
– This value is likewise on the main axis but in reverse of the current writing mode.column
– As the name implies, this flows the flex items along the cross axis (vertically), taking into consideration the current writing modecolumn-reverse
– Same ascolumn
but reversed
You can see all the values in the following interactive demo:
Note that the boxes are numbered so you can easily see the effect of the *-reverse
values.
Also note that in English and many other languages, the writing mode is set as left-to-right, whereas other languages it’s reversed. This is why you’ll often see more generic terminology used in newer CSS specifications, and why a specification like Logical Properties and Values was created. Logical properties make no assumption about the page’s language (unlike something like text-align: left
, which does make assumptions), thus terms like ‘left’ and ‘right’ are not used but instead are replaced by ‘start’ and ‘end’.
Wrapping items: flex-wrap
The flex-wrap
property allows you to determine how and if you want the flex items inside the container to wrap to the next line.
.flex-container {
display: flex;
flex-wrap: nowrap;
}
Code language: CSS (css)
The values break down as:
nowrap
– Don’t wrap the items to the next linewrap
– Wrap the items if they don’t fit on a single linewrap-reverse
– Wrap the items if necessary but reverse their order in relation to the default writing direction
By default, items will not wrap – even if you specify widths that force the items to expand past the available space. Below is an interactive demo that demonstrates the three different values. Note that the width is set at 15% for all the flex items.
As you can see, even with a set width, the items fit on a single line when the flex container is set to flex-wrap: nowrap
. Once the elements wrap, then they break onto multiple lines while respecting the specified widths.
Aligning elements along either axis: justify-content
The aptly-named justify-content
property accepts one of five possible values and the syntax looks like this:
.flex-container {
display: flex;
justify-content: flex-start;
}
Code language: CSS (css)
A value of flex-start
is the initial value. It’s easy to see the effect of each value using the demo below, but here’s a quick summary of each one:
flex-start
– Pack the flex items to the start of the lineflex-end
– Pack the flex items to the end of the linecenter
– Pack the flex items in the centerspace-between
– Flex items are evenly distributed with no space at the start or end outside of margins or paddingspace-around
– Flex items are evenly distributed with a “half size” of space at the start and end of each line
And here’s the interactive demo to help you visualize how each one works:
The values will behave in a fairly predictable way when you have two or more items, but notice the behavior with a single flex item:
As you can see, the space-between
value behaves the same as flex-start
on the lone element. A value of space-around
behaves the same as center
in this instance, but that’s fairly predictable.
The same property can also be used to align items in a cross-axis flex container, as shown in the following demo:
Aligning elements in the cross axis of the current line: align-items
The align-items
property is a little tricky to get your head around because its name doesn’t really suggest what it does. This property helps you align each individual flex item perpendicular to the main axis, while the items still remain aligned along the main axis.
That might be a bit confusing. To make it more clear, let’s say I have five flex items in a flex container along the main axis (i.e. flex-direction: row
). While these items remain in the row
direction, I can align them individually in the perpendicular direction. If that’s still confusing, some code and an interactive demo will help greatly here.
.flex-container {
display: flex;
flex-wrap: wrap;
align-items: stretch;
}
Code language: CSS (css)
In order to see the effect of align-items
, I’m setting the container’s flex-wrap
property to wrap
, and the demo will include enough items to allow you to see the effect more clearly. Here are the possible values:
stretch
– The default; flex items are individually stretched to fit along the cross axisflex-start
– Aligns each element to the ‘start’ edge of the line along the cross axisflex-end
– Aligns each element to the ‘end’ edge of the line along the cross axiscenter
– Centers each flex item on the line along the cross axisbaseline
– Centers each flex item with its text baseline
And here’s the demo:
Note that not only am I including ten flex items but some of them have different heights and line-heights to demonstrate how the different values behave.
As you can see, the items are aligned perpendicular in relation to the current flex line (which is the default row
, or horizontal). Notice that the value stretch
doesn’t stretch the flex items across the entire height of the container, but only across the item’s flex line, or ‘row’.
If I remove the extra line of flex items, note the behavior in the following demo:
Again the varying heights and line-heights help drive home the concept. This is one you’ll have to play around with to grasp its usefulness.
Handling extra space between flex lines: align-content
The align-content
property is another one that’s a little tough to grasp at first. But it’s relatively easy to understand when you think about it the same way as justify-content
except instead of dealing with the items and the space between them along the main axis, this property deals with the space between flex lines.
.flex-container {
display: flex;
flex-wrap: wrap;
align-content: stretch;
}
Code language: CSS (css)
The values are the same as justify-content
with the addition of stretch
, the default:
stretch
– Flex lines are stretched to take up the available space, making all flex lines the same heightflex-start
– Lines are packed to the start (usually the top) of the containerflex-end
– Lines are packed to the end (usually the bottom) of the containercenter
– Lines are packed to toward the center with equal space at top and bottomspace-between
– Lines are evenly distributed with equal space between lines and no space at the top or bottomspace-around
– Lines are evenly distributed with equal space but with half the leftover space at the top and bottom
The spec points out the following:
Only multi-line flex containers ever have free space in the cross-axis for lines to be aligned in, because in a single-line flex container the sole line automatically stretches to fill the space.
With that in mind, the interactive demo includes multiple flex lines:
Again I’ve included items with different sizes to demonstrate the behavior in an unusual context.
Flexbox properties for the flex items
So far, this interactive CSS flexbox tutorial has covered all the properties you can apply to the container. Once those are in place, there are a number of properties you can apply to one or more flex items (i.e. child elements of the flex container).
Let’s continue the CSS flexbox tutorial by considering the flex item properties.
Specifying the order of flex items: order
By default, flex items are laid out according to the order they appear in the HTML source. The order
property can be applied to any flex item to adjust that item’s place in the source order.
.flex-item {
order: 3;
}
Code language: CSS (css)
The order
property accepts an integer that represents the order that the flex item appears relative to the its sibling flex items, taking into account any other order
values that are present.
Here’s a simple demo that has three flex items. The options at the top allow you to change their order.
In that example, the three flex items change order similar to how you might adjust a three-column layout contrary to source order (which you might do for SEO purposes).
Understanding precedence when using order
To understand the order
property a little better, note the following interactive demo. It’s probably confusing at first, especially if you don’t understand how order is determined in certain circumstances.
To understand what you’re seeing, here’s a breakdown:
- Each of the numbered flex items has an
order
value set equal to its visible number - The one flex item that’s a different color changes its order when you select one of the number options
With that in mind, notice the somewhat strange behavior:
- Although you’re giving the #5 flex item an order value of
1
, it appears as the second item (the same happens when choosing2
,3
, or4
). - Choosing
5
brings it back to its starting place but choosing6
leaves it at the5
position - Choosing
7
puts it in the 6th position and choosing8
puts it in the 7th position
Those behaviors are explained as follows:
- The items all start with an existing
order
value. If two flex items share the same order, the one first in HTML source order will take precedence in flex order - Thus, items #1 through #4 all have precedence in order when they share the same order as the #5 item after it’s changed
- Likewise, since #5 appears before the #6 through #12 items in the original source, #5 takes precedence when any of those share the same
order
value
Again, the main concept to keep in mind is that elements sharing the same order behave as if they have no order set in relation to one another.
Determining relative size of flex items: flex-grow
The flex-grow
property accepts a number value (that may be fractional) that tells the browser how much a flex item will grow relative to the rest of the flex items in the flex container. It specifies how much of the remaining space is assigned to the item’s size.
.flex-item {
flex-basis: auto;
flex-grow: 0;
flex-shrink: 1;
}
Code language: CSS (css)
If the flex-direction
is set to row
, then the grow factor is applied to the flex item’s width. If it’s set to column
, then the grow factor is applied to the flex item’s height.
In the code above, I’m also including flex-basis
and flex-shrink
(discussed later). These properties are designed to work together, so it’s encouraged to include all three, or use the shorthand (see later on flexbox shorthand properties).
Here’s a demo that allows you to increment the flex-grow
property on a single flex item, so you can see the behavior:
Notice the flex container has three flex items. All three have their flex-grow
property set to 0
(the default). The number input on the page allows you to increase the flex-grow
value for the middle flex item, setting it to a decimal value between 0 and 1.
In this example, any number higher than 1
is the same as 1
. The other flex items do not have a flex-grow
value, so their flex-grow
is at the default value of 0. Therefore, any value higher than 0 for the second flex item will result in that item taking up that percentage of the remaining space.
If however, the other items had their flex-grow
values set at 1
, then any item you wanted to be bigger would have to have a value higher than 1
to see any difference in size. To illustrate, here’s another demo, this time the #1 and #3 items start with flex-grow: 1
and the middle item starts with flex-grow: 0
:
As you can see, the flex-grow
value for any one flex item is relative to the flex-grow
value for the others and the remaining space is assigned based on the difference in flex-grow
values.
Determining relative size of flex items: flex-shrink
The flex-shrink
property is probably the flexbox property that you’ll use the least of any of the ones in this CSS flexbox tutorial. It works somewhat in the reverse way that flex-grow
works. In the example, I’ll start with the following code for all three flex items:
.flex-item {
flex-basis: 500px;
flex-grow: 1;
flex-shrink: 0;
}
Code language: CSS (css)
In the interactive demo, I’m setting the flex-shrink
value to 1
for all the flex items, then I’m changing the middle item to flex-shrink: 0
, which you can then adjust using the number input in increments of 0.05:
Likely you would use whole numbers for the shrink factor in a real-world example, but this just demonstrates that fractional values are possible. As you can see, as the flex-shrink
value increases in relation to the flex-shrink
of the other items, the targeted item’s size gets smaller, which is more or less opposite to how flex-grow
works.
To clarify how this works:
- All items are set with a
flex-basis
of 500px - Two of the items have a
flex-shrink
value of1
, which makes them shrink - The middle item starts with a
flex-shrink
value of0
, which means it’s not shrunk to begin with - When you incrementally increase the shrink value of the middle item, it shrinks accordingly
- The other items get bigger as the middle item shrinks because both the shrink and grow factors are always calculated based on space available as well as relative to the other items’ shrink or grow factors
As already mentioned, these three properties are designed to work together, so you should get in the habit of including all three, or else using the shorthand.
Set the initial size of a flex item: flex-basis
The flex-basis
property lets you define the size of a specific flex item before free space is distributed according to common flexbox calculations such as those already discussed.
The syntax is similar to width and height in CSS:
.flex-item {
flex-basis: auto;
flex-grow: 0;
flex-shrink: 1;
}
Code language: CSS (css)
The flex-basis
property can accept one of the following values:
auto
– The initial value, similar to how width and height values can be set toauto
content
– This keyword is similar toauto
but it calculates the size of the item based on the content it containslength
– Any length value (px, em, etc.)percentage
– Any percentage value
As of this writing, the content
value is a new feature that’s supported only in Firefox, so the demo below doesn’t include content
as an option.
Try changing the value of the number input. Notice how the size of the first flex item changes as its flex-basis
gets larger. This allows you to adjust the size of a specific element before the rest of the available space is assigned.
And note that when using any of the three properties flex-basis
, flex-grow
, and flex-shrink
, the effects they have will depend on whether the flex container is in row or column mode. Note the next CodePen that demonstrates this with the container now set to flex-direction: column
:
As you can see, the value for flex-basis
isn’t just tied to width
but will affect the flex items depending on the flex-direction
of the container.
Self-aligning a flex item: align-self
Earlier, I showed you how to use the align-items
property on the flex container to determine alignment of the flex items across the cross axis while the items remain aligned on the main axis.
The align-self
property allows you to define the same type of alignment but narrowed to a specific flex item. Recall that align-items
is for the flex container; align-self
is applied to one or more flex items.
.flex-item {
align-self: flex-start;
}
Code language: CSS (css)
The align-self
property accepts the same values as the align-items
property with the only difference being that align-self
also accepts the keyword auto
. The auto
value simply means that the flex item will determine any alignment based on the value of align-items
on the container.
I’m going to use the same demo that I used earlier for align-items
, except this time the values selected will be applied only to a single element of the ten (the #5 item).
To see the same values applied to a different element, move the .extra
class in the HTML to a different element (the change will apply to the first element with a class of .extra
, so there should only be one).
Flexbox shorthand properties
I’ve covered all the longhand flexbox properties so far, but you should be aware that some of the properties can be expressed using shorthand. I won’t provide any further demos in this section, just a breakdown of the shorthands.
The flex
shorthand
The flex
shorthand is applied to one or more flex items and represents three properties:
.flex-item {
flex: <flex-grow> <flex-shrink> <flex-basis>;
}
Code language: CSS (css)
You can also supply a keyword value of none
by itself to reset any existing flex values on the item. One of flex-grow
or flex-basis
must be present and flex-shrink
is optional and must follow flex-grow
.
Taking what I covered earlier for those individual longhand properties, an example might look like this:
.flex-item {
flex: 0 1 300px;
}
Code language: CSS (css)
This single declaration sets the flex-grow
property to 0
, the flex-shrink
property to 1
, and the flex-basis
property to 300px
.
I should also point out that the spec encourages use of the flex
shorthand vs. the individual longhand properties. It says:
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.
The flex-flow
shorthand
The other shorthand property you have the option to use is flex-flow
and it applies to the flex container. This property represents:
.flex-container {
flex-flow: <flex-direction> <flex-wrap>;
}
Code language: CSS (css)
You’re only required to include one of the values. Because the possible values for each don’t overlap, you can include either property’s value by itself. The following example sets flex-direction
to column
and flex-wrap
to wrap-reverse
:
.flex-container {
flex-flow: column wrap-reverse;
}
Code language: CSS (css)
Some real-world CSS flexbox snippets
Flexbox makes it easy to do a sticky footer with CSS, a common pattern where the footer stays at the bottom of the viewport until content pushes it down.
Use the buttons to add or remove paragraph content. This was previously only possible with various hacks and workarounds.
Flexbox also makes it easy to center any element vertically inside any container, regardless of the size of the element or its container – something that was virtually impossible in the past.
In the above demo, try resizing either the container or the flex item inside it. Whatever the size, the item will remain both horizontally and vertically centered. This is accomplished using just three lines of flexbox CSS on the container:
.flex-container {
display: flex;
align-items: center;
justify-content: center;
}
Code language: CSS (css)
Finally, here’s a responsive CSS cards layout where each card is a media object. No floats, no display: inline-block
or other grid-mimicking workarounds.

If you visit that CodePen, you can interactively add or remove card components to see how the layout behaves. With CSS flexbox, this is easy and there are no layout side effects to worry about like we used to have when using floats or other methods.
Wrapping up this CSS flexbox tutorial
I hope this interactive CSS flexbox tutorial has given you lots to experiment with if flexbox is a new concept to you. You can use CSS templates as a playground if you like. If you were already familiar with flexbox, maybe some of the details of the different features are clearer now.
Finally, if you’d like to fiddle around with the examples from this CSS flexbox tutorial, you can view all the interactive CodePen demos in this CodePen collection.
Have any questions about flexbox? Ask away in the comments section!
…
Don’t forget to join our crash course on speeding up your WordPress site. Learn more below:
Layout and presentation by Karol K and Chris Fitzgerald.