Background
The (Flexible Box) module ( as of October 2017) aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word "flex").
The main idea behind the flex layout is to give the container the ability to alter its items' width/height (and order) to best fill the available space (mostly to accommodate to all kind of display devices and screen sizes). A flex container expands items to fill available free space or shrinks them to prevent overflow.
Most importantly, the flexbox layout is direction-agnostic as opposed to the regular layouts (block which is vertically-based and inline which is horizontally-based). While those work well for pages, they lack flexibility (no pun intended) to support large or complex applications (especially when it comes to orientation changing, resizing, stretching, shrinking, etc.).
Flexbox layout is most appropriate to the components of an application, and small-scale layouts, while the layout is intended for larger scale layouts.
Basics & Terminology
Since flexbox is a whole module and not a single property, it involves a lot of things including its whole set of properties. Some of them are meant to be set on the container (parent element, known as "flex container") whereas the others are meant to be set on the children (said "flex items").
If "regular" layout is based on both block and inline flow directions, the flex layout is based on "flex-flow directions". Please have a look at this figure from the specification, explaining the main idea behind the flex layout.
Items will be laid out following either the (from to ) or the cross axis (from to ).
Properties for the Parent
(flex container)
display
This defines a flex container; inline or block depending on the given value. It enables a flex context for all its direct children.
.container {
display: flex; /* or inline-flex */
}
Note that CSS columns have no effect on a flex container.
flex-direction
This establishes the main-axis, thus defining the direction flex items are placed in the flex container. Flexbox is (aside from optional wrapping) a single-direction layout concept. Think of flex items as primarily laying out either in horizontal rows or vertical columns.
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
row
(default): left to right inltr
; right to left inrtl
row-reverse
: right to left inltr
; left to right inrtl
column
: same asrow
but top to bottomcolumn-reverse
: same asrow-reverse
but bottom to top
flex-wrap
By default, flex items will all try to fit onto one line. You can change that and allow the items to wrap as needed with this property.
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap
(default): all flex items will be on one linewrap
: flex items will wrap onto multiple lines, from top to bottom.wrap-reverse
: flex items will wrap onto multiple lines from bottom to top.
There are some visual demos of flex-wrap
here.
flex-flow (Applies to: parent flex container element)
This is a shorthand for the flex-direction
and flex-wrap
properties, which together define the flex container's main and cross axes. The default value is row nowrap
.
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
justify-content
This defines the alignment along the main axis. It helps distribute extra free space leftover when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
flex-start
(default): items are packed toward the start of the flex-direction.flex-end
: items are packed toward the end of the flex-direction.start
: items are packed toward the start of thewriting-mode
direction.end
: items are packed toward the end of thewriting-mode
direction.left
: items are packed toward left edge of the container, unless that doesn't make sense with theflex-direction
, then it behaves likestart
.right
: items are packed toward right edge of the container, unless that doesn't make sense with theflex-direction
, then it behaves likestart
.center
: items are centered along the linespace-between
: items are evenly distributed in the line; first item is on the start line, last item on the end linespace-around
: items are evenly distributed in the line with equal space around them. Note that visually the spaces aren't equal, since all the items have equal space on both sides. The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies.space-evenly
: items are distributed so that the spacing between any two items (and the space to the edges) is equal.
Note that that browser support for these values is nuanced. For example, space-between
never got support from some versions of Edge, and start/end/left/right aren't in Chrome yet. MDN has detailed charts. The safest values are flex-start
, flex-end
, and center
.
There are also two additional keywords you can pair with these values: safe
and unsafe
. Using safe
ensures that however you do this type of positioning, you can't push an element such that it renders off-screen (e.g. off the top) in such a way the content can't be scrolled too (called "data loss").
align-items
This defines the default behavior for how flex items are laid out along the cross axis on the current line. Think of it as the justify-content
version for the cross axis (perpendicular to the main-axis).
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
stretch
(default): stretch to fill the container (still respect min-width/max-width)flex-start
/start
/self-start
: items are placed at the start of the cross axis. The difference between these is subtle, and is about respecting theflex-direction
rules or thewriting-mode
rules.flex-end
/end
/self-end
: items are placed at the end of the cross axis. The difference again is subtle and is about respectingflex-direction
rules vs.writing-mode
rules.center
: items are centered in the cross-axisbaseline
: items are aligned such as their baselines align
The safe
and unsafe
modifier keywords can be used in conjunction with all the rest of these keywords (although note browser support), and deal with helping you prevent aligning elements such that the content becomes inaccessible.
align-content
This aligns a flex container's lines within when there is extra space in the cross-axis, similar to how justify-content
aligns individual items within the main-axis.
Note: this property has no effect when there is only one line of flex items.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
flex-start
/start
: items packed to the start of the container. The (more supported)flex-start
honors theflex-direction
whilestart
honors thewriting-mode
direction.flex-end
/end
: items packed to the end of the container. The (more support)flex-end
honors theflex-direction
while end honors thewriting-mode
direction.center
: items centered in the containerspace-between
: items evenly distributed; the first line is at the start of the container while the last one is at the endspace-around
: items evenly distributed with equal space around each linespace-evenly
: items are evenly distributed with equal space around themstretch
(default): lines stretch to take up the remaining space
The safe
and unsafe
modifier keywords can be used in conjunction with all the rest of these keywords (although note browser support), and deal with helping you prevent aligning elements such that the content becomes inaccessible.
Properties for the Children
(flex items)
order
By default, flex items are laid out in the source order. However, the order
property controls the order in which they appear in the flex container.
.item {
order: <integer>; /* default is 0 */
}
flex-grow
This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.
If all items have flex-grow
set to 1, the remaining space in the container will be distributed equally to all children. If one of the children has a value of 2, the remaining space would take up twice as much space as the others (or it will try to, at least).
.item {
flex-grow: <number>; /* default 0 */
}
Negative numbers are invalid.
flex-shrink
This defines the ability for a flex item to shrink if necessary.
.item {
flex-shrink: <number>; /* default 1 */
}
Negative numbers are invalid.
flex-basis
This defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword. The auto
keyword means "look at my width or height property" (which was temporarily done by the main-size
keyword until deprecated). The content
keyword means "size it based on the item's content" - this keyword isn't well supported yet, so it's hard to test and harder to know what its brethren max-content
, min-content
, and fit-content
do.
.item {
flex-basis: <length> | auto; /* default auto */
}
If set to 0
, the extra space around content isn't factored in. If set to auto
, the extra space is distributed based on its flex-grow
value. See this graphic.
flex
This is the shorthand for flex-grow,
flex-shrink
and flex-basis
combined. The second and third parameters (flex-shrink
and flex-basis
) are optional. Default is 0 1 auto
.
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
It is recommended that you use this shorthand property rather than set the individual properties. The shorthand sets the other values intelligently.
align-self
This allows the default alignment (or the one specified by align-items
) to be overridden for individual flex items.
Please see the align-items
explanation to understand the available values.
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
Note that float
, clear
and vertical-align
have no effect on a flex item.
Examples
Let's start with a very very simple example, solving an almost daily problem: perfect centering. It couldn't be any simpler if you use flexbox.
.parent {
display: flex;
height: 300px; /* Or whatever */
}
.child {
width: 100px; /* Or whatever */
height: 100px; /* Or whatever */
margin: auto; /* Magic! */
}
This relies on the fact a margin set to `auto` in a flex container absorb extra space. So setting a vertical margin of auto
will make the item perfectly centered in both axes.
Now let's use some more properties. Consider a list of 6 items, all with fixed dimensions, but can be auto-sized. We want them to be evenly distributed on the horizontal axis so that when we resize the browser, everything scales nicely, and without media queries.
.flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
}
Done. Everything else is just some styling concern. Below is a pen featuring this example. Be sure to go to CodePen and try resizing your windows to see what happens.
Let's try something else. Imagine we have a right-aligned navigation element on the very top of our website, but we want it to be centered on medium-sized screens and single-columned on small devices. Easy enough.
/* Large */
.navigation {
display: flex;
flex-flow: row wrap;
/* This aligns items to the end line on main-axis */
justify-content: flex-end;
}
/* Medium screens */
@media all and (max-width: 800px) {
.navigation {
/* When on medium sized screens, we center it by evenly distributing empty space around items */
justify-content: space-around;
}
}
/* Small screens */
@media all and (max-width: 500px) {
.navigation {
/* On small screens, we are no longer using row direction but column */
flex-direction: column;
}
}
Let's try something even better by playing with flex items flexibility! What about a mobile-first 3-columns layout with full-width header and footer. And independent from source order.
.wrapper {
display: flex;
flex-flow: row wrap;
}
/* We tell all items to be 100% width, via flex-basis */
.wrapper > * {
flex: 1 100%;
}
/* We rely on source order for mobile-first approach
* in this case:
* 1. header
* 2. article
* 3. aside 1
* 4. aside 2
* 5. footer
*/
/* Medium screens */
@media all and (min-width: 600px) {
/* We tell both sidebars to share a row */
.aside { flex: 1 auto; }
}
/* Large screens */
@media all and (min-width: 800px) {
/* We invert order of first sidebar and main
* And tell the main element to take twice as much width as the other two sidebars
*/
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
Prefixing Flexbox
Flexbox requires some vendor prefixing to support the most browsers possible. It doesn't just include prepending properties with the vendor prefix, but there are actually entirely different property and value names. This is because the Flexbox spec has changed over time, creating an versions.
Perhaps the best way to handle this is to write in the new (and final) syntax and run your CSS through , which handles the fallbacks very well.
Alternatively, here's a Sass @mixin to help with some of the prefixing, which also gives you an idea of what kind of things need to be done:
Related Properties
Other Resources
Bugs
Flexbox is certainly not without its bugs. The best collection of them I've seen is Philip Walton and Greg Whitworth's . It's an open source place to track all of them, so I think it's best to just link to that.
Browser Support
Broken up by "version" of flexbox:
- (new) means the recent syntax from the specification (e.g.
display: flex;
) - (tweener) means an odd unofficial syntax from 2011 (e.g.
display: flexbox;
) - (old) means the old syntax from 2009 (e.g.
display: box;
)
20- (old) 21+ (new) |
3.1+ (old) 6.1+ (new) |
2-21 (old) 22+ (new) |
12.1+ (new) | 10 (tweener) 11+ (new) |
17+ (new) | 2.1+ (old) 4.4+ (new) |
3.2+ (old) 7.1+ (new) |
Blackberry browser 10+ supports the new syntax.
For more informations about how to mix syntaxes in order to get the best browser support, please refer to this article (CSS-Tricks) or this article (DevOpera).
I think the browser support table is missing a cell, the one with Opera’s version 12.1+.
The table, as it is now, shows “Any” for IE. It’s funny! :)
Fixed, thanks!
Great post Chris. I think that flexbox capability to order items will be usefull in RWD.
I’ve got only a question. When you define main-axis you say that its direction depends on the justify-content property, but isn’t the flex-direction property that defines if flex items are layed out as a row or as a column? Am I misunderstanding something?
You’re correct, that was wrong in the article and is fixed now.
column-reverse
: same as row-reverse but top to bottomDon’t you mean bottom to top?
Correct, I’ll fix that in the article.
What does 22+ (new), in the Firefox support table means?
Meaning version 22 of Firefox which is the newest version at the time the article was written.
And the + means “and up”
Nice tutorial. Has anything changed this this tutorial was published?
Also it doesn’t work for me in IE10.
IE 10 has the tweener syntax, so make sure you’re prefixing for that. Autoprefixer does a great job of writing in the latest syntax and handling the fallbacks.
Chris, your embedded Codepen demo is broken, perhaps because of the new rendering engine update on Codepen? Just my assumption :p. Anyways great article, it helps me a lot! Thanks…
This is the error on the embedded codepen
{"success":false,"errors":{"error":["Load on secure subdomain."]},"status":200}
Temporary thing, sorry about that!
Your definition of “main axis” has a bug: you say it’s dependent on justify-content but I think you mean to say it’s dependent on flex-direction.
That was incorrect in the article and is fixed now. You’re correct, it’s
flex-direction
.Would you happen to know how I could code in a horizontal split ( like they have on Code Pen ) that separates the top of the window and the bottom of the window and moves fluidly when the bar is moved, with flexbox framework? Any help would be appreciated, thanks!
The draggable bar isn’t going to happen with just CSS, flexbox or no, save for some super crazy hack using a resizeable textarea or something. On CodePen we use jQuery UI draggable, but there are others out there. Flexbox does make the situation easier though. One time I redid the whole CodePen editor layout in Flexbox for fun and it was way easier, but of course I can’t find it now. Basically if the flex items have flex: 1; they will fill the area, so you just resize one of them to a specific height (or width) and the other will fill the remaining space. So no math.
Do you know of any working examples of jQuery UI Draggable for a horizontal split pane? I’ve been messing with it for a couple of days now and can’t seem to figure it out.
Where are things:
Those are deprecated properties. I feel like it’s best at this point (at least in terms of this guide) to focus on the current properties. Also best in practice to let a tool like Autoprefixer deal with inserting those older properties for you when needed.
Hey i’m interested in why this background: darken(colour, % ) part of code is not working for me, i tried to do it by myself with my own examples and it didn’t work so i pasted your code form codepen and it still doesn’t work. I’m sorry if i’m asking a noob question and there is something obvious that i’ve missed!?
Incase a haven’t been clear thats the example that concerns a making of dynamic navbar!
Thanks a bunch!
SRBIOTIK
That’s a Sass function.
main axis – “The main axis of a flex container is the primary axis along which flex items are laid out. Beware, it is not necessarily horizontal; it depends on the justify-content property (see below).”
flex-direction – “This establishes the main-axis,…”
These two are in conflict right..? :)
Correct. It’s
flex-direction
. I’ll update. (Then bury this as no longer relevant).I think the Support Chart is out of date for Safari. Should read:
6.1+ (new)
3.1+ (old)
According to http://beta.caniuse.com/#search=flexbox
Similarly, Android 4.4+ (new), iOS 7.1+ (new)
Thanks Scott!
It seems that example images for
space-around
in this article are a bit inaccurate. From these images, one may think that these values result in equal spaces between items, before first item and after last item. Actually, the space between items becomes twice as big as the space before first item/after last item, since the portion of free space per each item/line is distributed equally before and after it, so there are two halves of such portion between items, but only one half before the first/after the last one.That’s a nice clarification. I can update the wording to more clearly describe that.
Thanks, Chris! Can you please update the align-content section similarly?
Yep. Burying cause fixed. Thanks!
This is a pretty good quick guide. Just a couple things I noticed from a skim:
It’s not very clear how ‘order’ actually works. ‘order: 3’ doesn’t mean “put it at the third position”, it means “put it after any items with ‘order’ less than 3 and before any items with ‘order’ greater than 3”.
We (the Flexbox spec editors) strongly recommend not using the longhands of ‘flex’ unless you really, really want to cascade in flex settings from some other style rule, so I’d suggest somehow discouraging the use of ‘flex-grow/shrink/basis’ here (or, preferably, leaving it out/in an advanced section). The shorthand resets things in appropriate ways, and will therefore result in fewer cascading errors. Please use the shorthand!
I tend to think of flex “order” as z-index for flow items. Maybe this will help others to visualize it this way also.
Awesome post. Thanks so much, Chris!
Question: why do you have
(Applies to: parent flex container element)
only next to flex-flow?Warning! Description of justify-content / align-items is incorrect. Behavior of the last two changes depending of flex-direction. Article says it should be independent. “This defines the alignment along the main axis.” No! If flex-direction = column, that will align items along the cross axis. To align items along main axis you’ll need to change align-items instead.
When you change the flex direction, you’re changing the main axis. That’s how I think about it anyway. Flex-direction:
flex-basis seems to have got some updates,
main-size
no longer exists,auto
means look at width / height property (previously main-size), newcontent
keyword means automatic sizing (previously auto)https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis
Indeed! Updated.
Could you please explain flex-shrink a little better? How does the browser tell if it is “necessary” to shrink an item? How does it shrink an item? What do higher numbers mean relative to lower numbers? What happens if flex-shrink and flex-grow are both specified on the same element, or on 2 sibling elements?
Article from the opposite perspective: https://css-tricks.com/flex-grow-is-weird/
flex-shrink refers to how much an element will “give up itself” when there isn’t enough room. Using the example below, item1 will take up 3 times less space than item2 if the parent div is less than the width of both
flex-basis
‘s (600px).Example:
Andrew: Those two statements appear to contradict each other. Based on the first statement (which matches my understanding), item1 wouldn’t “take up” 3 times less space, but would “give up” three times as much space — in other words, would shrink at 3x the rate of item2.
So if the available width were 500px, instead of both being reduced by an even 50px, item1 would shrink by 75px (to be 225px wide), and item2 by only 25px (to be 275px wide). Do I have that right?
It seems this guid is missing the justify-items property
That property doesn’t apply to flexbox. MDN:
I think that fact that justify-items doesn’t apply to flexbox layouts should be included in this article as well :)
That’s because this property is ignored in Flexbox: https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items