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: flexflex-directionjustify-contentalign-itemsorderself-alignflex-basisflex-growflex-shrinkflexflex-wrapThis 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;
}