What is flexbox?
Flexbox is a CSS display option that lets a container change the size of its children, such that the best possible layout is maintained across all display sizes. That's a mouthful, but it means that you can make sure your responsive components keep a great layout, without having to use javascript or do lots of absolute positioning or floats.
Example time, EXCELLENT!
Let's get started by bringing our basic page and a little styling in. I'm not
doing anything special in the body, just making a
main
block as my container
and then a series of boxes. I'll go ahead and put classes on each box so we
can address them individually later. In the stylesheet, I'm going to give our
main
area a background color and a bit of margin and padding to make clear
what changes happen as we apply rules.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Flexbox</title>
<link rel="stylesheet" href="normalize.css" type="text/css">
<link rel="stylesheet" href="typebase.css" type="text/css">
<link rel="stylesheet" href="style.css" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<header>
<h1>Flexbox</h1>
</header>
<main>
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="four">5</div>
<div class="six">6</div>
<div class="seven">7</div>
<div class="eight">8</div>
<div class="nine">9</div>
<div class="ten">10</div>
</main>
</body>
</html>
header {
text-align: center;
margin: 1rem;
}
main > div {
width: 10rem;
background: yellow;
margin: 1rem;
padding: 1rem;
}
main {
background: lightblue;
margin: 1rem;
padding: 1rem;
}
Flex Contianer Properties
Now that we're all setup and good to go, let's start looking at the container
properties that you can use with flexbox. We'll start off by adding
display: flex;
to our
main
element. With a refresh we see that now our
divs are now horizontally aligned, and grow or shrink within reason to fit our
page. We could also use
inline-flex
to make
main
an inline element. This
is a great strategy if you are stacking multiple flex areas next to each other,
for example product cards in a shopping site.
main {
background: lightblue;
margin: 1rem;
display: flex;
}
Flex Direction
The first thing we should play with is flex direction. After we add that to the
container, and can choose either
row
to go horizontal, or
column
to make
it vertical. Additionally, we can add
-reverse
to either and have it go
left-to-right or bottom-to-top, respectively. Let's look at a quick example of
this:
main {
/* snip */
flex-direction: column-reverse;
}
By adding
flex-direction: column-reverse;
to our
main
element, we now have
our divs counting down from 10, vertically. Let's revert that change to
row
before moving on.
main {
/* snip */
flex-direction: row;
}
Axis, Starts, and Ends
Just to have a clear model in your head about how this works, browsers track
a handful of different pieces of data to make the flex calculations. Axis are
one set of these points. The
main axis
is measured across the
flex-direction
with the
cross axis
being perpendicular to that. Each Axis
has a
start
and
end
point where you would expect it, and they flip if you
set a
-reverse
direction. Having this model in your head is important,
because a lot of the later properties we'll cover use the axis and points as
anchor positions. There is a great diagram on the
MDN site
and it's worth taking a few minutes to study.
Flex Wrap
With
flex-wrap
your options are
nowrap
,
wrap
, and
wrap-reverse
. By
default, flex will keep all your items in a single row or column; this is
nowrap
.
main {
/* snip */
flex-wrap: nowrap;
}
If you need to build your items from the
cross end
then you'll want
wrap-reverse
.
main {
/* snip */
flex-wrap: wrap-reverse;
}
Here we can see that our items are built out left to right, bottom to top.
Often, you'll want them to roll over to the next line, just like normal inline elements would, this is when you would want to use 'wrap'.
main {
/* snip */
flex-wrap: wrap;
}
Luckily, this looks exactly like you think it should, and is probably the most common use case with flexbox.
At this point, we should be able to get our elements roughly in the right place, the final few properties determine how the elements take up that space.
justify-content
If you need to tweak how your items are placed along the main axis, then
justify-content
is what you are looking for. The first few properties are
obvious:
-
flex-start: places the content starting at main-start -
flex-end: places the content starting at main-end -
center: centers the content midway along the main axis
Let's try adding a
center
property and seeing what it looks like.
main {
/* snip */
justify-content: center;
}
Our content is wrapped just like before, but the elements are all centered horizontally (since that is our main axis). The next two are a bit more confusing, so we should look at more examples.
If you want the space spread out between all the elements, with the first
element touching main start, and the final element touching main end, then
space-between
is your best bet.
main {
/* snip */
justify-content: space-between;
}
Where as if you want to split the empty space evenly around all the elements,
space-around
will do that easily.
main {
/* snip */
justify-content: space-around;
}
align-items
To control how the cross axis is spaced, then you'll want to use
align-items
.
We'll also need to add some height to our container to see how these work.
Again the first three are trivial:
-
flex-start: places the content starting at cross-start -
flex-end: places the content starting at cross-end -
center: places the content midway on the cross axis
main {
/* snip */
height: 30em;
align-items: center;
}
I think
baseline
is confusing. It aligns based upon the baselines of each of
the affected elements so its great for lining up text. However, it can produce
unexpected results when you have differing sized boxes. Let's make one of our
boxes have some more content, so we can see how this works.
<div class="three">3<br />3<b3 /></div>
With
center
you can see that the threes aren't inline with the other text.
Now if we cange to
baseline
you see that the top '3' is vertically aligned
with the other numbers.
main {
/* snip */
align-items: baseline;
}
stretch
is much easier, it just fills all of the available space along the
cross axis.
main {
/* snip */
align-items: stretch;
}
Let's change that back to center before moving on:
main {
/* snip */
align-items: center;
}
align-content
To control spacing along the cross axis, between rows or columns there is
align-content
. Not to come as a surprise, but the first the first three are
gimmies:
-
flex-start: places the content starting at cross start, leaving space at the cross end -
flex-end: places the content starting at cross end, leaving space at the cross start -
center: places the content in the center, with extra space split between the cross start and cross end
stretch
has a gotcha. It obviously stretches the content to take up all space,
though you'll need to drop any
align-items
as both can't be compensating for
the available space:
main {
/* snip */
/* align-items: center; */
align-content: stretch;
}
space-between
and
space-around
work just like before, only on the cross
axis.
space-between
locks the first and last row or column to the cross start
and cross end.
main {
/* snip */
align-items: center;
align-content: space-between;
}
Here we can see
space-around
distributing the space equally around all sides
of both of our rows of content.
main {
/* snip */
align-items: center;
align-content: space-around;
}
Summary
Today we looked at Flexbox and the properties that go on the flex container. We examined alignment and distribution, flow direction and spacing. Tomorrow we'll learn more about flex items, along with a couple layout basics that will make your life with flexbox much easier.
Comments for Flexbox Containers