The first important notion to fully understand is that of flex
container, also known as container box. The element on which
display: flex
or display: inline-flex
is applied becomes a flex
formatting context for the containing box’s children, known as the flex
container. Once we have created a flex container (by adding a
display: flex
or display: inline-flex
), we need to learn how to
manipulate the layout of the container’s children.
The children of this container box are flex items, whether they are DOM nodes, text nodes, or generated content. Absolutely positioned children of flex containers are also flex items, but they are sized and positioned as though they are the only flex item in the flex container.
We will first learn all about the CSS properties that apply to the flex container, including several properties impacting the layout of flex items. Flex items themselves are a major concept you need to grok and will be covered in full in Chapter 3.
The display
property examples in Figure 1-6 show three flex items
side by side, going from left to right, on one line. With a few
additional property value declarations, we could have centered the items, aligned them to the bottom of the container,
rearranged their order of appearance, and laid them out from left to
right or from top to bottom. We could even have made them span a few
lines.
Sometimes we’ll have one flex item, sometimes we’ll have dozens.
Sometimes we’ll know how many children a node will have. Sometimes the
number of children will not be under our control. We might have a varied
number of items in a set-width container. We might know the number of
items, but not know the width of the container. We should have robust
CSS that can handle our layouts when we don’t know how many flex items
we’ll have or how wide the flex container will be (think responsive).
There are several properties outside of the new display
values we can
add to the flex container to provide control over layout that enable us
to build responsive layouts and responsive widgets.
The display
, flex-direction
, flex-wrap
, and flex-flow
properties
impact the ordering and orientation of the flex container. The
justify-content
, align-items
, and align-content
properties can be
applied to the flex container to impact the alignment of the container’s
children.
flex-flow
Shorthand PropertyThe flex-flow
property lets you define the directions of the main and
cross axes and whether the flex items can wrap to more than one line if
needed.
The flex-flow
shorthand property sets the flex-direction
and
flex-wrap
properties to define the flex container’s wrapping and main
and cross axes.
The default value of flex-direction
is row
. The default value of flex-wrap
is nowrap
. As long as display
is set to flex
or inline-flex
, omitting
flex-flow
, flex-direction
, and flex-wrap
is the same as declaring
any of the following three, which all mean the same thing:
flex-flow
:
row
;
flex-flow
:
nowrap
;
flex-flow
:
row
nowrap
;
In left-to-right writing modes, declaring any of the property values just listed or omitting the flex-flow
property altogether will create a flex container with a horizontal main axis that doesn’t wrap, as shown in Figure 2-1. That’s not the look you’re going for. flex-flow
can help. But you might be wondering why we’re introducing a shorthand property before you understand the component properties.
While the specification’s authors encourage the use of the flex-flow
shorthand, understanding flex-wrap
and flex-direction
, the two properties that make up this
shorthand, is necessary. And, by learning about the values that make up
the flex-flow
shorthand, we’ll learn how to fix the unsightly layout
shown in Figure 2-1.
flex-direction
PropertyIf you want your layout to go from top to bottom, left to right, right
to left, or even bottom to top, you can use flex-direction
to control
the main axis along which the flex items get laid out.
The flex-direction
property specifies how flex items are placed in the flex container. It defines the main axis of a flex container (see “Understanding axes”), which is the primary axis along which flex items are laid out.
Figure 2-2 shows the four values of flex-direction
, including row
,
row-reverse
, column
, and column-reverse
in left-to-right
languages. Note that all flex properties discussed here, like all CSS
properties, accept the global values of inherit
, initial
, and
unset
.
We specified left-to-right languages, because the direction of the main axis for row
—the direction the flex items are laid out in—is the direction of the current writing mode.
Preferably, we should have used the flex-flow
shorthand property. The two right columns in Table 2-1 are equivalent, with the nowrap value being explained in the next section.
flex-direction |
single-value flex-flow |
flex-flow |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
You can reverse this default direction with flex-direction: row-reverse
.
The flex items will be laid out from top to bottom when
flex-direction: column
is set, and from bottom to top if
flex-direction: column-reverse
is set, as shown in Figure 2-2. Note
if the CSS direction
value is different from the dir
attribute value
on an element, the CSS property value takes precedence over the HTML
attribute.
Do not use flex-direction
to change the layout for
right-to-left languages. Rather, use the dir
attribute, or the
writing-mode
CSS property, which enables switching between horizontal
and vertical, to indicate the language direction.
In horizontal writing modes, which includes left-to-right and
right-to-left languages, setting flex-direction: row
,
flex-flow: row
, flex-flow: row nowrap
, or omitting both the
longhand and shorthand properties so it defaults to row
will set all
the flex items horizontally, side to side. By default, they will all be
aligned horizontally, along the main-axis line, in source order. In
left-to-right languages, they will be aligned from left to right: the
left side is referred to main-start and the right is main-end, for
the start and end points of the main-axis. In right-to-left languages,
the main direction is reversed: the flex items are side by side from
right to left, with the main-axis going from left to right, the right
side being main-start and left being main-end.
The row-reverse
value is the same as row
, except the flex items are
laid out in the opposite direction of the text direction: the start and
end points are reversed. The direction of the main-axis of the flex
container is reversed by the row-reverse
value. For left-to-right
languages, like English, row-reverse
will lay out all the flex items
side to side from right to left, horizontally, with main-start being
on the right and main-end now on the left. These are shown in the top two image examples in Figure 2-2.
Had the direction of the page or flex container been reversed, such as for Hebrew or Arabic, with the attribute dir="rtl"
on the flex container or an ancestor in the HTML, or with direction: rtl
on the flex container or container’s ancestor in the CSS, the direction of the row-reverse
main axis, and therefore the flex items, would be inverted from the default, going left to right, as shown in Figure 2-3. Similarly, the writing-mode
property impacts the direction in which the flex items are drawn to the page.
The column
value will lay out the flex items from top to bottom. The
column
value sets the flex container’s main-axis to be the same
orientation as the block axis of the current writing mode. This is the
vertical axis in horizontal writing modes and the horizontal axis in
vertical writing modes. Basically, it sets the flex-container’s
main-axis to vertical in most cases.
There are vertically written languages, including Bopomofo, Egyptian hieroglyphs, Hiragana, Katakana, Han, Hangul, Meroitic cursive and hieroglyphs, Mongolian, Ogham, Old Turkic, Phags Pa, Yi, and sometimes Japanese. These languages are only vertical when a vertical writing mode is specified. If one isn’t, then all of those languages are horizontal. If a vertical writing mode is specified, then all of the content is vertical, whether one of the listed vertically written languages or even English.
The writing-mode
controls the block flow direction: the direction in
which lines and blocks are stacked. The default value, horizontal-tb
,
stacks them top to bottom. The other values stack them right to left or
left to right.
The direction controls the inline “base direction,” the direction in which content within a line is ordered. LTR, short for “left to right,” goes from nominal “left” to nominal “right”. RTL, short for “right to left”, is the opposite. Which side is nominally “left” for the purpose of direction is affected by the writing mode: if the writing mode is vertical, the “left” side might be the top!
The inline base direction is and should always be a property of the
content. Use the dir attribute in HTML. Do not use the CSS direction
property. The writing-mode
is a layout preference.1 Chinese, Japanese, and Korean can be written in
either orientation. While English is a top-to-bottom, left-to-right
language, you will sometimes see and may even use vertical writing for
stylistic effect.
With column
, the flex items are displayed in the same order as
declared in the source document, but from top to bottom instead of left
to right, so the flex items are laid out one on top of the next instead
of side by side:
nav
{
display
:
flex
;
flex-direction
:
column
;
border-right
:
1px
solid
#ccc
;
}
a
{
margin
:
5px
;
padding
:
5px
15px
;
border-radius
:
3px
;
background-color
:
#ccc
;
text-decoration
:
none
;
color
:
black
;
}
a
:hover
,
a
:focus
,
a
:active
{
background-color
:
#aaa
;
text-decoration
:
underline
;
}
Using similar markup to our preceding navigation example, by simply changing a few CSS properties, we can create a nice sidebar-style navigation.
For the navigation’s new layout, we changed the flex-direction
from
the default row
to column
, moved the border from the bottom to the
right, and changed the colors, border-radius
, and margin
values, as seen in Figure 2-4.
The column-reverse
value is similar to column
, except the main axis
is reversed, with main-start being at the bottom, and main-end being
at the top of the vertical main-axis, going upward, as laid out in the bottom-right example in Figure 2-3.
The reverse values only change the appearance. The speech order and tab order remains the same as the underlying markup.
What we’ve learned so far is super powerful and makes layout a breeze. If we include the navigation within a full document, we can see how simple layout can be with flexbox.
Let’s expand a little on our preceding HTML example, and include the navigation as a component within a home page:
<body>
<header>
<h1>
My Page's title!</h1>
</header>
<nav>
<a
href=
"/"
>
Home</a>
<a
href=
"/about"
>
About</a>
<a
href=
"/blog"
>
Blog</a>
<a
href=
"/jobs"
>
Careers</a>
<a
href=
"/contact"
>
Contact Us</a>
</nav>
<main>
<article>
<img
alt=
""
src=
"img1.jpg"
>
<p>
This is some awesome content that is on the page.</p>
<button>
Go Somewhere</button>
</article>
<article>
<img
alt=
""
src=
"img2.jpg"
>
<p>
This is more content than the previous box, but less than the next.</p>
<button>
Click Me</button>
</article>
<article>
<img
alt=
""
src=
"img3.jpg"
>
<p>
We have lots of content here to show that content can grow, and everything can be the same size if you use flexbox.</p>
<button>
Do Something</button>
</article>
</main>
<footer>
Copyright©
2017</footer>
</body>
By simply adding a few lines of CSS, we’ve got a nicely laid out home page, as shown in Figure 2-6:
*
{
outline
:
1px
#ccc
solid
;
margin
:
10px
;
padding
:
10px
;
}
body
,
nav
,
main
,
article
{
display
:
flex
;
}
body
,
article
{
flex-direction
:
column
;
}
It took only two CSS property/value declarations to create the basic layout for a site home page.
Obviously there was some additional CSS. We added border, margin, and
padding to all the elements so you can differentiate the flex items for
the sake of learning (I wouldn’t put this less-than-attractive site in
production). Otherwise, all we’ve done is simply declare the body,
navigation, main, and articles as flex containers, making all the navigation, links, main, article, images, paragraphs, and buttons flex items. Yes, elements can be both flex items while being flex containers, as we see with the navigation, main, and articles in this case. The body
and article
s have column
set as their flex directions, and we let nav
and main
default to row
. Just two lines of CSS!
But what happens when the flex items’ main-dimension (their combined
widths for row
or combined heights for column
) don’t fit within the
flex container? We can either have them overflow, as shown in Figure 2-1,
or we can allow them to wrap onto additional flex lines.
flex-wrap
PropertyThus far, the examples have shown a single row or column of flex items.
If the flex items’ main-dimensions don’t all fit across the
main-axis of the flex container, by default the flex items will not
wrap. Rather, the flex items may shrink if allowed to do so via the flex
item’s flex
property (see “The flex
Property”) and/or the flex items may overflow the bounding container box.
You can control this behavior. flex-wrap
can be set on
the container to allow the flex items to wrap onto multiple flex lines—rows or columns of flex items—instead of having flex items
overflow the container or shrink as they remain on one line.
The flex-wrap
property controls whether the flex container is limited
to being a single-line container or is allowed to become multiline if
needed. When the flex-wrap
property is set to allow for multiple flex
lines, whether the value of wrap
or wrap-reverse
is set determines
whether any additional lines appear either before or after the original line of flex items.
By default, no matter how many flex items there are, all the flex items
are drawn on a single line. This is often not what we want. That’s where
flex-wrap
comes into play. The wrap
and wrap-reverse
values allow
the flex items to wrap onto additional flex lines when the constraints
of the parent flex container are reached.
Figure 2-7 demonstrates the three values of the flex-wrap
property when the
flex-direction
value is defaulting to row
. When there are two or more flex lines, the second line and subsequent flex lines are added in the
direction of the cross-axis.
Whether the additional flex lines are added above or below, as in the
case of Figure 2-7, or to the left or to the right of the previous line is determined
by whether wrap
or wrap-reverse
is set, by the flex-direction
value, and by the writing mode.
Generally for wrap
, the cross-axis goes from top to bottom for row
and row-reverse
and the horizontal direction of the language for
column
and column-reverse
. The wrap-reverse
value is similar to
wrap
, except that additional lines are added before the current line
rather than after it.
When set to wrap-reverse
, the cross axis direction is reversed: subsequent lines are drawn on top in the case of flex-direction: row
and flex-direction: row-reverse
and to the left of the previous column in the case of flex-direction:
column
and flex-direction: column-reverse
. Similarly, in right-to-left languages, flex-flow: row wrap-reverse
and flex-flow: row-reverse wrap-reverse
, new lines will also be added on top, but for flex-flow: column wrap-reverse
and flex-flow: column-reverse wrap-reverse
new lines will be added to the right—the opposite of the language direction or writing mode, the direction of the inverted cross-axis.
You may notice that in Figure 2-7, the new lines created in the wrap
and
wrap-reverse
examples are not the same height as the first line. Flex lines are as tall or wide as their tallest or widest flex item within that line. The flex line’s main dimension is the main dimension of the flex container, while the flex line’s cross dimension grows to fit the cross-size of the flex item with the largest cross-size.
While the examples thus far are fairly simple, as you may have noticed from the two previous paragraphs, fully understanding all the complexities of flexbox is not. The preceding explanation introduced possibly confusing terms like main-axis, main-start, and main-end and cross-axis, cross-start, and cross-end. To fully grasp flexbox and all the flexbox properties, it is important to understand.
To understand flex layout you need to understand the physical directions, axes, and sizes affecting the flex container and its flex items. Fully understanding what the specification means when it uses these terms will make fully understanding flexbox much easier.
Flex items are laid out along the main-axis. Flex lines are added in
the direction of the cross-axis. The “main-” terms have to do with
flex items. The “cross-” terms come into play on multiline flex containers: when wrap
or
wrap-reverse
is set and the flex items actually wrap onto more than
one line.
Up until we introduced flex-wrap
, all the examples had a single line
of flex items. That single line of flex items involved laying out the
flex items along the main axis, in the main direction, from
main-start to main-end. Depending of the flex-direction
property,
those flex items were laid out side by side, top to bottom or bottom to
top, in one row or column along the direction of the main axis.
Table 2-2 summarizes the “main-” and “cross-” terms. It lists the dimensions and directions of the main-axis and cross-axis, along with their start point, end points, and directions for left-to-right writing mode layouts. In addition to describing the dimensions and direction of the flex container, these terms can be used to describe the direction and dimension of individual flex items.
Flex directions in left-to-right (LTR) writing modes | ||||
---|---|---|---|---|
row | row-reverse | column | column-reverse | |
main-axis | left to right | right to left | top to bottom | bottom to top |
main dimension | horizontal | horizontal | vertical | vertical |
main-start | left | right | top | bottom |
main-end | right | left | bottom | top |
main-size | width | width | height | height |
cross dimension | vertical | vertical | horizontal | horizontal |
cross-start | top | top | left | left |
cross-end | bottom | bottom | right | right |
cross-size | height | height | width | width |
In the case of flex-flow: row
(Figure 2-1), the sum of the main-sizes of the nonwrappable line of flex items
was greater than the main-size of the flex container parent. In
plainer English, the combined widths (and noncollapsed horizontal
margins) of the flex items was wider than the width of the flex
container.
In horizontal writing modes, for row
and row-reverse
, the
main size refers to the widths of the flex items and flex container.
In the case of column
and column-reverse
, the main size is
height.
Figure 2-8 shows the axes and the direction of each axis for flex
containers with a flex-direction
of row
, row-reverse
, column
, and
column-reverse
for LTR writing modes.
The main-axis is the primary axis along which flex items are laid out, with flex items being drawn along the main-axis in the direction of main-start to main-end.
If all writing modes were from left to right and top to bottom, like in
English, flex-direction
would be less complex. For both RTL and LTR languages,
flex-direction: row
and flex-direction: row-reverse
the main-axis
is horizontal. For LTR languages, in the case of row
, the main-start is on the left, and
main-end is on the right. They’re inverted for row-reverse
, with the
main-start switching to the right and main-end now on the left. For
column
, the main axis is vertical, with main-start on top and
main-end on the bottom. For column-reverse
, the main-axis is also
vertical, but with main-start on bottom and main-end is on the top.
As shown in Table 2-3, when the
writing mode is right to left, like in Arabic and Hebrew, if you have
dir="rtl"
set in your HTML, or direction: rtl
set in your CSS, the
direction of the text will go from right to left. In these cases, the
direction of row
is reversed to be from right to left with
main-start on the right and main-end on the left. Similarly, the
main-axis for row-reverse
will go from left to right, with
main-start being on the right. For column
, the main-start is
still on the top and main-end is on the bottom, just like for
left-to-right languages, as both are top-to-bottom languages.
Flex directions in RTL writing modes | ||||
---|---|---|---|---|
row | row-reverse | column | column-reverse | |
main-axis | right to left | left to right | top to bottom | bottom to top |
main dimension | horizontal | horizontal | vertical | vertical |
main-start | right | left | top | bottom |
main-end | left | right | bottom | top |
main-size | width | width | height | height |
cross dimension | vertical | vertical | horizontal | horizontal |
cross-start | top | top | right | right |
cross-end | bottom | bottom | left | left |
cross-size | height | height | width | width |
If your site has writing-mode: horizontal-tb
set, as in
Figure 2-5, the main-axis of the
content for row
and row-reverse
will be vertical, while column
and
column-reverse
are horizontal. The writing-mode
property is starting
to get support in browsers, with support in Edge and Firefox, prefixed
support in Chrome, Safari, Android, and Opera, and support for an older
syntax in Internet Explorer.
While the CSS direction
property along with unicode-bidi
can be
used to control the direction of text, don’t do it. It is recommended to
use the dir
attribute and CSS writing-mode
property because HTML’s dir
attribute concerns HTML content, and the writing-mode
property concerns layout.
It’s important to understand things get reversed when writing direction is reversed. Now that you understand that, to make explaining (and understanding) flex layout much simpler, we’re going to make the rest of the explanations and examples all be based on left-to-right writing mode, but will include how writing mode impacts the flex properties and features discussed.
How your flex layout appears on the screen is determined in part by
interactions between flex-flow
—which includes flex-direction
and
flex-wrap
—and the writing mode. We’ve covered the direction in
which flex items are added to a line of flex items, but when the end of
the flex line is reached, how are new flex lines added?
When thinking about flex-direction
, we now know the flex items are
going to start being laid out across the main axis of the flex
container, starting from the main-start. The “cross-” directions come
into play when it comes to adding additional lines of flex items, known
as flex lines. When the flex-wrap
property is used to allow the
container to wrap if the flex items don’t fit onto one line, the cross
directions determine the direction of additional lines in multiline
flex containers.
While the laying out of the flex items on each flex line is done in the main direction, going from main-start to main-end, the wrapping to additional lines is done along the cross direction, from cross-start to cross-end.
The cross-axis is perpendicular to the main-axis.
As we see in Figure 2-9, when we have horizontal rows of flex items, the
cross-axis is vertical. Flex lines are added in the direction of the
cross-axis. In these examples, with flex-flow: row wrap
and
flex-flow: row-reverse wrap
set on horizontal languages, new flex
lines are added below preceding flex lines.
The cross-size is the opposite of main-size, being height for row
and row-reverse
and width for column
and column-reverse
in both
RTL and LTR languages. Flex lines are filled with items and placed into
the container, with lines added starting on the cross-start side of
the flex container and going toward the cross-end side.
The wrap-reverse
value inverts the direction of the cross-axis.
Normally for flex-direction
of row
and row-reverse
, the
cross-axis goes from top to bottom, with the cross-start on top and
cross-end on the bottom, as shown in Figure 2-9. When flex-wrap
is set to wrap-reverse
, the
cross-start and cross-end directions are swapped, with the
cross-start on the bottom, cross-end on top, and the cross-axis
going from bottom to top, as shown in Figure 2-7. Additional flex lines get added on top of, or above, the
previous line.
If the flex-direction
is set to column
or column-reverse
, by
default the cross-axis goes from left to right in left-to-right
languages, with new flex lines being added to the right of previous
lines. As shown in Figure 2-10, when flex-wrap
is set to wrap-reverse
,
the cross-axis is inverted, with cross-start being on the right,
cross-end being on the left, the cross-axis going from right to
left, with additional flex lines being added to the left of the
previously drawn line.
We added align-items: flex-start
(see “The align-items
Property”)
and align-content: flex-start
(see “The align-content
Property”) to the flex container in Figures 2-9 and 2-10 to enunciate the height and directions of the flex lines. These properties are covered in the following sections.
The flex-wrap
property seemed fairly intuitive when it was first described. It turned out to be a bit more complex than it might have
originally seemed. You may never implement reversed wrapping in a right-to-left language, but this is a “Definitive Guide.” Now that we have a better understanding of the “cross-” dimensions, let’s dig deeper into the flex-wrap
property.
The default value of nowrap
prevents wrapping, so the cross-
directions just discussed aren’t relevant when there is no chance of a
second flex line. When additional lines are possible—when flex-wrap
is set to wrap
or wrap-reverse
—those lines will be added in the
cross direction, which is perpendicular to the main-axis. The first
line starts at the cross-start with additional lines being added on
the cross-end side.
The wrap-reverse
value inverts the direction of the cross-axis.
Normally for flex-direction
of row
and row-reverse
, the
cross-axis goes from top to bottom, with the cross-start on top and
cross-end on the bottom. When flex-wrap
is wrap-reverse
, the
cross-start and cross-end directions are swapped, with the
cross-start on the bottom, cross-end on top, and the cross-axis
going from bottom to top. Additional flex lines get added on top of the
previous line.
You can invert the direction of the cross-axis, adding new lines on
top or to the left of previous lines by including
flex-wrap: wrap-reverse
. In Figures 2-9, 2-10, and 2-11, the last example in each is wrap-reverse
. You’ll notice the new line starts at the main-start, but is added in the inverse direction of the cross-axis
set by the flex-direction
property.
In Figure 2-11, the same flex-wrap
values are repeated, but with a
flex-direction: column
property value instead of row
. In this case,
the flex items are laid out along the vertical axis. Just as with the
first example in Figure 2-7, if wrapping is not enabled by the
flex-wrap
property, either because flex-wrap: nowrap
is explicitly
set on the container, or if the property is omitted and it defaults to
nowrap
, no new flex lines will be added, even if that means the flex items are drawn beyond the bounding box of the flex container.
With column
, just like with row
, if the flex items don’t fit within
the flex container’s main dimension, they’ll overflow the flex container, unless
explicitly forced with min-width: 0
or similar, in which case they
shrink to fit, though flex items will not shrink to smaller than their
border, padding and margins combined.
When "flex-direction: column; flex-wrap: wrap;
" or
"flex-flow: column wrap;
" is set on a flex container, the flex item children are aligned along the main-axis. In LTR modes, the first flex item is placed in the top left, which is the
main-start and cross-start respectively. If there is room, the next
item will be placed below it, along the main-axis. If there isn’t
enough room, the flex container will wrap the flex items onto new lines.
The next flex item will be put on a new line, which in this case is a
vertical line to the right of the previous line, as can be observed in
the flex-flow: column wrap
example, the top-right example in
Figure 2-11.
Here, the flex items have wrapped onto 3 lines. The flex items are wrapping onto new lines as the height: 440px
was set on the parent. Including a height forces the creation of new flex lines when the next flex item will not fit onto the current flex line.
As shown in the bottom-right example in Figure 2-11, when we include "flex-direction: column; flex-wrap: wrap-reverse;
" or "flex-flow: column wrap-reverse;
" and the main-axis is the vertical axis, flex items are added below the previous flex item, if they can fit within the parent container. Because of the wrap-reverse
, the cross-axis is reversed meaning new lines are added in the opposite direction of the writing mode. As shown in this example and in Figure 2-10, with wrap-reverse
, columns are laid out right to left, instead of left to right. The first column of flex items is on the leftmost side of the parent flex container. Any additional required columns will be added to the left of the previous column. Again, we’re assuming a left-to-right default writing mode for all the examples.
In this example, the flex items are different heights based on their
content. When divided across three lines, the last line is not filled.
Since subsequent lines are being added to the left of previous lines,
the empty space, if there is any, will be on the bottom left (assuming justify-content
, described next, is set or defaults to flex-start
).
As you can see, flex-direction
and flex-wrap
have great impact on
your layout and on each other. Because it’s generally important to set
both if you’re going to set either, we are provided with the flex-flow
property, which is simply shorthand for flex-direction
and
flex-wrap
.
Similar to the display examples in Figure 1-6, in the flex-flow
example in Figure 2-1, the flex items grew to fill the cross dimension of the flex line they
were on. Because they default to nowrap
, all the flex items will
be on a single line. With other flex properties defaulting to their default values, the flex items are stretched filling the container.
In the flex-wrap
example in Figure 2-7, we
had two flex lines. All the flex items in a single line were the same
height, but the individual flex lines were not of the same height: instead all
the flex items were as tall as the tallest flex item within that
same flex line.
By default, all flex items will appear to be the same height. We
controlled this in Figures 2-9 and 2-10 in order to highlight the how flex lines are drawn. This stretching (or overwriting of that stretching) is caused by the stretch
default value of the justify-content
property, described in the next section.
In those examples, you’ll note the second row is not as wide as the flex
container. When flex items are allowed to wrap onto multiple lines, by
default all the items on one line will have the same cross dimension,
which means all the items in a flex line of row
and row-reverse
will
be the same height and all the items in a flex line of column
or
column-reverse
will have the same width.
Figure 2-12 is an example in which flex-flow: column-reverse wrap-reverse
is set. This means the main-axis is vertical, going bottom to top with a horizontal cross-axis going from right to left. Notice the extra
space on the top left. New flex items get placed to the top of the
previous ones, with new lines wrapping to the left of the
previously filled row. By default, no matter the values of flex-flow
,
the empty space, if there is any, will be in the direction of main-end
and cross-end. There are other flex properties that will allow us to
alter that. Let’s look into those.
In Chapter 1 we learned how to use display
property values
flex
and inline-flex
to instantiate a flex container and turn the
container’s children into flex items. We now understand how
flex-direction
sets the direction of the flex items within the flex
container, setting the main-axis and cross-axis directions and how flex-wrap
can be used to enable multiline flex containers and even invert the cross-axis direction. We also know how to
use flex-flow
to set both flex-direction
and flex-wrap
.
While we learned how to use flex-flow
properties to handle multiline flex containers, we haven’t really discussed what happens to the extra
space when the flex items don’t fill a row or column, and what happens
to the extra space when not all the flex items have the same cross
dimension.
Thus far in our examples, when the flex items did not fill the flex container, the flex items have been grouped toward the main-start on the main-axis. We can control that. Flex items can be flush against the main-end instead. They can be centered. We can even space the flex items out evenly across the main-axis.
The flex layout specification provides us with flex container properties
to control the distribution of space: in addition to display
and
flex-flow
, the CSS Flexible Box Layout Module Level 1 properties
applied to flex containers include the justify-content
,
align-content
, and align-items
properties.
The justify-content
property controls how flex items in a flex line
are distributed along the main-axis. The align-content
defines how
flex lines are distributed along the cross-axis of the flex container.
The align-items
property defines how the flex items are distributed
along the cross-axis of each of those flex lines.
The properties applied to individual flex items are discussed in Chapter 3.
justify-content
PropertyThe justify-content
property enables us to define how flex items will
be distributed along the main-axis of the flex container.
The distribution of elements along the main axis of the container is
controlled with the justify-content
property. If you remember from
Figure 1-6, when an
element is converted to a flex container, the flex items, by default,
were grouped together at the main-start.
The justify-content
defines how space is distributed. There are five
values for the justify-content
property: flex-start
, the
default value, and flex-end
, center
, space-between
, and
space-around
.
As shown in Figure 2-13, by default or with justify-content: flex-start
explicitly set, flex items are laid out flush against main-start. With flex-end
, flex items are justified toward main-end. center
groups the items flush against each other centered in the middle of the main-dimension along the main axis. The space-between
value puts the first flex item on a flex line flush with main-start and the last flex item in each flex line flush with main-end, and then puts an equal amount of space between every pair of adjacent flex items. space-around
evenly distributes the flex items, as if there were noncollapsing margins of equal size around each item. More examples of the five justify-content
values are demonstrated in Figure 2-14.
As the justify-content
property is applied to the flex container, the
flex items will be distributed in the same manner whether they’re on a
filled first flex line or on a partially filled subsequent flex line in
a wrapping flex container.
Those are the basics of justify-content
property. But, of course,
there’s more to the property and each of the values. What happens if
there is only one flex item on a line? If the writing mode is right to
left? If flex-flow: nowrap
is set and the flex items overflow the flex
container?
If nowrap
is set, and the items overflow the line, the
justify-content
property helps control the appearance of the line
overflow. Figure 2-14 illustrates
what happens with the different justify-content
when
flex-flow: column nowrap
is set and the flex items heights are taller
than the container’s main dimension.
Let’s take a look at the five values.
Setting justify-content: flex-start
(Figure 2-15) explicitly sets the default
behavior of grouping the flex items toward main-start, placing the
first flex item of each flex line flush against the main-start side.
Each subsequent flex item then gets placed flush with the preceding flex
item’s main-end side, until the end of the flex line is reached if
wrapping is set. The location of the main-start side depends on the
flex direction and writing mode, which is explained in “Understanding axes”.
If there isn’t enough room for all the items, and nowrap
is the default or expressly set, the items will overflow on the main-end edge, as shown in the third example of Figure 2-15.
Setting justify-content: flex-end
puts the last flex on a line flush
against the main-end with each preceding flex item being placed flush
with the subsequent item. In this case, if the items aren’t allowed to
wrap, and if there isn’t enough room for all the items, the items will
overflow on the main-start edge, as shown in the third example of
Figure 2-16. Any extra space on a flex line will be on the main-start side.
Setting justify-content: center
will pack all the items together, flush against each other at the center of each flex line instead
of at the main-start or main-end. If there isn’t enough room for all
the items and they aren’t allowed to wrap, the items will overflow
evenly on both the main-start and main-end edges, as shown in the third example in Figure 2-17. If the flex items
wrap onto multiple lines, each line will have centered flex items, with
extra space being on the main-start and main-end edges.
Setting justify-content: space-between
puts the first flex item flush
with main-start and the last flex item on the line flush with
main-end, and then puts an even amount of space around each flex item,
until the flex line is filled. Then it repeats the process with any flex
items that are wrapped onto additional flex lines. If there are three flex items, there will be the same amount of space between the first and second items as between the second and third, but there will be no extra empty space between the edge of the container and the first item and the opposite edge of the container and the outer edge of the last item, as shown in the second example in Figure 2-18. With space-between
, the first item is flush with main-start
, which is important to remember when you only have one flex item or when your flex items overflow the flex container in a nowrap
scenario. This means, if there is only one flex item, it will be flush with main-start, not centered, which seems counterintuitive to many at first.
With justify-content: space-between
, the first flex item is placed
flush with main-start, so, if there is only one item, or if the flex
items aren’t allowed to wrap and overflow the flex container, the
appearance will be the same as flex-start
—the comparison can be
seen in Figure 2-14—which may
be less than intuitive.
With justify-content: space-between
the space between any two items on
a flex line will be equal but won’t necessarily be the same across
flex lines. When set to allow wrapping, on the last flex line, the
first flex item of that last line is flush against main-start, the
last if there are two or more on that line will be against main-end,
with equal space between adjacent pairs of flex items. As shown in the
last example of Figure 2-18, A and G, the first items on each flex line, are flush against main-start. F and I, the last items on each line, are flush against main-end. The flex items are evenly distributed with the spacing between any two adjacent items being the same on each of the lines, but the space between flex items on the first line is narrower than the space between flex items on the second line.
Setting justify-content: space-around
evenly distributes the extra
space on the line around each of the flex items, as if there were
noncollapsing margins of equal size around each element on the
main-dimension sides. So there will be twice as much space between the
first and second item as there is between main-start and the first
item and main-end and the last item, as shown in Figure 2-19.
If nowrap
is set, and there isn’t enough room on the flex container’s
main-direction for all the flex items, the flex items will overflow
equally on both sides, similar to setting center
, as shown in the
third example in Figure 2-14.
If the flex items wrap onto multiple lines, the space around each flex item is based on the available space on each flex line. While the space around each element on a flex line with be the same, it might differ between lines, as shown in the last examples in Figure 2-19. The spaces between A and B and between G and H are twice the width of the spaces between the main-start edge and A and the edge and G.
With the margin added to the flex items to make the examples less
hideous, this may be difficult to see. Comparing margin-free examples of center
, space-around
, and space-between
might be more helpful.
Figure 2-20 demonstrates the difference between the spacing concepts of center
, space-around
, and space-between
. When set to center
, the flex items are grouped flush against each other in the center of the main-dimension.
With space-between
, you’ll note the first and last flex items
on both flex lines abut main-start and main-end, respectively. The
space between each of the flex items on the first flex line is 24 px: the
120 px of free space is divided into 5 equal gaps placed between the 6
flex items. The space between each flex item on the second flex line is 150 px: the 300 px of free space is divided into two and placed between
the three flex items.
With space-around
, the flex items do not necessarily abut the edges:
if there is any extra space, it is put around every flex item. In all three examples in Figure 2-20, there are 120 px of free space and 6 items on
the first line and 300 px of free space and 3 flex items on the second
flex line. On the first line of the space-around
example, the 120 px of free space are divided among
the two sides of the six items, placing 10 px on the left and right of
each item. This way, there are 10 px of space between main-start and
the first item and the last item and main-end, and twice that, or
20 px, between each adjacent flex item. On the second flex line, the
300 px of free space is divided between the two sides of the 3 flex
items, putting 50 px on the outer edges and twice that, or 100 px, between adjacent items.
It may also help to compare the overflow edge and edges of the five
justify-content
properties with a different main-axis. In Figure 2-21, all flex containers have the following CSS:
container
{
display
:
inline-flex
;
flex-flow
:
nowrap
column
-
reverse
;
height
:
200px
;
}
The layout when there is negative free space should now be more intuitive:
flex-start
and space-between
overflow at main-end.
flex-end
overflows at main-start.
center
and space-around
overflow on both ends.
With justify-content: space-between
, the first flex item is placed
flush with main-start. If the flex items don’t fit on a line within
the flex container, they will overflow on the main-end side, as shown
in Figure 2-21. With justify-content: space-around
, if there is only
one flex item on a line, or more items than a nonwrapping flex line can
hold, it will be centered. If there are multiple items, the outer spaces
are half the size of the spaces between adjacent item.
In our examples, we’ve also prevented the flex items from shrinking, a
default feature we haven’t yet covered. The height: 200px
limited the
height of the container ensuring the flex items could overflow their
container. The display: inline-flex
declaration provided for a flex
container that was only as wide as its content. Had we included wrap
instead of nowrap
, the container would have doubled in width, allowing
for two columns or flex lines.
justify-content
ExamplesWe took advantage of the default value in
Figure 1-7, creating a left-aligned navigation bar. By changing the default value to justify-content: flex-end
we can right align the navigation bar, as shown in Figure 2-22.
For right-to-left writing modes, we don’t have to alter the CSS. As shown in Figure 2-21, and as discussed in Chapter 1, flex items are grouped toward main-start. In English, main-start is on the left. For Hebrew, main-start is on the right.
By simply adding a single line to our CSS, we altered the appearance of our navigation example, making the English version flush to the right and the Hebrew translation flush to the left:
nav
{
display
:
flex
;
justify-content
:
flex
-
end
;
border-bottom
:
1px
solid
#ccc
;
}
We could have centered that navigation, as shown in Figure 2-23:
nav
{
display
:
flex
;
justify-content
:
center
;
border-bottom
:
1px
solid
#ccc
;
}
align-items
PropertyWhereas the justify-content
defines how flex items are aligned along
the flex container’s main-axis, the align-items
property defines how
flex items are aligned along its flex line’s cross-axis.
With the align-items
property, you can align flex items to the start,
end, or center of the cross-axis of their flex line. Set on the
container element, align-items
is similar to justify-content
but in
the perpendicular direction, setting the cross-axis alignment for all
flex items, including anonymous flex items, within the flex container
(we’ll learn how to override this value for individual flex items when
we cover align-self
(“The align-self
Property”).
With align-items
, you can set all the items to have their cross-axis
flush against the cross-start or cross-end of their flex line, or
stretched flush to both. Or you can center all the flex items in the
middle of the flex line. Stretched across the entire cross-axis is the
default and is what we have seen in most of the examples thus far. There
are five values, including flex-start
, flex-end
, center
,
baseline
, and the default stretch
, as shown in Figure 2-24.
While align-items
sets the alignment for all the flex items within a
container, the align-self
property
enables overriding the alignment for individual flex items.
In Figure 2-24, you’ll note how the flex items either hug the cross-start or cross-end side of the flex container, are centered, or stretch to hug both, with the possible exception of baseline
.
The general idea is flex-start
places the flex items on the
cross-start, flex-end
puts them on the cross-end edge, center
centers them on the cross-axis, the default stretch
stretches the
flex item from cross-start to cross-end, and baseline
looks
similar to flex-start
but actually lines up the baselines of the flex
items and then pushes the group of flex items toward cross-start.
With baseline
, the flex items’ baselines are aligned: the flex item
that has the greatest distance between its baseline and its
cross-start side will be flush against the cross-start edge of the
line. That’s the general idea—and explains nonwrapping flex
containers pretty well—but there’s more to it than that.
In the multiline align-items
figures that follow, the following code
has been included:
flex-container
{
display
:
inline-flex
;
flex-flow
:
row
wrap
;
border
:
1px
dashed
;
padding
:
10px
;
}
flex-item
{
border
:
1px
solid
;
margin
:
0
10px
;
}
.C
,
.H
{
margin-top
:
10px
;
}
.D
,
.I
{
margin-top
:
20px
;
}
.J
{
font-size
:
3rem
;
}
For each flex line in Figures 2-25, 2-27, 2-28, 2-29 and
2-30, the red line is cross-start and the blue is cross-end. The lines appear purple when a new flex line abuts the previous flex line. C, H, D, and I have different values for top and bottom margins. We’ve added a bit of margin to the sides of all the flex items to make the figures more legible, which doesn’t affect the impact of the align-items
property. J has the font size increased, increasing the line height. This will come into play when we discuss the baseline
value.
The default is align-items: stretch
, as shown in Figure 2-25.
align-items: stretch
The default and the explicitly set align-items: stretch
stretches all
the stretchable flex items in a line to be as tall or wide as the
tallest or widest flex item on the line. What does “stretchable” mean?
While by default all the flex items will stretch to take up 100% of the
cross-size, if min-height
, min-width
, max-height
, max-width
,
width
, or height
are set, those properties will take precedence.
If set or defaulting to stretch
, the flex items’ cross-start will be
flush with the flex line’s cross-start, and the flex items’
cross-end will be flush with the flex line’s cross-end. The flex
item with the largest cross-size will remain its default size, and
the other flex items will stretch, growing to the size of that largest
flex item on that same flex line. The cross-size of the flex items includes the margins, as demonstrated by items C, D, H, and I.
The margins in the cross direction have an impact. In Figure 2-26, we’ve
added 30 px of margin to the cross-start edge of C
of flex item and
40 px to the cross-end edge of the D
. You’ll note A
, B
, and
E
are flush against both cross edges, but the C
and D
appear
pushed in. This is due to the margins: their outer margins are flush
against cross-start and cross-end.
The size of the stretched flex item includes the margins on the cross-start and cross-end sides: it is the outer edge of the flex items’ margin that will be flush with cross-start and cross-end. This is the reason C, D, H, and I may appear smaller than the other flex items on their flex lines. They’re not. The outer edge of the top and bottom margins are flush with the cross-start and cross-end of the flex lines they occupy. Those flex lines are, in turn, as tall as the tallest item on the line (or as wide as the widest item when the cross dimension is horizontal).
Flex lines are only as tall as they need to be to contain their flex
containers. In the five align-items
figures, the line height of the flex line containing only K is much smaller than the line containing E, which is smaller than the line containing F. K has only one line of text, and no margin, whereas E has five lines of text. The second line, which includes F with six lines of text, making it even taller than the first line.
align-items: flex-start
The flex-start
value lines up each flex items’ cross-start edge
flush against the cross-start edge of their flex line. The flex item’s
cross-start edge is on the outside of the margin: if a flex item has a
margin that is greater than 0, flex item will not appear flush with the
flex line’s cross-start edge, as seen in flex item C, D, H, and I, in
Figure 2-27.
align-items: flex-end
Setting align-items: flex-end
will align the cross-end edge of all
the flex items along the cross-end edge of the line they are in as
shown in Figure 2-28. In these examples, none of the flex items have a
bottom margin greater than 0 px, so unlike our other examples, this
example does not look jagged.
align-items: center
As shown in Figure 2-29, setting align-items: center
will center the flex items’ cross-size along the middle point of the cross-axis of the line. The center is the midpoint between the outer edges of the margin, remembering flex item margins do not collapse. Because the cross-edge margins for C, D, H, and I are not symmetrical, the flex items do not appear centered along the cross-axis, even though they are. In LTR and RTL languages, in the case of flex-direction: row
and row-reverse
, the midpoint is the midpoint of the top margin, top border, top-padding, content or height, bottom padding, bottom border, and bottom margin. For flex-direction: column
, and column-reverse
, the midpoint is the midpoint of the left margin, left border, left-padding, content or width, right padding, right border, and right margin.
Flex items may overflow their parent flex container along in the main-axis if
nowrap
is set and the main-size is constrained. Similarly, if the
flex container’s cross-size is constrained, the contents may overflow
the flex container’s cross-start and/or cross-end edge. The
direction of the overflow is not determined by the align-items
property, but rather by the align-content
property, discussed next.
The align-items
aligns the flex items within the flex line and does
not directly impact the overflow direction of the flex items within in
the container.
align-items: baseline
The baseline
value may be a little more confusing. With baseline
,
the flex items in each line are all aligned at their baselines, which is
basically the bottom of the first line of text, if there is any. The
flex item on each flex line with the biggest distance between its
baseline and its cross-start margin edge is placed flush against the
cross-start edge of the line, with all other flex items’ baselines
lined up with the baseline of that flex item.
Instead of aligning the cross-start of each flex item flush against the cross-start of each line, the flex items are aligned so their baselines align. In many implementations, baseline
will look like flex-start
, but will differ from the flex-start
value if the flex items have different margins, padding, or border on the cross-start side, or if the first lines of content of the flex items don’t all have the same line heights.
You’ll notice that A, B, C, D, and E all seem aligned at top. What you may have missed is that they are not flush to the top—they are not flush against the red line. D has a top margin of 20 px. The outer edge of D’s top margin is flush against the cross-start of the flex line, which is flush with the top of the flex container. As previously noted, the distance between the cross-start line and baseline is determined by the item on the line that has the biggest distance between its outer margin on its cross-start side and its baseline. In the Figure 2-30 baseline example, the items with the largest distance on their own flex lines are D, J, and K. These items’ outer margins on the cross-start side are placed flush against the cross-start edge of their respective lines, and the other items in the same flex lines have their baseline lined up with D, J, and K’s baseline.
As A, B, C, D, and E all have the same line height, and D has the tallest
top margin, they are aligned with D’s baseline, and D’s top margin is
flush against the cross-start edge. When it comes to the first line,
because they all have the same line height, border, and padding, it looks
like they’re lined up like flex-start
, but they are actually a little
lower, accommodating for D’s top margin. The green line denotes where
the baseline is.
In all the examples, we increased the font size for J to 3rem
to
create a flex item that had a different baseline from all the other flex
items. Only when align-items: baseline
is set does this impact the
flex item alignment within the flex line, as shown in Figure 2-30. When
align-items: baseline
is set, the baselines of all the items in the
second flex line are aligned with J’s baseline, as J is the flex item
with the greatest space between the outer top margin and the bottom of
the first line of text. Again, the green line denotes the approximate
location of the baseline.
The align-items
property is set on the flex container and impacts all
of the flex items within that flex container. If you want to change the
alignment of one or more flex items, but not all, you can include the
align-self
property on the flex items you would like to align
differently. The align-self
takes the same values as align-items
,
and is discussed in Chapter 3.
You cannot override the alignment for anonymous flex items (nonempty
text node children of flex containers): their align-self
always
matches the value of align-items
of their parent flex container.
In the align-items
examples, the flex container’s cross-size was as
tall as it needed to be. No height
was declared on the container, so it defaulted to height: auto
. Because of this, the flex container grew to fit the content. You may have noticed the example flex containers were all the same height, and the flex line heights were the same across all examples.
Had the cross-size, in this case the height, been set to a specific size, there may have been extra space at cross-end, or not enough space to fit the content. Flexbox allows us to control the alignment of flex lines with the align-content
property. The align-content
property is the last property we need to focus on that applies to the flex container (versus the flex items). The align-content
property only impacts flex line alignment in multiline flex containers.
align-content
PropertyThe align-content
property aligns a flex container’s lines within a
flex container that has extra space in the cross-axis direction, and dictates which direction will have overflow when there is not enough room to fit the flex lines.
The align-content
property allows us to dictate how any extra cross-direction space in a flex container is distributed between and around flex lines. This is different from the previously discussed align-items
property which dictates flex item positioning within each flex line.
The align-content
property determines how flex lines are aligned
within a multi-line flex container. When there is extra space in the
cross-axis direction, you can dictate whether the lines are grouped at
cross-start, cross-end, centered, or stretched to take up all the
available space, or distributed across the flex container with the extra
space distributed between or around the flex lines.
Think of align-content
as similar to how justify-content
aligns
individual items along the main-axis of the flex container, but for
flex lines across the cross-axis of the container. This property only
applies to multiline flex containers, having no effect on nonwrapping
and otherwise single-line flex containers.
Figure 2-31 demonstrates the six possible values of the align-content
property.
We’ve used the following CSS as the base for the preceding six examples, with no margins on the flex items:
flex-container
{
display
:
flex
;
flex-flow
:
row
wrap
;
align-items
:
flex
-
start
;
border
:
1px
dashed
;
height
:
480px
;
}
In Figure 2-31, each flex container has three flex lines. With a height of 480 px, the flex container is taller than the default combined heights of the 3 flex lines. The tallest items in each line—E, F, and K—are 150 px, 180 px, and 30 px, respectively, for a combined total of 360 px. Each flex container has an extra 120 px of free space in the cross-size direction. The cross-start side of each flex line is denoted with a red line, the cross-end side with a blue line; they may appear purple when they overlap. With five of the align-items
values, the free space is distributed outside of the flex lines, as is more apparent in Figure 2-32. With stretch
, the extra space is evenly distributed between all the flex lines, increasing their cross-size.
Figure 2-32 reiterates the six possible values of the align-content
property, with align-items: stretch
and flex: 1
set to allow the flex items to grow to take up their entire lines to make the impact of the align-content
values more apparent (and generally, to be less of an eyesore):
flex-container
{
display
:
flex
;
flex-flow
:
row
wrap
;
align-items
:
stretch
;
border
:
1px
dashed
;
height
:
480px
;
}
flex-items
{
flex
:
1
;
}
Just like in the previous example, with a height of 480 px, and with flex lines 150 px, 180 px, and 30 px tall, we have 120 px of free space along the cross-direction distributed differently depending on the value of the align-content
property:
480 - (150 + 180 + 30) = 120
As shown in the first examples in both Figures 2-31 and 2-32, with flex-start
the 120 px is on the cross-end side. With flex-end
the extra 120 px of available space is at the cross-start side. With
center
, the lines are centered, with 60 px of extra space at both the
cross-start and cross-end sides, as shown in the top-right example
of both figures. With space-between
, there is 60 px between adjacent
pairs of flex lines, as shown in the bottom-left examples. With
space-around
, the space is evenly distributed around each line: the
120 px is distributed evenly, putting 20 px of non-collapsed space on the
cross-start and cross-end sides of each flex line, so there are 20 px
of extra space at the cross-start and cross-end sides of the flex
container and 40 px of space between adjacent flex lines.
The stretch
value is different: with stretch
the lines stretch with
the extra space evenly distributed among the flex lines rather than
between them. In this case, 40 px was added to each of the flex lines.
You’ll note in the sixth example in both Figures 2-31 and 2-32, there is no area within the container that is not occupied by a flex line. Stretch is the default value, as you likely want to fill all the
available space.
If there isn’t enough room for all the lines, they will overflow at cross-start, cross-end, or both, depending on the value of the align-content
property, as shown in Figure 2-33.
Figure 2-33 shows the size align-content
values when the flex lines overflow their parent flex container. The only difference in the CSS between this and Figure 2-31 is the height of the flex container. We defined height: 240px
to create flex containers not tall enough to encompass all their child flex items:
flex-container
{
display
:
flex
;
flex-flow
:
row
wrap
;
align-items
:
flex
-
start
;
border
:
1px
dashed
;
height
:
240px
;
}
If the flex lines overflow the flex container, flex-start
,
space-between
, and stretch
overflow the cross-end side, stretch
and center
overflow evenly both the cross-end and cross-start
sides, and only flex-end
overflows only on the cross-start side.
align-content: flex-start
With align-content: flex-start
, the cross-start edge of the first line of flex items will be flush against cross-start, with each subsequent line placed flush against the preceding line, as shown in Figure 2-34.
In other words, all the flex lines will be grouped together at the cross-start edge of the flex container. Note all the extra space (the extra 120 px in this case) is at cross-end. Remembering the cross-direction is inverted with flex-direction: wrap-reverse
(see “The flex-direction
Property”), as shown in Figure 2-15. If there isn’t enough room for all the lines, they will overflow at cross-end.
align-content: flex-end
With align-content: flex-end
, the cross-end edge of the last line of
flex items is placed flush with the cross-end edge of the flex
container, and each preceding line is placed flush with the subsequent
line, leaving all the extra whitespace at cross-start. In other
words, all the flex lines will be grouped flush against the cross-end
edge of the flex container. Should the content overflow the flex
container, it will do so on cross-start side.
align-content: center
Declaring align-content: center
groups the flex lines together, so
they are flush against each other, just like they are grouped together
with flex-start
and flex-end
, but in the center of the flex
container.
center
, flex-start
, and flex-end
all have each line’s cross-end
being flush against the subsequent line’s cross-start. Instead of all
the lines being grouped at the container cross-start as in
flex-start
or at cross-end as in flex-end
, with
align-content: center
the group of lines is centered between the flex
container’s cross-start and cross-end, with equal amounts of empty
space—60 px on each side in this case—between the cross-start
edge of the flex container and the cross-start edge of the first flex
line, and between the cross-end edge of the flex container and the
cross-end edge of the last flex line, as shown in the top-right
example in 2-31 and 2-32. If the flex items overflow the flex container, the lines will overflow equally in both directions past the cross-start and cross-end edges of the container, as shown in the center-left example in Figure 2-33.
align-content: space-between
When align-content: space-between
is set, the flex lines are evenly
distributed in the flex container. The even distribution is based on
the available space, not the size of the lines; the extra space is divided equally among the lines, not proportionally.
If we remember back to justify-content: space-between
, the first flex
item is flush against main-start. The second flex item, if there is
one, is flush against main-end. The rest of the flex items, if there
are any, are spread out with equal amounts of the free space distributed
between the flex items. This is similar to how
align-content: space-between
works. If there is more than one flex
line, the first line will be flush against the container’s
cross-start, the last line will be flush against the container’s
cross-end, and the available extra space is distributed evenly between
the additional lines, if there are any. The extra space is distributed
evenly, not proportionally. The space between any two flex lines within
the flex container is equal, even if the cross-sizes of the multiple
flex lines differ.
Only flex containers with multiple lines can have free space in the
cross-axis for lines to be aligned in. If there is only one line, the
align-content
property will not impact the distribution of the
content. In flex containers with a single line of flex items, the lone
line stretches to fill all of the available space.
The middle line, if there is an odd number of lines, is not necessarily centered, as the lines don’t necessarily all have equivalent cross dimensions. Rather, the spacing between any two adjacent lines is the same: there is the same amount of space between the first and second line as there is between any other adjacent flex line, as shown in the bottom left example in Figure 2-32. In this case, we have 120 px total of free space, which gets divided equally, with half, or 60 px, between the first and second flex lines, and 60 px between the second and third flex lines:
120px / 2 = 60px
If there isn’t enough space to encompass all the flex lines, the
free space is negative and align-content: space-between
appearance is
identical to flex-start
, with the overflow on the cross-end side.
align-content: space around
The space-around
value distributes the lines within a multiline flex container
evenly, as if all the flex lines had equal, noncollapsing margins on
both the cross-start and cross-end sides. Because there is an equal
distribution of the extra available space around each line, the space
between the edges of the container and the first and last flex lines is
half the size of the distance between any two flex lines. The
distribution of the extra space is shown in Figure 2-35.
In this case we have 120 px of free space distributed to 3 flex lines, with half of each flex lines extra space being added to the cross-start edge and half being added to the cross-end edge:
(120px / 3 lines) / 2 sides = 20px per side
In this example, there is 20 px on the outer sides of the flex lines, with twice that between any two adjacent flex lines. There is 20 px between the cross-start edge and the first line, 20 px between the cross-end edge and the last line, and 40 px (twice 20 px) between the first and second flex lines and the second and third flex lines.
If there isn’t enough room for the flex lines and they overflow the flex
container, the free space is negative, and align-content: space-around
value appears identical to center
, with the overflow evenly distributed
between the cross-start and cross-end sides.
align-content: stretch
Omitting the align-content
property, or setting it explicitly to the
align-content: stretch
default value, makes the lines stretch to
take up all the extra available space.
If you take a close look at Figure 2-32, you’ll note that stretch
and
space-between
are actually quite different. In space-between
, the
extra space is distributed between the lines. In stretch
, the extra
space is divided into the number of lines and added to the lines. The
original lines were 150 px, 180 px, and 30 px tall, respectively. When set to
stretch, the extra 120 px is added to the lines in equal amounts. As we
have three flex lines and 120 px of extra space, each flex line grows by
40 px, giving us flex lines that are 190 px, 220 px, and 70 px, respectively, as shown in Figure 2-36.
That extra space, in this example, appears at the cross-end of each
individual line since we included align-items: flex-start
. Had we
used align-items: flex-end
instead, the extra space in each line
would have been apparent at the individual lines’ flex-start.
If there isn’t enough space to fit all the flex lines, the lines will
behave as if set to flex-start
, with the first flex line flush against
the cross-start edge of the flex container.
We have been taking a look at properties of the flex container. It’s time to take a look at properties directly applied to flex items.
1 Horizontal layout is incorrect for Mongolian. Because of this exception it’s not really a “preference.”