Introduction to Flexbox
This blog post is also published on the Cardinal Solutions Blog.
There are plenty of good resources on flexbox in the community already, but I would like to provide my own take on this newer CSS feature. I will not cover all of the features available in flexbox, but instead walk through some of the basic properties, provide some practical examples that I have come across in my own work, and finally leave you with a few tips, tricks, and links to help make working with flexbox a little bit easier.
Background
CSS layout has been a challenge for a long time. Early on, if you wanted much beyond a vertical column of elements,
you had to use tables. When the web standards movement came along, tables were thrown out and several
grid systems based on the float
or display: inline-block
property appeared. Websites have been using some variant of
these layout techniques for over a decade, and while they work, they leave much to be desired.
Flexbox emerged a few years ago to provide alternative layout schemes for all sorts of different design patterns. As a layout technology, flexbox is not perfect or a silver bullet for all web design problems, but it provides a significant step forward in what we can build on the web.
The Basics
Flexbox is based around the concept of arranging elements on a main axis and then a cross axis. Secondary to this, the elements arranged on the main axis can have a "flexible" dimension along the axis computed dynamically by the browser. No more JavaScript window resize handlers necessary!
To begin a flexbox layout, we start with a parent element with display: flex
:
<div class="flex-container"></div>
.flex-container {
display: flex;
}
This tells the browser that the immediate children of this element should be laid out using the flexbox rules.
Next, we configure the orientation of the main axis with the flex-direction
property:
.flex-container {
display: flex;
flex-direction: row;
}
The direction of row
says that the main axis is horizontal and child elements are laid out from left-to-right
(or right-to-left if you specify row-reverse
). Using column
says that the main axis is vertical and the child
elements stack from top-to-bottom (or bottom-to-top if you specify column-reverse
).
The flex-wrap
property allows us to configure what happens when child elements fill the parent container.
By default, this property is set to nowrap
which tells the browser to try to fit all children onto the same line.
If the sum of the children's dimensions are too big, they may overflow their parent container.
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
Other available values for flex-wrap
include wrap
and wrap-reverse
. When the minimum dimensions of the child
elements exceed the parent's dimensions, these values allow child elements to flow onto the next line from left-to-right
or right-to-left, respectively.
The last property we will go over here is justify-content
. This property aligns the child elements along the main axis
and distributes leftover space after the children's maximum dimensions have been reached. The default value of
flex-start
tells the browser to lay out child elements at the start of the main axis and let all extra space fall at
the end:
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
Other options for justify-content
include flex-end
, center
, space-between
, and space-around
. The value
flex-end
functions opposite of flex-start
by laying out child elements from the end of the main axis and leaving
all extra space at the start. We will explore the values center
and space-between
later on.
Note: The values we used for flex-direction
, flex-wrap
, and justify-content
so far are the browser defaults,
but we will keep them as a reminder of what those values are.
Next, we add some children to our .flex-container
and define some base padding and a border so we can see the
elements' boundaries better:
See the Pen Basics - Part 1 by Marc Denning (@kenobi883) on CodePen.
There are two main properties set on child elements: flex
and order
. The flex
property is a shorthand property
for flex-grow
, flex-shrink
, and flex-basis
. While each of those can be set individually, using the shorthand
is more common and recommended because it will apply intelligent defaults to the remaining properties. If we look at
our output before applying these rules to the child elements, we should see three boxes stuck together, just big enough
for their content, aligned to the left.
Notice that we don't use float: left
, display: inline-block
, or any of the old tricks! By defining a container with
display: flex
, we have horizontally-aligned children. If we add one rule to our .flex-child
definition, we can see
even more of flexbox in action:
See the Pen Basics - Part 1 by Marc Denning (@kenobi883) on CodePen.
Now, each child element takes up equal width across the .flex-container
. Setting flex: 1
sets the underlying
flex-grow
property to 1
. The flex-grow
property is a unitless value (we do not use px
or em
here).
This tells the browser that each element should expand to fill the space available
in our .flex-container
element proportionately to one another.
Note: Since we only specified one value for the flex
shorthand property, the other properties flex-shrink
and
flex-basis
are set to 0
and auto
respectively. Like flex-grow
, flex-shrink
instructs the browser to determine
how wide the element should be, but it does so by allowing the element to shrink rather than expand. The
flex-basis
property provides a default width (or height if using flex-direction: column
) from which to shrink or
expand. You should only set either flex-grow
or flex-shrink
to a non-zero value, not both.
If we set the value of flex
to 2
for one of our child elements, that element now takes double the amount of space
available in the container relative to the remaining elements equally share the leftover space:
See the Pen Basics - Part 2 by Marc Denning (@kenobi883) on CodePen.
The final property to explore is order
. The order
property allows us to visually re-order child elements.
For instance, we could have "Child 3" appear first:
See the Pen Intro to Flexbox by Marc Denning (@kenobi883) on CodePen.
The key here is that the source order of elements in the DOM has not changed. Only what appears visually on the page.
There are other properties and options to cover within the flexbox specification, but this gives us enough to get going. Now, let's look at some practical uses of these properties!
Practical Examples
Application Menu Bar
See the Pen Flexbox Examples - Application Menu Bar by Marc Denning (@kenobi883) on CodePen.
The application menu bar is an example of using the order
property. The components displayed are common requirements
for a web application: a title, a menu button, and a search bar. Note that in the example, these components are
in the DOM in one order, but visually displayed in a different order! For accessibility or SEO reasons,
you may want to ensure that while your app's title is in the center of the menu bar, it comes first in the source order
of the DOM. Flexbox makes this easy.
Side Bar Layout
See the Pen Flexbox Examples - Sidebar Layout by Marc Denning (@kenobi883) on CodePen.
The side bar layout example once again shows how flex
and order
properties may be used to provide a content-first,
responsive layout. Note that our main content is first in source order and is at the top of the page on smaller screens,
but shows up in the middle of the page on wider screens. Change the flex-direction
from column
on
smaller screens to row
on wider screens and adjusting the width and order properties, to get a functional layout
at both dimensions.
Fixed Footer
See the Pen Flexbox Examples - Fixed Footer by Marc Denning (@kenobi883) on CodePen.
The fixed footer is one of my current favorites for showing off a neat application of flexbox. You may need to open this example in another window to appreciate the effect. When you adjust the height of the window, notice that when the window is shorter, you can scroll the page as usual and observe the different regions in their static height, but as the window gets taller, the footer stays fixed to the bottom of the window!
There are a few keys to making this work: starting from the body
, the container elements should have a height of
100%
, flex-direction
is set to column
and the main content area has flex
set to 1 0 auto
. This allows the
main area to grow in height from its static height but not shrink. This technique is certainly useful for websites
where page content may be short on some pages and longer on others, but it is also quite helpful in creating responsive
application layouts where some elements have static dimensions, but a primary workspace area should take the rest of the
available window space.
Tips & Tricks
- Flexbox is well-supported in all modern browsers, but comes with some caveats for those needing to support older versions of Internet Explorer. Flexbox is supported in IE10, but you must use an older prefixed version of the syntax. A tool like Autoprefixer is really helpful here. IE8 and IE9 do not support flexbox.
- Flexbox is best at laying out components in one direction: along the main axis. Some of the properties we covered affect the behavior of elements along the cross axis, but at its core, flexbox is a one-dimensional tool. For modern two-dimensional layout, see the working draft of the CSS Grid Specification.
- When you are comfortable working with the properties covered in this article, explore the flexbox properties that
affect the cross-axis:
align-items
,align-content
, andalign-self
. Using these properties in addition the core properties we explored will give you greater and more advanced control over flexbox components. - The
display: flex;
rule only applies to direct children. However, if you adddisplay: flex;
to a child element, children of that element become flex items, so nested flexbox layouts are entirely possible. Check out the Put it all together pen for an example of nested layouts.