A complete guide to CSS Flexbox with practical examples
Hello! This is the first article in a series on HTML&CSS. And I decided to start with Flexbox. There are already quite a few guides on Flexbox in CSS on the Internet. But most often these are cheat sheets that don’t really help you understand how everything actually works. I will try to cover the topic using real examples. And at the end of the article I will share life hacks that I myself constantly use in my work.
If you prefer to perceive information in video format, you can watch the video on YouTube:
What is Flexbox and why is it used?
Flexbox in CSS is a special tool that helps you control the arrangement of elements on a web page.
Flexbox is especially useful for creating flexible and responsive layouts because the flex grid configuration can be easily changed across different device sizes.
Sandbox
Later in the article I will talk about all the properties using the example of a block with several elements.
Div with class container
– this is the element with a white outline from the example. It will act as a flex container. And inside this block there will be the elements themselves with the class item
. Initially, our example without special flex styles looks like this.
<div class="container">
<div class="item item-1">item 1</div>
<div class="item item-2">item 2</div>
<div class="item item-3">item 3</div>
</div>
The example will be available in the sandbox on Codepen. You can simultaneously repeat all the steps from the article yourself, so the information will be absorbed even better.
display:flex
Meaning flex
for the container is set via the property display
. By default this property has the value display: block
.
We write down the meaning display: flex
. And then our block turns into a flex container.
.container {
display: flex;
}
We will immediately notice how the values line up.
flex-direction
In general, a flex container can arrange values both horizontally and vertically. By default, as you can see from the previous example, the main axis is the horizontal axis. But we can change the direction using the property flex-direction
.
If you write the value column
at flex-direction
then the direction of the elements will change.
.container {
display: flex;
flex-direction: column;
}
U flex-direction
Reversible properties are also available. For example, row-reverse
displays values horizontally in reverse order.
.container {
display: flex;
flex-direction: row-reverse;
}
A column-reverse
sets values in reverse vertical order.
.container {
display: flex;
flex-direction: column-reverse;
}
flex-wrap
If we add more elements to the example, we will see that they are compressed into 1 row and do not go to a new line.
<div class="container">
<div class="item item-1">item 1</div>
<div class="item item-2">item 2</div>
<div class="item item-3">item 3</div>
<div class="item item-4">item 4</div>
<div class="item item-5">item 5</div>
<div class="item item-6">item 6</div>
<div class="item item-7">item 7</div>
<div class="item item-8">item 8</div>
<div class="item item-9">item 9</div>
</div>
The property is responsible for moving elements to a new line flex-wrap
. If we indicate flex-wrap: wrap
then the elements will be moved to a new line.
.container {
display: flex;
flex-wrap: wrap; /* default - flex-wrap: no-wrap */
}
If you specify a value wrap-reverse
then the elements will begin to line up starting from the bottom line and then move from the top to a new line.
.container {
display: flex;
flex-wrap: wrap-reverse;
}
justify-content
Property justify-content
allows you to control the distance between elements along the main axis.
If you set the property to flex-end
then all elements will be pressed to the right edge.
.container {
display: flex;
justify-content: flex-end;
}
If we change to flex-start
, then we will see how the elements are pressed to the left edge. And this, by the way, is the default value.
.container {
display: flex;
justify-content: flex-start; /* default */
}
Let's look at the other possible values below.
Meaning center
compresses all elements into the center.
.container {
display: flex;
justify-content: center;
}
Meaning space-beetwen
sets the same distance between elements, but presses them along the edges.
.container {
display: flex;
justify-content: space-between;
}
Meaning space-around
sets the same distance around each element. The effect of double indentation between elements is created, because the indents from each element are added.
.container {
display: flex;
justify-content: space-around;
}
Meaning space-evenly
Creates equal spacing along the edges and between elements.
.container {
display: flex;
justify-content: space-evenly;
}
align-items
The next important property for a flex container is the property align-items
. It sets the rules for how to align elements vertically, that is, along an additional axis.
But to see how it works, we need to make the elements of different heights. To do this, we will add a different number of lines in each item.
<div class="item item-1">
item 1
<div>text</div>
<div>text</div>
</div>
<div class="item item-2">
item 2
<div>text</div>
</div>
<div class="item item-3">
item 3
</div>
Initially, we see that all values are stretched to the same height. This happens because align-items
has the meaning stretch
default.
Next, let's look at other available properties.
Meaning flex-start
presses all elements up.
.container {
display: flex;
align-items: flex-start;
}
If you write the value flex-end
then all the elements will be pressed down.
.container {
display: flex;
align-items: flex-end;
}
Meaning center
will align all elements to the center.
.container {
display: flex;
align-items: center;
}
Meaning baseline
at first glance it looks like flex-start
.
.container {
display: flex;
align-items: baseline;
}
But, if we set different font sizes in all elements, we will see that the elements move a little.
.item-1 {
font-size: 32px;
}
.item-2 {
font-size: 64px;
}
.item-3 {
font-size: 16px;
}
Meaning baseline
aligns elements along the bottom border of the first line of the font, the so-called baseline. Pay attention to the yellow line in the screenshot.
gap
The last property for a flex container is the property gap
. It sets the distance between elements. Let's add more elements to the example and pass it to the property gap
meaning 16px
.
.container {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
We see that 16 pixels of padding have been added between elements.
But we can set different indents horizontally and vertically – to do this we need to pass 2 values in a row. Let's try to convey 16px
And 32px
. And we will see that the first property will set the vertical margins, and the second property will set the horizontal margins.
.container {
display: flex;
flex-wrap: wrap;
gap: 16px 32px;
}
While this is all you need to know about the flex container, we have studied all its properties. Next, let's look at the properties for the elements themselves, which are inside the flex container.
order
And we can start with the property order
. This property specifies the display order of a particular element. By default, all elements have order: 0
and then the elements are simply displayed in the order in which they are declared in the HTML.
Let's try to change the value order
by 1 for the second element.
.item-2 {
order: 1;
}
We immediately see that the second element went to the very end. Because the first element has a value order: 0
the third element has the value order: 0
and the second element has the value order: 1
and he accordingly goes to the very end.
Now let's try to change order
for all elements.
.item-1 {
order: 5;
}
.item-2 {
order: 3;
}
.item-3 {
order: 1;
}
By the way, order
does not have to be 1 to 1 in a row. We can specify any values, and CSS simply compares which is greater and which is less.
align-self
Property align-self
similar to align-items
at the container, but only it is now set to the child element and is responsible only for its alignment.
For clarity, let’s make different heights for the elements and set align-items: center
at the container. After this, the first element in the property align-self
indicate the value flex-start
.
.container {
display: flex;
align-items: center;
}
.item-2 {
align-self: flex-start;
}
The second element is now aligned to the top border, although the remaining values are aligned to the center.
If we change the value to flex-end
then the element will jump down.
.item-2 {
align-self: flex-end;
}
And so you can change each element separately. For property align-self
the same values are available as for the property align-items
for a flex container – flex-start
, flex-end
, center
, baseline
, stretch
.
Next we move on to a series of the most complex properties. It is with them that beginners most often have problems.
flex-grow
And we'll start with the property flex-grow
. This property allows you to specify the enlargement factor of the element relative to the free space inside the flex container. Free space is the remaining unfilled space inside the flex container, which is highlighted in yellow below.
Please note that the value flex-grow
– this is not the ratio of elements to each other.
Default flex-grow
has a value of 0. This is why initially the elements do not share space with each other. If we specify 1, then all elements become the same, because they evenly divided this free space among themselves.
.item {
flex-grow: 1;
}
Now let's try to overwrite the value flex-grow
the very first element by 0, and we will see that it has decreased again.
.item {
flex-grow: 1;
}
.item-1 {
flex-grow: 0;
}
Here the area of potential free space is highlighted in yellow if all elements had flex-grow: 0
. A value of 0 means that the first element does not participate in the division of free space in any way. And the remaining 2 elements divide the space between themselves, as can be seen from the lower scale in the screenshot above.
Now let's try to write different values flex-grow
for all elements.
.item-1 {
flex-grow: 1;
}
.item-2 {
flex-grow: 2;
}
.item-3 {
flex-grow: 3;
}
I would like to point out once again that these properties do not mean that the second element will be 2 times larger than the first, and the third element will be 3 times larger than the first. All elements will precisely divide the free space among themselves in equal proportions.
Relatively speaking, the first element will get 1 share of the yellow block, the second element will get 2 shares, and the third element will get 3 shares.
By the way, this property will stop working if the content doesn’t fit on the screen anyway. For example, let's add more elements and try to specify for .item-1
meaning flex-grow
more than 0.
.item-1 {
flex-grow: 2;
}
Nothing changes. This happens because there is no free space and, accordingly, there is nothing to divide.
Values other than 0 and 1 are rarely used in practice. Therefore, the most important thing is to work out how exactly 0 and 1 interact with each other.
flex-basis
The next property is the property flex-basis
. This is a super important property and is very often used in practice.
Property flex-basis
indicates how wide the element will be by default. It may seem that flex-basis
is a replacement width
, But actually it is not. Property flex-basis
establishes only optimal width, that is, if we pass flex-basis: 200px
then it’s not at all a fact that the element will be width 200px
– it can be either more or less. Let's figure out why this happens.
First, let's indicate for all elements flex-basis 200px
:
.item {
flex-basis: 200px;
We can make sure that it really became 200px. Let's try to substitute other values. For example, let's specify 50px.
.item {
flex-basis: 50px;
}
Now we see that the elements actually occupy a larger width, 86px to be exact. This happens because they have been compressed to the smallest possible width, then the word item
It just doesn't fit in the container.
A similar story will happen if you specify too large a value. For example, let's try in flex-basis
hand over 300px
.
.item {
flex-basis: 300px;
}
And now we see that the elements, on the contrary, occupy a smaller width – 262px instead of 300px. Otherwise they simply would not fit in the container.
Very often in practice flex-basis
use percentages. For example, let's write 25%:
.item {
flex-basis: 25%;
}
We see that all the elements took up 1/4 of the part. This creates a grid on the sites. An example of such a grid will be shown at the end of the article.
flex-shrink
flex-shrink
helps distribute space if there is not enough space in the container. Let's create a situation where there is not enough space. Let's try to indicate a big one flex-basis
for the elements so that they do not fit. We will also add a fixed width to 600px
for a flex container.
.container {
display: flex;
width: 600px;
}
.item {
flex-basis: 300px;
}
In fact, the elements took on the width 200px
but not 300px
, as can be seen in the screenshot. Although ideally all three elements should occupy the width 900px
if only the container were larger.
If we specify flex-shrink: 0, then we will see the width of the content 900px
. The elements will simply fall outside the container.
.item {
flex-basis: 300px;
flex-shrink: 0;
}
This happens because flex-shink: 0
prevents elements from shrinking. And they strictly occupy the optimal width that we indicated in flex-basis
. If we change the value to 1
then we will return to the original state. 1
– this is the default value of the property flex-shrink
.
Now let's try to give different flex-shrink
for all the elements and let's see what comes of it.
.item {
flex-basis: 300px;
}
.item-1 {
flex-shrink: 1;
}
.item-2 {
flex-shrink: 2;
}
.item-1 {
flex-shrink: 3;
}
Pay attention to the actual width of the elements. The first element has a width 250px
the second 200px
and the third 150px
. Why did this happen?
Our container was conditionally overfilled by 300px
if there was an optimal width everywhere flex-basis
. As a result, these 300px
lost for all elements in proportion to the coefficient flex-shrink
. The first one became smaller by 50px
the second element became smaller by 100px
and the third element became smaller by 150px
.
Shorthand notation
For these three properties (flex-grow,
flex-shrink
And flex-basis
) there is a shorter notation. We can write like this:
.item {
flex: 1 1 200px;
}
The first value is responsible for flex-grow
second for flex-shrink
and the third for flex-basis
. You can write as you prefer, both options are correct – full and shortened.
Lifehacks
We have looked at all the flex properties of both the container and child elements. And now I will show you some examples from real practice. These are my life hacks that I constantly use at work.
On my YouTube video These examples are discussed in more detail. And here you can look at the code and try to experiment.
Centering an element
The first life hack is to center a single element in a flex container. A very simple hack that will also come in handy during interviews when they ask about centering methods.
Net
The next example is a little more complicated. But I don’t have a single project where I haven’t written such a grid for myself.
Stretching to available space
And the last example that I use very often in my work is a component with a fixed part. This fixed part should take up as much space as the content it contains. In this case, it is the “Submit” button. As you can see, it is always the same width. And the second part of the component should stretch to the entire available space.
Bottom line
You and I have learned to use flexes to the fullest. I also showed you some useful examples that you can safely use in your work. All examples from the article are available at link in github.
Subscribe to telegram channel Vaitishnaya — I post useful materials there and write honestly about IT