Flexbox
There are many ways to style a flexbox, but I'll keep this one simple so that it'll be easier to follow.
First, I want to illustrate what flexbox actually does. While it is an alternative to displays, floats, and other layout properties, it is a lot better as it makes our design responsive—that is to say, mobile-friendly. Check out these two examples and see how they respond to your browser as you resize it:
With Inline-Block and %:
With Flexbox:
As you can see, flexbox enables us to arrange items easily, and once our viewport shrinks, the second box moves to the next line. Now, the latter isn't anything new and is something you could easily achieve with
columns. Personally though? I prefer flexbox as it allows for better control and styling. Now, if you're going for something simple, columns may be your best bet.
So how do we actually make a flexbox? We're going to need two different components: a
container and its
items. Let's get started with creating our container.
First, we're going to input
display: flex;
You can add a width for your container, and
margin: auto;
to center it. However, width and margin are optional. It depends on what design you're going for.
[div=
width: 600px;
margin: auto;
display: flex;][/div]
Next, let's nest our items. In this example, I'll be using two items. However, you can use as few or as many as you'd like.
Let's give our first nested item a red background and 100px height so we can actually see what we're working with. We're going to do the same for its sibling, except we're going to give that one a blue background.
[div=
width: 600px;
margin: auto;
display: flex;][div=
background: red;
height: 100px;][/div][div=
background: blue;
height: 100px;][/div][/div]
Let's add
flex: 1
to our red box and
flex: 2
to our blue box.
[div=
width: 600px;
margin: auto;
display: flex;][div=
background: red;
height: 100px;
flex: 1;][/div][div=
background: blue;
height: 100px;
flex: 2;][/div][/div]
flex: 2;
is basically making our blue box grow 2x faster than our red box, making it larger. If you make this value 3, it will be 3x as fast. And so on and so forth. If you use a value of 1 for both boxes, however, they will be the same size.
Next, we're going to append
min-width: 230px
to each of our flexboxes. This stands for minimum width.
[div=
width: 600px;
margin: auto;
display: flex;][div=
background: red;
height: 100px;
flex: 1;
min-width: 230px;][/div][div=
background: blue;
height: 100px;
flex: 2;
min-width: 230px;][/div][/div]
Output:
Alright. Personally, I don't like how these boxes are sticking too close together, so let's add a gap, shall we? How about a 10px gap? Let's add it to our container.
[div=
width: 600px;
margin: auto;
display: flex;
gap: 10px;][div=
background: red;
height: 100px;
flex: 1;
min-width: 230px;][/div][div=
background: blue;
height: 100px;
flex: 2;
min-width: 230px;][/div][/div]
Output:
If you try resizing your browser now, you'll notice that the second box doesn't go to the next line. Not yet, anyway. We need one last thing to make this perfectly mobile-friendly, and that's
flex-wrap: wrap;
Let's append it to our container once again.
[div=
width: 600px;
margin: auto;
display: flex;
gap: 10px;
flex-wrap: wrap;][div=
background: red;
height: 100px;
flex: 1;
min-width: 230px;][/div][div=
background: blue;
height: 100px;
flex: 2;
min-width: 230px;][/div][/div]
Output:
flex-wrap
is working with our minimum width. As soon as the screen becomes too small to contain our flexboxes at their minimum width, the second box moves to the next line. I find that a 230px-250px of minimum width or each flexbox is best for mobile-viewing.
Now, we also have the option of using
flex-wrap: wrap-reverse
instead of
flex-wrap: wrap
. By using this, we are making our red box move to the next line instead.
Try making your browser smaller!
Now, if that's all you wanted to know, you can stop reading here. It should be enough to help you create responsive designs. However, if you'd like to know more about flexboxes and what we can do with them, read on.
> Grow, Shrink, Basis
Earlier, I refrained from dissecting
flex: value
as there simply wasn't enough space to discuss it in detail. It definitely warrants its own section as there is a lot to say about them, but don't be overwhelmed. They're easy to understand once you get the hang of them. As always, it just takes practice.
The syntax that I used in the previous article is actually a shorthand,
flex: grow shrink basis;
Once again, I will be using visual aid to demonstrate how it is used. However, do bear in mind this will make a lot more sense if you view it on a desktop, where you can resize your browser to see the effects taking place.
Alright, with that out of the way, let's begin.
flex-basis
defines the starting value of our items. It is the
base width of our flexboxes. You can use
lengths, like px, to specify its value.
flex-basis: 100px;
flex-basis: 100px;
flex-basis: 100px;
See that extra space on the right?
flex-grow
, makes the element grow according to the container size or window size. It defines how much of the extra space should be distributed among the items. We use
numbers to specify its value.
If we set it to 0 (the default value), none of the items will take up the extra space. They will remain at their basis, which is 100px in our example.
So, instead, let's try setting our first item to
flex-grow: 1;
Watch what happens:
flex-grow: 1;
flex-grow: 0;
flex-grow: 0;
As you can see, it took up all the extra space for itself. Make your browser smaller. Now, slowly drag to make it bigger. See how the red box grows? That's
flex-grow
doing the work.
Alright, let's set the second item to 2 and see what happens.
flex-grow: 1;
flex-grow: 2;
flex-grow: 0;
Try resizing your browser again. As you can see, the blue box grows twice as fast as the red box.
This time, let's try giving all the boxes a value of 1.
flex-grow: 1;
flex-grow: 1;
flex-grow: 1;
If they all have a value of 1, the space will be distributed equally among all the items.
flex-shrink
, on the other hand, makes the items shrink according to the window size. I'm going to change the basis to 300px real quick just so I can better demonstrate to you what it does.
The default value for
flex-shrink
is 1.
flex-shrink: 1
flex-shrink: 1
flex-shrink: 1
Make your browser smaller. You can see that at 1, they will all shrink at an equal rate and can even become smaller than our basis of 300px.
Let's try setting our red box to a shrink value of 0.
flex-shrink: 0
flex-shrink: 1
flex-shrink: 1
If we set an item to 0, it will not shrink. However, the other items still shrink in our example as they still have the same shrink value of 1.
Let's see what happens if we set our green box to 5.
flex-shrink: 0
flex-shrink: 1
flex-shrink: 5
If we set our third item to 5, it will shrink five times faster than our second item, which has a value of 1.
Now, all these three can simply be specified with a shorthand, which is as follows:
flex: grow shrink basis;
> Flex Item Order
We can also change the order that our items present themselves without restructuring our code. To do this, we simply append the
order
property and input
numbers.
Let's try to move these letters around.
[div=
display: flex;
height: 50px;
color: white;][div=
flex-grow: 1;
order: 2;
background: red;]A[/div][div=
flex-grow: 1;
order: 3;
background: blue;]B[/div][div=
flex-grow: 1;
order: 1;
background: green;]C[/div][/div]
Output:
Pretty easy, right?
> Main Axis & Cross Axis + Justify-Content
An important component of flexbox are the axes, namely the main axis and the cross axis. By default, the main axis would be referring to the
row, whereas the cross axis would be referring to the
column. However, it's not that straightforward, which is probably where a lot of the confusion regarding flexboxes come from.
By default, our boxes would be positioned along a row, like so:
Now, if we want to change where our items are situated within that row, we use
justify-content
by default. There are many values associated with this property, and they are as follows:
- flex-start - positions items at the beginning of the container
- flex-end - positions items at the end of the container
- center - positions items at the center of the container
- baseline - positions items at the baseline of the container
- space-around - items are evenly distributed along the line, with spaces around them
- space-between - items are evenly distributed along the line, with spaces between them
- space-evenly - items are distributed so that the spacing before, between, and after two adjacent items is the same
We've already seen
flex-start
in action, as it is the default, so let's see what
flex-end
does.
[div=
height: 50px;
display: flex;
justify-content: flex-end;
border: 1px solid yellow;
color: white;][div=
flex: 0 1 100px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 100px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 100px;
padding: 10px;
background: green;]C[/div][/div]
Output:
And center:
BUT--and this is where it gets confusing--
justify-content
does not always position items along the x-axis, no sir! It goes hand-in-hand with
flex-direction
. Now, if you omit
flex-direction
from your code, it will default to
row
, thus enabling
justify-content
to align items in a row.
However, if you specify
flex-direction: column
, that will flip things around, meaning
justify-content
does not align items in a row anymore! It aligns things in a column. Capeesh?
Yeah, I know, it's a lot. But a simpler way to remember this is that they both always
mirror each other.
TL;DR
- If
flex-direction
is default row, justify-content
will align items along a row.
- If
flex-direction
is column, justify-content
will align items along a column.
Okay, so let's try appending
flex-direction: column
into our code.
I'll be changing some stuff around, so you can better see how things are working.
[div=
height: 300px;
border: 1px solid yellow;
display: flex;
color: white;
flex-direction: column;][div=
flex: 0 1 50px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 50px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 50px;
padding: 10px;
background: green;]C[/div][/div]
Output:
Alright, what do you think will happen if I append
justify-content: center;
Will it align our items horizontally or vertically?
[div=
height: 300px;
border: 1px solid yellow;
display: flex;
color: white;
flex-direction: column;
justify-content: center;][div=
flex: 0 1 50px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 50px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 50px;
padding: 10px;
background: green;]C[/div][/div]
Output:
Yup, it aligns our items along a column to mirror
justify-content: column
!
But now you must be wondering: well, there must be another property related to this right? Surely this guy has a twin that aligns our items in the opposite arrangement?
You're right. This is where
align-items
comes in.
> Align-Items
Unlike
justify-content
which aligns items horizontally by default,
align-items
aligns our items vertically by default.
When the
flex-direction
is flipped to
column
, however,
align-items
begins affecting horizontal alignment.
Let's check our first example. For now, I'll be using the default direction, which is row.
The default value for
align-items
is
stretch
, meaning the items stretch to fit the container along the main axis. However, we can use some of the same values as the ones we used for
justify-content
. To refresh your memory, they are as follows:
- flex-start - positions items at the beginning of the container
- flex-end - positions items at the end of the container
- center - positions items at the center of the container
- baseline - positions items at the baseline of the container
To use any of these values, simply append them after
align-items:
Don't forget to put them in the div holding the container!
This is how
flex-start
would look like:
[div=
height: 150px;
border: 1px solid yellow;
display: flex;
color: white;
align-items: flex-start;][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: red;]A[/div][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: blue;]B[/div][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: green;]C[/div][/div]
For the purposes of this demonstration, I will be adding a height of 150px for our container, as well as a yellow border so that you see its dimensions. I allocated 33.33% height and 100px basis for each of our items to make them smaller, enabling you to see them moving around in the box.
Output:
Now, what if we changed the alignment to
flex-end
?
Output:
And center?
Output:
Now, let's try to change our
flex-direction
. Once again, I'll be changing some stuff around (namely the flex property) so you can better see how things are working.
[div=
height: 300px;
border: 1px solid yellow;
display: flex;
color: white;
flex-direction: column;][div=
flex: 0 1 50px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 50px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 50px;
padding: 10px;
background: green;]C[/div][/div]
Output:
So, like I said before, by using
flex-direction: column
, we have flipped our axes around. Now,
align-items
will now control the cross axis, which is now the x-axis:
[div=
height: 300px;
border: 1px solid yellow;
display: flex;
color: white;
flex-direction: column;
align-items: flex-start;][div=
flex: 0 1 50px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 50px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 50px;
padding: 10px;
background: green;]C[/div][/div]
Output:
Flex-end will look like this:
Center:
> Individual Item Alignment
So you want to align items
individually? One of the properties we can use is
align-self
. Instead of putting this in our div container, we place it in the div defining our items. Like so:
[div=
height: 150px;
border: 1px solid yellow;
display: flex;
color: white;][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: red;
align-self: flex-start;]align-self: flex-start;[/div][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: blue;
align-self: center;]align-self: center;[/div][div=
flex-basis: 100px;
padding: 10px;
height: 33.33%;
background: green;
align-self: flex-end;]align-self: flex-end;[/div][/div]
Output:
align-self: flex-start;
align-self: center;
align-self: flex-end;
On the other hand, we can't really align items individually with
justify-content
. However, we can use
margin
to aid us with this.
Let's say we want C to go all the way to the right. By using
margin-left: auto
we will be pushing C from the left:
[div=
height: 50px;
display: flex;
border: 1px solid yellow;
color: white;][div=
flex: 0 1 100px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 100px;
padding: 10px;
background: blue;]B[/div][div=
flex: 0 1 100px;
padding: 10px;
background: green;
margin-left: auto;]C[/div][/div]
Output:
Now, if we append the same declaration to B, look what happens:
[div=
height: 50px;
display: flex;
border: 1px solid yellow;
color: white;][div=
flex: 0 1 100px;
padding: 10px;
background: red;]A[/div][div=
flex: 0 1 100px;
padding: 10px;
background: blue;
margin-left: auto;]B[/div][div=
flex: 0 1 100px;
padding: 10px;
background: green;]C[/div][/div]
Output:
Pretty cool, right?
> Centering Items
Now that we know how to manipulate the main axis and the cross axis, let's talk about centering items in our flex container.
Let's say you want to put some text in the middle.
First, let's make our base. As usual, it's
width
,
height
, and a red
background
.
[div=
width: 200px;
height: 200px;
background: red;][/div]
Output:
Let's input our text next. We'll make the color white so we can see it clearly.
We will center our text later.
[div=
width: 200px;
height: 200px;
background: red;
color: white;]Hello world.[/div]
Output:
Now for the fun part. Once again, we'll be using
display: flex
[div=
width: 200px;
height: 200px;
background: red;
color: white;
display: flex;]Hello world.[/div]
Output:
Then, use
justify-content: center
to center our item horizontally. Append
align-items: center
to center items vertically.
[div=
width: 200px;
height: 200px;
background: red;
color: white;
display: flex;
justify-content: center;
align-items: center;]Hello world.[/div]
Output:
You can also center other elements using this process!
[div=
width: 200px;
height: 200px;
background: red;
color: white;
display: flex;
justify-content: center;
align-items: center;][div=
background: blue;
width: 100px;
height: 100px;
border-radius: 100%;][/div][/div]
Output:
And there you have it. Flex makes everything simple for us.
Now that you know how to flexbox, go and flex your skills!
# Featured Properties
display: flex;
flex: grow shrink basis;
flex-grow: value;
flex-shrink: value;
flex-basis: value;
order: value;
min-width: value;
justify-content: value;
align-items: value;
align-self: value;
margin-left: value;
margin-right: value;