This documents the use of some CSS flexbox layout properties applied to a container element, the "flexbox parent", and the child elements it contains, the "flexbox children":
display: flex
flex-direction
justify-content
align-items
order
self-align
flex-basis
flex-grow
flex-shrink
flex
flex-wrap
This deals with how flexbox properties may be very simply used to arrange a primary navigation element.
Focusing on a single piece of an overall webpage layout should help keep this
example simple and easy to understand. Primary site navigations will likely be
the most common ways you will use flexbox, so a very common approach to laying
out navigation will serve as our example here, with ul
inside of a nav
element as the flexbox parent and several li
elements as the children of that
flexbox parent.
<nav>
<ul>
<li><a href="#">First</a></li>
<li><a href="#">Second</a></li>
<li><a href="#">Third</a></li>
</ul>
</nav>
Setting display
to flex
makes your flex container's children behave as
block items, and inline-flex
makes them behave as inline items. The default
value for flex-direction
is row
, which arranges these block items
horizontally, but it can be set to column
to arrange them vertically. You
can also set flex-direction
to column-reverse
or row-reverse
to arrange
them in the reverse of the order in which they are specified in your HTML in a
column (vertical) or row (horizontal) arrangement, respectively.
Some browsers require prefixed names for some flex properties. An automatic prefixer tool like post-css can be used to handle the complexity of any cross-browser compatibility issues for you.
nav ul {
list-style: none;
display: flex;
flex-direction: column-reverse;
}
This deals with how the order
property of flexbox children can be used to
arrange them on a page. This is probably most useful for two purposes:
changing the arrangement order dynamically within a page, and changing the
arrangement order of ordered list elements.
We will use an example with a body
element as a flexbox parent. That parent
element will have four immediate children: header
, nav
, main
, and
footer
. The ul
element within nav
will be another (nested) flexbox
parent element, with several li
children, just for the sake of a simple
nesting example to illustrate a common layout pattern, though the focus of this
section is on the use of the order
property for the body
flexbox parent's
children.
<body>
<header>Header</header>
<nav>
<ul>
<li><a href="#">First</a></li>
<li><a href="#">Second</a></li>
<li><a href="#">Third</a></li>
</ul>
</nav>
<main>Content</main>
<footer>Footer</footer>
</body>
As indicated in the "Basic Flexbox" section above, using the default
flex-direction
property means arranging the children as a row, horizontally
across the screen. In the case of content elements, this typically means
creating a visually columnar appearance to content blocks on the screen.
The order
property defaults to zero. When multiple children of the flexbox
parent have the same order value, they simply appear in the order they are
specified in your HTML. Order properties are set in the child elements, and
when order values are compared between flexbox children the higher values are
moved after the lower values. Negative values can be used, which results in
zero (the default value) being treated as the center around which other values
are arranged, with negative values determining how far before zero order
elements the negative value element is placed, and positive values determining
how far after.
body {
display: flex;
flex-direction: column;
}
header {
order: -1;
}
nav {
order: 1;
}
nav ul {
list-style: none;
display: flex;
}
footer {
order: 1;
}
Giving header
an order of negative one guarantees it comes before all other
children of the body
flexbox parent in this example, because all other
elements have the default value of zero or a positive number value. Setting
nav
to one pushes it to the bottom because no other flexbox child element has
a higher positive number value; setting footer
to one as well also pushes it
to the bottom, and because both of them have an order
property value of one
they are arranged relative to each other in the same order they are arranged in
the HTML.
This deals with alignment of flexbox child elements, using the common pattern of multiple articles of different lengths in a single page, a layout characteristic common to blogs.
<body>
<div>
<h2>First Post!</h2>
<p>This is an uninteresting article with two paragraph elements.</p>
<p>The second paragraph element is more boring than the first.</p>
</div>
<div>
<h2>Second Post</p>
<p>This is a very short second article.</p>
</div>
<div id="longest">
<h2>Third Post</h2>
<p>
By the third article, this writer found more to say about something.
As a result, it ended up being a longer article than either of the
preceding two, not only in paragraph count but in word count per
paragraph.
</p>
<p>Of course, the per-paragraph word count is an average.</p>
<p>
The difference in article length ensures wildly different lengths on
a small page so that the results of making alignment changes can be
demonstrated very clearly in this example. There is no other
particular reason for writing this much text for an HTML example in
this documentation.
</p>
</div>
</body>
The justify-content
property in the flexbox parent element affects usage of
whitespace between flexbox children uniformly, aligning the children along the
flex-direction
property's flow. Thus, if you set flex-direction
to a value
of column
, you arrange children vertically, and justify-content
aligns them
vertically, but if you set flex-direction
to row
to arrange flexbox
children horizontally, the justify-content
property aligns children
horizontally. Put another way, justify-content
determines how to distribute
space around and between elements vertically when using column
and
horizontally when using row
for the flex-direction
property.
The default is start
, which groups all flexbox child elements at the top of
the area within the flexbox parent. A value of end
does the same at the end
of the parent, and center
will group them in the middle. These three values
serve the most common alignment needs people have previously wanted to use
other alignment properties, but this flexbox approach probably meets intuitive
expectations better than those other CSS alignment properties -- especially for
vertical alignment, as in this flexbox-direction: column
example.
Other possible justify-content
values include space-between
, which places
the first element at the beginning of the parent element with no excess space
before it, and the last element at the end with no excess space after it,
distributing any excess space equally between the child elements; and
space-around
, which divides excess space equally amongst the child elements,
half of the excess space assigned to each element placed before it and the
other half after it. This results, visually, in the space between flexbox
child elements appearing to be twice the size of the space before the first
element and the space after the last element.
The align-items
property aligns flexbox children in a direction perpendicular
to the flex-direction
flow. Thus, for flex-direction: column
, which
arranges children vertically, align-items
aligns children horizontally; for
flex-direction: row
, which arranges children horizontally, align-items
aligns children vertically.
The default value of align-items
is stretch
, which ensures that with
flex-direction: column
the width of flexbox children is 100%, while with
flex-direction: row
the height of child elements is 100% instead. Changing
the align-items
property to flex-start
, flex-end
, or center
will set the
appropriate dimension (width or height) to the minimum for the element's
content, then place the element flush with the beginning or end of the
direction perpendicular to the flex-direction
or in the center of the
provided area, as appropriate. When using flex-direction: row
, this
conveniently mitigates the complexity of using other approaches to trying to
vertically align block elements with CSS.
Another align-items
value is baseline
, which minimizes the space taken up
by a flexbox child element like flex-start
, flex-end
, or center
. In a
flex-direction: row
arrangement, the baseline
value for align-items
aligns the baseline of the first content line of all flexbox children, which
means that, for instance, the bottom of the first line of text in each child
could be aligned with the bottom of the first line of text in the others. This
is probably most useful when you want to align single-row elements with
different sizes at the top of all flexbox children, such as when showing
multiple content blocks arranged horizontally with an image at the top of each
block. [ NOTE: CHECK THIS TO MAKE SURE IT WORKS THIS WAY. ]
You can also use the align-self
property to align flexbox children
individually. Apply the property to a flexbox child to affect only the
alignment of that specific child, rather than to the flexbox parent. The
default value is auto
, which just causes the child to do what you specified
in the flexbox parent's align-items
property.
body {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
}
#longest {
align-self: stretch;
}
This deals with the sizes of flexbox child elements, and how both positive and
negative excess space gets used when the amount of available flex-direction
space is different from the dimensions specified for child elements.
<nav>
<ul>
<li id="first"><a href="#">First</a></li>
<li id="second"><a href="#">Second</a></li>
<li id="third"><a href="#">Third</a></li>
</ul>
</nav>
Normally, with flex-direction: row
, the width of a flexbox child element
shrinks to its content width. The same applies to the height of a flexbox
child when using flex-direction: column
. This can be overridden with
flex-basis
.
The flex-basis
property for a flexbox child applies to the dimension of the
element that matches the flex-direction
. Thus, for flex-direction: row
, it
applies to width, and for flex-direction: column
, it applies to height. In
fact, the flex-basis
property overrides the width
property for row
, and
overrides the height
property for column
, but it overrides neither
max-width
or min-width
for row
, nor max-height
or min-height
for
column
. The flex-basis
property defaults to auto
, but can be set using
standard CSS dimension units, such as em
or px
.
The flex-grow
property, which defaults to flex-grow: 0
, has a unitless
numeric value used to set CSS policy for what to do with any excess space along
the dimension that corresponds to the value of flex-direction
, where a value
of one is equivalent to one share of excess space, and a value of two is
equivalent to two shares. Setting the flex-grow
property for exactly one
child element to 1
ensures that element will use all excess space, increasing
its effective flex-basis
value to its explicit value plus whatever extra
space remains after allocating flex-basis
space to all other flexbox
children. Setting the first child element's flex-grow
to a value of 2
and
the second's to 1
means there are three equal shares of whatever excess space
remains, assigning two shares of it to the first element and one share to the
second.
To allocate the total space the same way, use flex-grow
to show the share of
total space applied to each element, and set flex-basis
to zero. This means
that each child element has a basis of zero space, which means all space on the
line is "excess" space, and flex-grow
then divides the total space into the
shares defined for each element, thus giving the first element in the example a
total space share of two and the second element a total space share of one.
The flex-shrink
property sets policy for what happens when there is not
enough total space available to meet the requirements of flex-basis
values.
The default value of flex-shrnk
is one, which means all child elements lose
the same amount of space. If you set flexbox-shrink: 2
for one element, that
element will lose flex-basis
value twice as quickly as others with
flex-shrink: 1
when there is not enough space to meet the requirements of
explicit flex-basis
settings. If you set flex-shrink: 0
for an element,
that element's space will not shrink at all, causing all shrinkage to apply to
other flexbox children; setting flex-shrink: 0
for all flexbox children will
cause the space used by the flexbox parent to overflow available space if
necessary so that child elements do not get robbed of specified space. The
effects of flex-shrink
will not shrink an element's space so much that it
cuts off the element's content, though.
The simple property name flex
provides a shortcut for all three of these flex
dimension properties. It takes up to three values, with default values
flex-grow: 1
, flex-shrink: 1
, and flex-basis: 0
, in that order. Notice
that 1
is the default value for flex-grow
in the flex
property instead of
0
as normal for when not defined in flex-grow
, and 0
is the default value
for flex-basis
by the flex
property, instead of auto
as normal for when
do not define by the flex-basis
property. This difference in defaults is
likely to prove confusing and frustrating if you do not keep it in mind.
Normally, setting one or two of the three possible values of flex
sets either
the first value (flex-grow
), or the first and second values (flex-grow
and
flex-shrink
), respectively, which then ensures the flex-basis
value gets a
default of 0
because the flex
shorthand's default value for flex-basis
overrides the explicit flex-basis
default itself. Because flex-grow
and
flex-shrink
only take unitless numeric values, flex: 250px
will apply the
250px
value to flex-basis
, and flex: 2 250px
will behave like you set
flex-grow: 2
and flex-basis: 250px
. In this way, the use of units on the
last value can alter the normal application precedence of flex
property
values.
A good reason for these differing defaults is that setting flex: 1
for all
flexbox children gives them all the equivalent of flex-grow: 1
, flex-shrink:
1
, and flex-basis: 0
, which means all children grow and shrink as needed to
maintain the same size along the flex-direction
dimension, a very common use
case. The downside of this is that defaults are different from how they work
for the long-form properties, which can cause problems when trying to figure
out why flexbox styles do not make the layout look the way you expect. The
most reasonable approach for most purposes might simply be to use flex
all
the time, and never use the flex-grow
, flex-shrink
, and flex-basis
properties themselves.
body {
display: flex;
}
#first {
flex-basis: 200px;
flex-grow: 2;
}
#second {
flex-basis: 100px;
flex-grow: 1;
}
#third {
flex-basis: 150px;
flex-shrink: 2;
}
This deals with breaking the space usage into multiple columns or rows, as
appropriate for flex-direction
, when flexbox child elements overflow the
available space.
<body>
<div class="thumbnail"><img src="/path/to/img/1.jpg" /></div>
<div class="thumbnail"><img src="/path/to/img/2.jpg" /></div>
<div class="thumbnail"><img src="/path/to/img/3.jpg" /></div>
</body>
The flex-wrap
property allows a row to break into multiple lines within a
flexbox, or columns to break into multiple rows.
If you set flex-wrap: wrap
, rows of flexbox children break before running out
of container room in the flexbox parent element as lines normally break for
text, or columns break vertically in a similar way. A setting of flex-wrap:
wrap-reverse
reverses the arrangement of elements and wraps from the end to
the beginning, instead of from the beginning to the end. Alignment properties
can be used to modify the arrangement of elements, such as justify-content:
space-around
and align-content: space-between
. Some alignment properties
(align-items
and align-self
) apply only to the block-level elements
arranged in rows or columns, and have no effect on content elements.
body {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-content: space-between;
}
.thumbnail {
display: block;
position: relative;
margin: 0;
flex: 0 100px;
height: 100px;
}