Flexible box, or Flexbox in short, is a set of properties in CSS introduced in 2009 to provide a new, exceptional layout system. The Flexbox module is identified as a part of the third version of CSS (CSS3).

You are probably already using many of the new properties in CSS3, such as box-shadow, border-radius, background gradients, and so on. However, Flexbox has yet to see the widespread adoption that it deserves. This may be because of all the breaking changes it has suffered over the years, or because it is only partially supported in Internet Explorer 10, or just because Flexbox is a whole ecosystem while previous paradigms have been predominantly based on single, ready-to-go properties.

It is super powerful and offers a wide range of options to achieve layouts that, previously, could only be dreamed of.

This article will walk you through the basics of Flexbox and how you can use it to achieve some really cool layouts which would otherwise require complicated CSS hacks or even JavaScript.

Why Use Flexbox?

By default, HTML block-level elements stack, so if you want to align them in a row, you need to rely on CSS properties like float, or manipulate the display property with table-ish or inline-block settings.

If you choose to use float (left or right), you must clear the wrapper at some point to push it until the very last floated element, otherwise, they will overflow over anything coming after. However, with float, you are limited to organizing elements horizontally.

Alternatively, or in addition, you can manipulate the display property to try to achieve the layout you desire! But this often feels kludgy at best, not to mention tedious, and often results in a fairly fragile layout that won’t necessarily render consistently across browsers. This approach is particularly ineffective if you are targeting multiple devices of varying sizes—which is almost always the case nowadays.

Enter Flexbox!

With a simple rule applied to a parent element, you can easily control the layout behavior of all of its children.

With Flexbox, you can:

  • Reverse the order of the elements inside a Flexbox parent.
  • Wrap child elements in columns (number of columns can vary depending on child and parent height).
  • Specify the rate at which elements grow or shrink while the viewport size changes.
  • Control whether elements are shrinkable or not, regardless of the specified width unit type (relative or absolute).
  • Change the order of elements with CSS (combine this with media queries and you will find limitless possibilities in your flow).
  • Generate complex distributions of the elements to be equidistant with space around or just space between.
  • Generate “renegade” elements that flow differently (everyone to the left but one to the right, top/bottom… it’s your call).
  • And, most importantly, avoid the clear-fix hack for good!

I understand Flexbox can be tough in the beginning. I think it is easier to learn ten unrelated CSS properties than five with some inter-dependency. However, with your current CSS skills, and maybe a little help from this article, you will launch yourself into a new CSS universe.

The Basics of Flexbox

Display

Display

display is one of the most basic properties in CSS and is quite important in the context of Flexbox, as it is used to define a flex wrapper.

There are two possible flex wrapper values: flex and inline-flex.

The difference between the two is that a display: flex wrapper acts like a block element while a display: inline-flex wrapper acts like an inline-block. Also, inline-flex elements grow if there is not enough space to contain the children. But other than those differences, the behavior of the two would be the same.

Try the sample code below, reduce the viewport width when inline-flex is active and… scroll.

See the Pen Flexbox @Toptal - Parent - `display` property by DD (@Diegue) on CodePen.

.wrapper {
    display: flex || inline-flex;
}

Flex Direction

Flex Direction

Now that you have seen the first sample, you can infer that the default behavior is to simply make a row of the elements. But there is more:

  • row (default): Arranges the elements from left to right (but if RTL is set it would be backward).
  • row-reverse: Reverses the order of elements in a row disposition
  • column: Arranges the elements from top to bottom
  • column-reverse: Reverses the orders of elements in a column disposition

Hint: The column and column-reverse values can be used to swap the axes, so the properties that would affect the horizontal axis would affect the vertical axis instead.

See the Pen Flexbox @Toptal - Parent - `flex-direction` property by DD (@Diegue) on CodePen.

.wrapper {
    flex-direction: row || row-reverse || column || column-reverse;
}

Flex Wrap

If you check the first code sample, you’ll figure out that the child elements don’t stack by default within a flex wrapper. This is where flex-wrap comes into play:

  • nowrap (default): Prevents the items in a flex container from wrapping
  • wrap: Wraps items as needed into multiple rows (or columns, depending on flex-direction)
  • wrap-reverse: Just like wrap, but the number of rows (or columns) grows in the opposite direction as items are wrapped

See the Pen Flexbox @Toptal - Parent - `flex-wrap` property by DD (@Diegue) on CodePen.

.wrapper {
    flex-wrap: nowrap || wrap || wrap-reverse;
}

Flex Flow

You can combine flex-direction and flex-wrap properties into a single property: flex-flow.

.wrapper {
    flex-flow: {flex-direction} {flex-wrap};
}

Justify Content

Justify Content

This property is used to control the horizontal alignment of the child elements:

  • flex-start (default): Elements are aligned to the left (similar to inline elements with text-align: left)
  • flex-end: Elements are aligned to the right (similar to inline elements with text-align: right)
  • center: Elements are centered (similar to inline elements with text-align: center)
  • space-around (where the magic begins): Every element will be rendered with the same amount of space around each item. Note that the space between two sequential child elements will be double the space between the outermost elements and the sides of the wrapper.
  • space-between: Just like space-around, except the elements will be separated by the same distance and there will be no space near either edge of the wrapper.

Note: Remember flex-direction, when set to column or column-reverse, swaps the axis. If one of these is set, justify-content will affect vertical alignment, not horizontal.

See the Pen Flexbox @Toptal - Parent - `justify-content` property by DD (@Diegue) on CodePen.

Align Items

Align Items

This property is similar to justify-content but the context of its effects is the rows instead of the wrapper itself:

  • flex-start: Elements are vertically aligned to the top of the wrapper.
  • flex-end: Elements are vertically aligned to the bottom of the wrapper.
  • center: Elements are centered vertically within the wrapper (at last, a safe practice to achieve this).
  • stretch (default): Forces the elements to occupy the full height (when applied to a row) and the full width (when applied to a column) of the wrapper.
  • baseline: Vertically aligns the elements to their actual baselines.

See the Pen Flexbox @Toptal - Parent - `align-items` property by DD (@Diegue) on CodePen.

Align Content

Align Content

This property is similar to justify-content and align-items but it works in the vertical axis and the context is the entire wrapper (not the row like the previous example). To see its effects, you will need more than one row:

  • flex-start: Rows are vertically aligned to the top (i.e., stacked from the top of the wrapper).
  • flex-end: Rows are vertically aligned to the bottom (i.e., stacked from the bottom of the wrapper).
  • center: Rows are centered in the wrapper vertically.
  • stretch (default): In general, this property stretches the elements to utilize the entire vertical height of the wrapper. However, if you have set some specific height of the elements, that height will be honored and the remaining vertical space (in that row, below that element) will be empty.
  • space-around: Every row will be rendered with the same amount of space around itself vertically (i.e., below and above itself). Note that the space between two rows will, therefore, be double the space between the top and bottom rows and the edges of the wrapper.
  • space-between: Just like space-around, except the elements will be separated by the same distance and there will be no space on the top and bottom edges of the wrapper.

See the Pen Flexbox @Toptal - Parent - `align-content` property by DD (@Diegue) on CodePen.

Flex Grow

Flex Grow

This property sets the relative proportion of the available space that the element should be using. The value should be an integer, where 0 is the default.

Let’s say you have two different elements into the same flex wrapper. If both have a flex-grow value of 1, they will grow equally to share the available space. But if one a flex-grow value of 1 and the other a flex-grow value of 2, as shown in the example below, this one with a flex-grow value of 2 will grow to take twice as much space as the first.

.wrapper .elements {
    flex-grow: 1; /* Default 0 */
}
.wrapper .elements:first-child {
    flex-grow: 2;
}

See the Pen Flexbox @Toptal - Children - `flex-grow` property by DD (@Diegue) on CodePen.

Flex Shrink

Similar to flex-grow, this property sets whether the element is “shrinkable” or not with an integer value. Similar to flex-grow, flex-shrink specifies the shrink factor of a flex item.

See the Pen Flexbox @Toptal - Children - `flex-shrink` property by DD (@Diegue) on CodePen.

.wrapper .element {
    flex-shrink: 1; /* Default 0 */
}

Flex Basis

This property is used to define the initial size of an element before available space is distributed and elements are adjusted accordingly.

Hint: flex-basis does not support calc() and box-sizing: border-box in every browser, so I recommend using width if you need to use one of these (note that you will also need to set flex-basis: auto;).

See the Pen Flexbox @Toptal - Children - `flex-basis` property by DD (@Diegue) on CodePen.

.wrapper .element {
    flex-basis: size || auto; /* Default auto */
}

Flex

You can combine flex-grow, flex-shrink, and flex-basis properties into a single property: flex as follows:

.wrapper {
    flex: {flex-grow} {flex-shrink} {flex-basis};
}

Hint: If you plan to use flex, make sure to define every single value (even if you want to use default values) because some browsers might not recognize them (a common bug is related to not having defined the flex-grow value).

Align Self

Align Self

This property is similar to align-items but the effect is applied individually to each element. The possible values are:

  • flex-start: Vertically aligns the element to the top of the wrapper.
  • flex-end: Vertically aligns the element to the bottom of the wrapper.
  • center: Vertically centers the element within the wrapper (at last a simple way to achieve this!).
  • stretch (default): Stretches the element to occupy the full height of the wrapper (when applied to a row) or the full width of the wrapper (when applied to a column).
  • baseline: Aligns the elements according to their actual baselines.

See the Pen Flexbox @Toptal - Children - `align-self` property by DD (@Diegue) on CodePen.

Order

Order

One of the best things included in Flexbox is the ability to reorder elements (using the order property) without needing to modify the DOM or use JavaScript. The way the order property works is super simple. In much the same way that z-index controls the order in which items are rendered, order controls the order in which elements are positioned within the wrapper; that is, elements with a lower order value (which can even be negative, by the way) are positioned before those with a higher order value.

See the Pen Flexbox @Toptal - Children - `order` property by DD (@Diegue) on CodePen.

.wrapper .elements {
    order: 1;   /* this one will be positioned second */
}
.wrapper .elements:last-child {
    order: -1;   /* this one will be positioned first */
}

Pulling it All Together: Example Uses of Flexbox

When it comes to designing layouts, Flexbox unleashes a world of possibilities. Below, you can find some example uses of Flexbox properties.

Vertical Alignment Component

With Flexbox, you can align anything vertically, including multiple elements at once. Without Flexbox, you needed to use positioning or table-ish techniques that required us to create one child to contain multiple elements. But with Flexbox, you can leave these tedious and fragile techniques behind, and simply define a few properties in the wrapper and that’s it, regardless of how many times the content inside the container changes or the type of change!

.wrapper {
    display: flex; /* always present for Flexbox practices */
    flex-direction: column; /* elements stack */
    justify-content: center; /* now that flex-direction is a column, the axis are swapped so this centers the content vertically */
    min-height: 100vh /* make sure wrapper is taller enough */
}

See the Pen Flexbox @Toptal - Real uses we can give - Vertical alignment by DD (@Diegue) on CodePen.

Half/half Layout

A “half/half” layout is a full height layout with two columns, each with its content centered vertically. It is usually implemented “above the fold” (i.e., before users have scrolled down after page loads).

Using more traditional techniques, you could create this layout with floated elements (of width 50% each), clearing the floats into the wrapper (“clearfix” :before and :after, overflow: hidden, or a whacky <div> with clear: both; in the end). Yet it is a lot of work and the result is not as stable as what Flexbox provides.

In the following code snippet, you will see how easy it is to set the layout and also how the children become also Flexbox wrappers since everything is vertically aligned as well.

Outer wrapper:

.wrapper {
    display: flex;
    flex-direction: column; /* only for mobile */
}

Inner wrappers:

.inner-wrapper {
    flex-grow: 1; /* Allow the element to grow if there is available space */
    flex-shrink:  1; /* Elements shrink at the same rate */
    flex-basis:  100%; /* Elements will cover the same amount, if is possible the 100% of the width */
}

See the Pen Flexbox @Toptal - Real uses we can give - Half-bleed section by DD (@Diegue) on CodePen.

Full-width Navbar Buttons

A full-width navbar distributes the space equally in the same row of navbar items regardless of the number of elements.

In the sample below, there are also are some iconic buttons without this behavior, demonstrating that you can combine the two in any way you want. Without Flexbox, achieving these sorts of layouts would have required JavaScript code to calculate the available space and then distribute it programmatically depending on which buttons span and which don’t.

Flexbox makes this much simpler.

Wrapper properties:

.navbar {
    display: flex;
}

Spanning child properties:

.navbar-item {
    flex-grow: 1; /* They will grow */
}

Non-spanning child properties:

.navbar-other {
    flex-grow: 0; // They won’t grow
}

See the Pen Flexbox @Toptal - Real uses we can give - Full-bleed buttons navbar by DD (@Diegue) on CodePen.

Blurbs

How many times did you have to implement a set of information boxes with icons and text in different projects?

This distribution of elements is mostly useful in digital marketing but can have some other uses in software development. With the power of Flexbox, you can set a sort of grid and also align elements regardless of how many there are.

Wrapper properties:

.wrapper {
    display: flex;
    flex-wrap: wrap;
}

Child properties:

.blurb {
    flex-grow: 0; /* elements don’t grow */
    flex-shrink: 0; /* elements don’t shrink in a flexible way */
    flex-basis: auto; /* the width of the elements will be set by proportions in `width` due to flex-basis not support workaround */
    width: calc(33.33% - 60px); /* calculate proportional width without space taken by padding (workaround for IE 11) */
}

For tablet and mobile viewports, the width varies between 50% and 100%.

See the Pen Flexbox @Toptal - Real uses we can give - Blurbs by DD (@Diegue) on CodePen.

Enhancing Cross-browser Compatibility

The syntax for Flexbox has changed numerous times across different browser versions. This can be an issue when implementing a layout with Flexbox and trying to support older web browsers, especially older versions of Internet Explorer.

Fortunately, many techniques and workarounds for getting your code to work across the widest range of web browsers are listed in Flexbugs, which is a great resource. If you follow the information on that site, you will have better, consistent results across different web browsers.

Prefix tasks are particularly useful in this regard. To automate prefixing of CSS rules, you can pick one of the following tools:

Ruby:

Node.js:

Start Building Smart Layouts

Flexbox is a great tool to speed, polish, and scale our work. The limit is only in the imagination of the developer.

If you need some visual aid to plan your next layout you can try this neat playground:

See the Pen Flexbox @Toptal - Flexbox playground by DD (@Diegue) on CodePen.

Open it in a new window.

With increasing adoption of modern web browsers by a majority of users, using Flexbox will allow you to create amazing layouts easily without the need to delve into messy JavaScript code or craft kludgy CSS.

About the author

Diego Díaz, Argentina
member since July 12, 2016
Diego's experience in advertisement, communication, and design is what drives him to develop web apps focused on UI and UX. Fluid layouts that fit any screen. Progressive enhancement or graceful degradation, variable display resolutions (from smallest portable devices to 5k resolution)---A strong foundation and content-oriented architecture allows the user to really "feel" the app. [click to continue...]
Hiring? Meet the Top 10 Freelance Front-End Developers for Hire in July 2017

Comments

mark
Very thorough and pretty good examples. Bookmarked for sure. Thanks!
Diego Díaz Ogni
I'm glad you liked it!
Anass Ez-zouaine
Thank you bro
Trade Southwest
Seems like an awful lot of bytes (code) to do so little. SCSS is nice but then you add Angular, script on page.... I would like to see more examples of flexbox in its naked form. (I know you are promoting yourself and topal so maybe that is the reason for all the flare, but the excess of <s>bulky</s> dependencies makes me want to just use CSS.) My goal is to make websites faster, not dedicated to multi-responsiveness. This is just an observation I have from a developer angle. Your work and the write up are both fantastic and I enjoyed reading.
Diego Díaz Ogni
Nice you like reading it. Angular is involved with the sole purpose of making dynamic samples but is not a dependency to make awesome layouts with Flexbox. The goal was to provide an extensive set of visual aids for those developers still don't have to courage to face the wide set of tools Flexbox comes with. Thanks for sharing your most honest opinion about the post. It helps always to improve.
Diego Díaz Ogni
Thank you too, hope you enjoyed the Playground, works like a charm into a blank window =D
Brayan Hernandez
awesome improvements!
Ron Pacheco
In the set of visual examples for "justify-content", "space-around" and "space-between" appear to be reversed. The graphic for "space-around" shows elements aligned all the way to the edges of the wrapper, and the graphic for "space-between" shows the outer elements padded away from the edge of the wrapper, but this appears to be the reverse of how these properties function.
Diego Díaz Ogni
Thanks Ron for bringing this to the table. In the graphic of "justify-content" the properties "space-around" and "space-between" are swapped. I've already flagged this out in the morning to the Blog's team to fix it as soon as possible. Hope you've enjoyed the code samples and the playground!
Diego Díaz Ogni
Thank you Brayan! Try the Flexbox playground for multiple combinations!
Adrian Kalbarczyk
Very good, to the point tutorial on Flexbox. Thanks for the sweat you've put into making the visual samples. They make understanding the concept A LOT easier!
Diego Díaz Ogni
Thanks Adrian, having fun is the best way of learning. The playground is the place to destroy and build back any layout. I should add some field to reset all margins in present elements to some value so you guys can create structures without spacing easier.
marofbd
Wonderful and very brief explanation on Flexbox. I learned lots. Thanks
Diego Díaz Ogni
Awesome!
Diego Díaz Ogni
The issue with "spacing" properties has been fixed in the image. Thanks again for flagging it out!
Leticia Peuser
thank you Diego vey helpful, easy to read and simple to understand :) I loved the examples
Bla Bla Bla
I've been learning CSS to build a web app I wrote with React.js and I've been tired of writing CSS for the past few weeks. After reading this blog yesterday. I finished two pages in the side project and I believe dedicating 2-3days would get the project done asap. I really want to say a big thank you to you for the thorough explanation, I really really appreciate it.
xgqfrms
Flexbox playground http://codepen.io/Diegue/pen/rjRrgW
Diego Díaz Ogni
Awesome Leticia, thanks!
Diego Díaz Ogni
Bla bla bla that sounds great! I'm really happy about being helpful with this post. Feel free to reach me if you need anything else!
Diego Díaz Ogni
Please anyone feel free to fork it and improve it with a better UX, more options or anything you might want. Everything sums =D
Laureano Martín Arcanio
Thanks for sharing, great article!
Diego Díaz Ogni
Thanks Laureano, I really appreciate it!
Juraj
Thanks, great article for learning advanced flex techniques :) just one note - you are saying that flex-shrink is binary but on your codepen is possible to set value = 2, or 3 and blocks are rendered differently. So that looks like it's accepting number - shrink factor, not a boolean. http://codepen.io/Diegue/pen/QdoVjb https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink
Diego Díaz Ogni
You are totally right Juraj. At the moment I wrote about "shrink" I couldn't corroborate what you say, but did it later when fixed some parameters in the Codepen sample. I'll work with Toptal's blog team to having this fixed as soon as possible. Please keep enjoying the article and if you find any other inconsistence don't hesitate to bring it up! Cheers!
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
You can edit your subscription preferences here.
Trending articles
Relevant Technologies
About the author
Diego Díaz
CSS3 Developer
Diego's experience in advertisement, communication, and design is what drives him to develop web apps focused on UI and UX. Fluid layouts that fit any screen. Progressive enhancement or graceful degradation, variable display resolutions (from smallest portable devices to 5k resolution)---A strong foundation and content-oriented architecture allows the user to really "feel" the app.