© We Can Code IT, LLC
The second layout tool in our CSS toolbox: Flexbox! It is a great tool to couple with CSS Grid to make sure that your content will look good on any device and with absolute ease. (At least compared to how this business used to get done. Which is bad. Very bad.) Flexbox is a very powerful tool and can actually be used to build out page layouts on its own. Hopefully by the end, though, it will become clear when to use grid and when to use flexbox. Let's get started.
Rejoice! It's our friend the container again! This time we make it a flex container:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flexbox Example</title>
<link rel="stylesheet" href="./layout.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<!-- Again, your content goes here -->
</div>
</body>
</html>
.container {
display: flex;
}
So there are two MAJOR pieces of vocabulary we need to understand before moving forward because we are going to reference them a lot.
The first thing we need if we are going to use flexbox is a flex container. In our example, our flex container is the div with the class container
. (This is a fairly common practice btw so get used to it and try to start using it on your own) Setting the display to flex lets your code know that anything inside of this containing element should be treated with flexbox rules
Now where would we be without some content to manipulate with this amazing tool. The direct children of the flex container are known as the flex items. This is the content that we are actually going to be manipulating. This is also why it's important to house your content in appropriate section
tags. We are going to be affecting almost every element in our code with CSS so organize it.
Flex item placement is based on two axes. The main-axis and the cross-axis.
The main-axis is the flex line that your content is placed on. By default the main-axis goes from left to right.
The cross-axis is situated perpendicular to the main-axis. This axis is used to distribute your content in the opposite direction of your main-axis.
These two work together as a sort of binary placement system. Think (x, y) coordinates on a graph. But these coordinates can be dynamic. This is what makes flexbox so powerful.
Let's get some content inside of our document to play with:
<div class="container">
<div class="flexItem flexItem--1">flex item 1</div>
<div class="flexItem flexItem--2">flex item 2</div>
<div class="flexItem flexItem--3">flex item 3</div>
<div class="flexItem flexItem--4">flex item 4</div>
<div class="flexItem flexItem--5">flex item 5</div>
</div>
.container {
display: flex;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
.flexItem {
margin-left: 5px;
padding: 11px;
}
.flexItem:first-child {
margin: 0;
}
So the first thing to notice is that display: flex;
renders your container as a block level element. Most of the time, this is going to be what you want because you'll want your container to fill the entirety of the space it occupies.
If, for some reason, you want your container to be viewed as an inline level element, you can use display: inline-flex;
instead of just flex. You'll notice that our auto
margins collapse when we do this because, as an inline level element, there is no extra space around our element.
One of the first advantages that you'll notice about flexbox is the ability to change the flow of your content from horizontal to vertical.
Before flexbox this was not as easy as it may seem. Sure you could change the display of the elements to inline or block based on your needs but this always came with unexpected consequences, things that needed to be worked around, unnecessary containers, etc. Flexbox mitigates all of the nonsense for you. All you need to do to change orientation in flexbox is to change one line of code: flex-direction
. Let's see it in action.
So let's have a reminder of what we're looking at currently:
The default value of flex direction is row. There are three other options. Let's check them out.
The next value to discuss is row-reverse
:
.container {
display: flex;
flex-direction: row-reverse;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
What do you think happens when we set the flex-direction
this way?
It gives us:
Next we're going to get into column
:
.container {
display: flex;
flex-direction: column;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
Any guesses for this flex-direction
?
You'll notice when we give our container flex-direction: column
that our main-axis and cross-axis actually switch places. This makes your content flow vertically beginning at the top:
Finally, we're going see what happens with column-reverse
:
.container {
display: flex;
flex-direction: column-reverse;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
And finally, we'll set flex-direction
to column-reverse
For our final flex-direction
, we see that the content behaves similar to how row-reverse
behaves only in a new orientation:
As you can see, flexbox has a wide range of options when it comes to the orientation of your content. The power lies in how little code you have to write to get your content to behave this way.
One of the first issues to deal with is wrapping content. You'll notice if you compress your window, your flex items just squish together on the same line:
We can fix this with another simple addition to our flexbox rules:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
Now whenever our container is too narrow for our content to fit in one line, it will split onto as many lines as it needs to display properly.
Other options are `nowrap` and `wrap-reverse`. Play around with both to see their functionality.
Another really powerful aspect of flexbox is the order
property. So we can give numerical values to individual elements and change their order.
The default order value given to elements is 0. This is why they're placed in the order they appear in your HTML. But if we wanted to have flex item 4
at the front, we can simply give it an order value less than 0:
.flexItem--4 {
order: -1;
}
Notice how flex item 4
is now at the front of our list as opposed to the fourth slot, where it falls in our HTML layout:
This is super valuable because we can leave our HTML semantically marked up and order things how we want them using CSS. This is the way things should be.
So what good is all of this without being able to distribute your content the way you want? Exactly, worthless. So let's jump into the magic of justify-content
. The default value of justify-content
is flex-start
. This is what you've seen so far:
Notice how the content is flush with the left side or start of the container.
The next value for justify-content
is similar to the first. The value is flex-end
and it does exactly what you'd expect:
All items are now aligned to the right side of the container.
A really useful value for justify-content
is center
. It's not only one of the most used values for justify-content
but one of the big reasons to use the property at all. We'll get to why this is such a powerful value in future slides:
This takes all content that you have inside of your container and centers it for you. On it's own it looks like you could easily do this with text-align: center;
, and you'd be right. The real power here comes from a pairing with another property.
The next value we're going to discuss is space-between
. This is a really interesting value because it's functionality hasn't even remotely existed in CSS until now. space-between
takes all space remaining outside of your content and distributes it evenly between each element. Like so:
This is really useful for distributing things like navigation items.
The final value we're going to talk about is space-around
. This value behaves similarly to space-between
but instead places excess space on either side of each item. Like so:
This is really useful for times that you need to distribute extra space evenly and not have the first or last item be flush to the side of your container.
So to recap, all values for justify-content are:
.some-containing-element {
/* Note: you cannot use the 'or' pipes
** in the declaration. They're just there
** to denote possible options
**/
justify-content: flex-start || flex-end || center || space-between ||
space-around;
}
This is where distributing items gets REALLY interesting (and way easier). The align-items
property is very similar to justify-content
except it handles distribution of items along the cross-axis instead of the main-axis. To see this in action, let's add some height to our container and check out the default value, stretch
:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: 20rem;
justify-content: space-around;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
As it's name implies, stretch
stretches all elements to take up all space available on the cross axis:
Sometimes this is very useful, other times, it's a nuisance. Luckily we have other values to choose from.
Our next stop on the align-items
value trail is one we've seen already, flex-start
! It does a very similar job here:
This is good for aligning everything to the top of your container.
It would logically follow, then, that align-items
also has a flex-end
value. It very does:
Again, this performs very similarly to flex-start
but aligns items to the bottom or end of the container.
And now, the moment you've had no idea you'd been waiting for. align-items
has a center
value! You should be freaking out about this but you probably have no idea the horrors that were trying to vertically center something without this amazing tool.
This is SO amazing. Centering in CSS was truly the stuff of nightmares for the frontend developer until flexbox. What's even more amazing is when you pair it with `justify-content: center;`. LET'S DO THAT!
.container {
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: 20rem;
justify-content: center;
margin: 2rem auto;
padding: 11px;
max-width: 1000px;
}
Which gives us:
Content.π Aligned.π To.π The.π Center.π Of.π A.π Container.π
Commence to losing your mind. I'll wait...
Related to align-items
but not totally is a property that can go on individual items called align-self
. This allows you to have the functionality of align-items
but with individual items. Let's try is on item 2:
.flexItem--2 {
align-self: stretch;
}
This yields the result:
This way you can pretty much put things where ever you want them to be.
There is a property on flex items called flex-grow
. This property has a default value of 0. But when applied to items in your flex container, it makes each item take up a certain amount of remaining space in the container. Let's apply of 1 to all of our items and see how it goes.
.flexItem {
flex-grow: 1;
margin: 5px;
padding: 11px;
}
Notice how all elements are taking up all available space (minus margins) in the container.
Let's change the flex-grow
property of item 3 and see how it's affacted.
.flexItem--3 {
flex-grow: 5;
}
Item 3 has a flex-grow
value of 5 and the other 4 elements have a flex-grow
value of one for a total of 9 units.
Notice how item 3 appears larger now.
Now on to flex-basis
. This allows each item with the property applied to have a width that it must have. That is to say items cannot shrink smaller than their flex-basis
. Let's apply this with a value of 350px
to item 4 and see the result.
Notice how when the container is compressed item four will not have a width lower than 350px
Clone the repository found here and follow the instructions in the README.md to complete the assignment. When you finish up, take a look at Flexbox Zombies for some in-depth practice with flexbox.