This article was originally published in CODE Magazine Issue 2016 Mar/April and has been updated on November 11th, 2017 with additional information
CSS hasn’t changed much since CSS 3 has been released, but the relatively new Flexbox module provides some much needed relief when it comes to creating complex structured layouts in HTML. Flexbox can be considered a much more flexible successor to HTML tables. In this article I’ll introduce the basic concepts of Flexbox and a few practical examples that demonstrate how to put Flexbox to use in your own HTML applications today.
Let’s face it – most of us doing Web development have struggled with multi-column layouts at sometime in our Web development. Any developer new to HTML coming from a desktop based development environment is very likely to comment immediately on the fact how difficult it is to
properly create a structured layout in HTML. While it’s always been possible to make layouts behave using various tricks and specialized workarounds, the process has never been easy.
HTML has always been very good for document style layout – that is, creating flowing documents where content stacks on top of the previous content. HTML thrives on flowing content that takes up as much space as is available and reflowing content around embedded floating elements automatically.
On the other hand, creation of structured layouts that display content in confined areas that sit side by side or need to stack in an exact order and location have been much more elusive to achieve with HTML. Trying to create paneled layouts that can stay fixed and/or dynamically resize relative to each other are not trivial to create in HTML.
Technologies to deal with structured layouts have come and gone over the years: Developers have used HTML frames, HTML tables, float based layouts, and more recently various CSS tricks and grid systems popularized by a number of CSS frameworks like Bootstrap, Foundation and
Google’s Material Design. While there have always been solutions and hacks to beat HTML into submission, it has never been an easy road as each of these technologies has limitations and requires compromises. Even today, for many Web developers tables are the first and only tool they reach for when a structured layout is required.
It seems we’ve been struggling long enough with various hacks to create complex, structured HTML layouts.
Flexbox to the Rescue
But that’s finally changing. With the advent of the HTML Flexbox model, HTML gains a rich box formatting engine that addresses complex layouts. You can think of Flexbox as HTML tables on steroids, without the styling limitations of tables and the ability to use any HTML semantic tag to create a Flexbox container and child elements. You can apply Flexbox styling to any HTML element which means you can easily restyle and reflow elements independently of each other as there is no fixed container hierarchy as there is in tables.
Flexbox makes it much easier to lay out documents that require multiple columns or need to flow complex layouts around pages by providing many declarative attributes that describe exactly how each container and their children should size themselves, how content should align and
wrap, how much and where spacing should be applied to fill space and so on. For example, it’s easy with Flexbox to create a full page layout that stay fixed to the height of the browser window and adjust all panels within the layout when the browser resizes. Likewise, it’s pretty easy to specify that content should be centered either horizontally and vertically or both. Content inside a container can be made to stack on top of the previous element or to flow side by side and you can easily control the wrapping behavior, which makes it much easier to create responsive mobile friendly layouts that can adjust according to screen size.
Much of this was possible before with HTML without Flexbox, but it required a lot of disjointed CSS attributes to find the right invocations. Flexbox creates a new, comprehensive model using a few clearly defined attributes specific to layout tasks that can interact with each other more easily than the old HTML attributes.
As we are building more and more interactive applications inside of the browser, it is increasingly important to control layout more easily to enable the complex interfaces we now build with HTML. User interface design still is one of the most time intensive operations in Web
application development, and anything that makes this process easier is a welcome change. Flexbox provides some much needed relief in this area as it facilitates creating complex layouts more easily using standard semantic HTML element tags.
The HTML Flexbox model is not exactly new. The initial, now outdated spec for Flexbox was released in 2009 followed by another now outdated update and was finally was replaced in 2012 by the current Flexbox specification that is now available in most browsers. It’s still a working draft in the final recommendation stage (see sidebar), but the draft has been fairly stable
for a few years now. All evergreen browsers and most reasonably recent mobile browsers now support Flexbox. The big glaring exception is Internet Explorer 9 and older which have no support and Internet Explorer 10 which has partial (but reasonably good and usable) support for Flexbox.
Although decent Flexbox browser support has been available since 2014, it seems that Flexbox really hasn’t hit the developer mainstream yet. It still feels like bleeding edge technology that hasn’t garnered wide adoption yet. This is because it’s relatively new and because Flexbox has a learning curve. The Flexbox CSS syntax is different and to use it you have to understand the basics of how the model and its relationships works. It’s not as simple as slapping a new attribute on a single HTML element and see behavior change. Flexbox deals with layouts and acts on
many elements simultaneously and therefore requires some Flexbox styling on each participating element. It’s not rocket science, but there are quite a few CSS attributes to choose from. The terminology for some these attributes and values is somewhat overlapping, so it can be a
little overwhelming at first to figure out which attributes to use. But as is often the case with new technology, you end up using a few features over and over again and the few attributes you need to master are easy to remember once you get the basic hang of how they relate to each other.
You’ll be hearing a lot more about Flexbox in the near future. Many of the updated big CSS frameworks coming out soon like Bootstrap 4.0 and Material Design from Google rely heavily on Flexbox to provide their layout features. It’s a good time to get up to speed on how Flexbox
works now. Even if you’re not using Flexbox directly some of the frameworks you might use in the future will leverage Flexbox under the covers and understanding how it works will make it easier to interact with these frameworks.
You can think of Flexbox as HTML tables on steroids, without the limitations of table styling and the ability to use any semantic HTML tags.
Getting Started with Flexbox
Flexbox is a CSS based container layout module. One of the big benefits of Flexbox over HTML tables is its ability to use any HTML element to define its containers and elements. You can use div, nav, article or any other built-in or dynamic semantic HTML tag to define your
containers and child items.
The key thing to understand about Flexbox is that it’s a container manipulation tool. It defines the overall behavior on the container and then allows element functionality to override some behavior traits of the elements that are under control of the container. Using a handful of
flexbox specific attributes, you get a ton of control how the container alignment and flow is managed.
Figure 1 – Flexbox works through containership using a flex
container and flex items. Items can control their own sizing and flow
Figure 1 demonstrates the containership and some of the more common
CSS attributes you’re going to see in a Flexbox layout. The container
controls the overall flow of the layout, using attributes like
flex-wrap, align-items and justify-content. The layout in Figure
1 is horizontal using flex-direction: row (along the main axis)
but Flexbox also supports flex-direction: column layouts that
formats a layout vertically (along the cross axis). Using these
attributes, you can control many aspects including element sizing,
wrapping and fill mode with very little CSS styling that clearly defines
the container behavior.
Individual items can control how they fit into the layout and manage
their own internal formatting using standard CSS styling. Child items
primarily use the flex attribute to determine their Flexbox
behavior. The flex attribute is a combination of the flex-grow,
flex-shrink and flex-basis attributes. These three attributes
determine whether the element can grow or shrink if the value is
non-zero. If the value is non-zero and the element can grow or shrink
and the value is used as a ration in relation to the other other
elements in the container. The flex-basis determines the initial size or
auto to use whatever the elements actual size is initially. Using
Flexbox it’s trivial to create relatively sized elements that are
recalculated on resizing and even as new elements are added to the
container. Other item attributes include align-self which overrides
the parent’s align-items setting and order which lets you
explicitly control the location of an element in the container’s child
collection. These are very useful if you programmatically insert and
manage elements dynamically.
Flex containers can be nested so you can create a top level container
that vertically manages elements, then use a child container to set up a
horizontal flex container inside one of the child containers. A common
example of this is a fixed window layout where you have a top level
container that manages the full height of the browser window with
header, content, footer. The content area can then have a horizontal
Flexbox layout that contains multiple panes for a nav sidebar, content
and ad sidebar. We’ll look at an example of this later in this article.
Unlike HTML tables, Flexbox can use any semantic HTML element for the
container or child elements
The Flex Container
The flex container starts off the Flexbox hierarchy using
display:flex attribute. This changes the display mode and tells the
container and immediate child elements that they are using Flexbox
layout formatting. The flex-direction attribute controls the
horizontal (row) or vertical (column) flow of the child
elements. The default is row and can be omitted for horizontal
layouts. You can also specify the fill characteristics via the
align-item and align-content which define the positioning via
fill or spacing respectively, the flex-wrap attribute that controls
wrapping behavior or elements. In combination these attributes give you
a lot of control over how the container renders its child elements.
To demonstrate here’s a simple example of a full-width horizontal
container using some very simple HTML:
To define a top level container you can do something like this (all but
the first attribute are optional):
Once you have a container you can customize how the contained elements
behave inside of that container primarily using the flex attribute.
To demonstrate I’m using three horizontal panels that have two fixed
width panels and one auto-resizing panel:
flex: none; /* manual resize */
flex: none; /* manual resize */
flex: 1; /* resizable */
The most important attribute is the flex attribute is a shorthand
for flex-grow, flex-shrink and flex-basis. The first two are
numeric values that represent relative sizes of all the child elements.
0 means the size is fixed and shouldn’t shrink or grow respectively. Any
number greater than 0 means the element can grow or shrink relative to
the other elements’ grow and shrink values. The most common values are
0 0 auto which specifies to keep the size fixed, or 1 1 auto
(which is also the default if not provided) which specifies the element
will auto size itself to fill available space. When using auto for the
flex-basis, the element uses the existing size as its basis, so if you
have a fixed width for the element that is used as the base value.
If you want to express a relationship without explicit width (or height)
you can also use relative numbers that establish a ratio relationship
between the elements:
flex: 2 2 auto; /* resizable */
flex: none; /* fixed */
flex: 4 4 auto; /* resizable 2x left */
This makes the left panel (2) half the size of the right panel (4), and
the splitter panel half the size of the left panel (1). As you resize
the container that relationship stays intact. This is similar to using
percentages in table layouts except that Flexbox can recalculate the
ratios even if new elements are added to the layout. Figure 2 shows
how this relationship renders in the browser when another .splitter
and .panel-right elements are added to the initial layout. You can
check it out online at: http://codepen.io/rstrahl/pen/adJPeQ.
Figure 2 – Using relative sizing in the flex property keeps
elements sized relatively to each other as you resize the browser window
and even if you add new elements dynamically.
Although relative sizing like this is very powerful, you can also use
specifically sized layouts where some elements stay fixed and others
automatically stretch or shrink to the accommodate the new size of the
container. Using flex: 0 0 auto specifies that the element should
stay fixed in size while flex: 1 1 auto will resize. This is very
common for layouts that have a single expanding element or that are
using things like splitters that let a user resize panels.
One of the most difficult layout issues to deal with in HTML
consistently, even in modern browsers, is to build a UI that
automatically stretches to fill the entire browser window and stays
properly sized as you resize the document. The age old problem with
vertical sizing in the browser is that HTML has to know the actual size
of the window from the top level container (body/html) all the way down
into the child elements. Flexbox makes this process much easier.
To create a vertical layout you can use the flex-direction: column
on the container, and then layer the elements to fill the height of the
container. Using the exact same layout as in Figure 2 and simply
switching the flex-direction:column results in a stacked layout
displayed in Figure 3. You can also check out the Codepen at:
Figure 3 – Creating a vertical layout that fills a container is as
simple as using flex-direction:column.
As in the horizontal layout, the vertical panels now fill the height of
the container to its maximum size using the ratios specified by in the
To create full window height layouts that fill the entire browser window
and resize to fill the entire content area, you have to ensure that the
html,body elements as well as the top level flex container that
wraps the entire page, have a height:100% set in their CSS:
This ensures the content of the items fills the entire window. Note the
overflow:auto in the .flex-container, which works around an odd
gotcha I ran into with FireFox. FireFox requires overflow:auto in
order to keep the panels constrained to the panel height, even though
overflow:auto should be the default setting. All other browsers seem
to work without this. I’ve found in a few instances where explicit
overflow settings are required so I’ve taken to being very explicit with
my overflow settings in flex containers.
Vertical and Horizontal Content Centering
Another common difficulty in HTML is vertical centering of elements in a
container. While there is a vertical-align property in CSS, this
property applies only to table-cells and inline elements. It has no
effect on any other container elements.
Flexbox provides a simple solution using align-items. There are several
ways to express this:
This implies flex-direction:row as that’s the default. If all you’re
after is centering this is the least CSS code you can use**.** This
might be counter intuitive because the flex-direction is horizontal
while align-items works on the vertical direction. This is exactly the
behavior of align-items, which aligns items on the perpendicular
Another slightly more verbose but maybe more obvious way to express this
same vertical centering is to use justify-content which aligns
content on the active flex-direction:
Both have the same effect of vertical centering the content but it’s
easier to see that centering is occurring on the column axis. To
summarize: justify-content works on the current flex-direction axis,
align-items works on the perpendicular/alternate axis. Hooray for bad
The reason both of these exist is so that you can combine them to center
both vertically and horizontally. The following does just that:
Applied to the .panel-right style in the previous example Figure 4
shows what the centered content looks like.
Figure 4 – Centering content inside of an element can be easily done
with justify-content and align-items on any flex container.
Other Posts you might also like