Flexbox is pretty awesome and is certainly part of the future of layout. The syntax has changed quite a bit over the past few years, hence the “Old” and “New” syntax. But if we weave together the old, new, and in-between syntaxes, we can get decent browser support. Especially for a simple and probably the most common use case: order-controlled grids
The HTML
A semantically meaningless wrapper goes around the three main areas and will set the flexbox context. Each of the areas is semantically marked up and will be turned into columns.
<div class="page-wrap">
<section class="main-content" role="main">
Main content: first in source order
</section>
<nav class="main-nav" role="navigation">
Links
</nav>
<aside class="main-sidebar" role="complementary">
Sidebar
</aside>
</div>
The end result looking like this:
Flexbox Context
We need to make the container for our columns a flexbox display context. Just by doing this, all direct children of this element become flex items. Doesn’t matter what they were before, they are flex items now.
Right away we need to weave the old, new, and tweener syntaxes together. Order is important here. Since the display property itself isn’t prefixed, we need to make sure we don’t override newer syntaxes with older syntaxes for browsers that still (and probably always will) support both.
.page-wrap {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
Controlling Column Widths
Our goal here is a 20% / 60% / 20% grid.
Step 1 is to set our main content to the 60%.
Step 2 is to set the outside sidebars to fill the remaining space equally.
Again we need to weave together old, new, and tweener syntaxes.
.main-content {
width: 60%;
}
.main-nav,
.main-sidebar {
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
width: 20%; /* For old syntax, otherwise collapses. */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
In the new syntax, setting the width for the sidebars isn’t necessary as it will fill the remaining 40% equally making them both 20%. But I found not setting it cause some width collapsing with the old syntaxes.
Column Re-Ordering
We want the main content to visually appear in the middle, but be first in the source order. Easy cheesy in flexbox, but of course we need to weave together the new, old, and tweener syntaxes.
.main-content {
-webkit-box-ordinal-group: 2; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-ordinal-group: 2; /* OLD - Firefox 19- */
-ms-flex-order: 2; /* TWEENER - IE 10 */
-webkit-order: 2; /* NEW - Chrome */
order: 2; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.main-nav {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
.main-sidebar {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
-ms-flex-order: 3;
-webkit-order: 3;
order: 3;
}
Browser Support
If you do all this weaving, you can get:
- Chrome any
- Firefox any
- Safari any
- Opera 12.1+
- IE 10+
- iOS any
- Android any
The biggest limiting factor of course being IE, but otherwise it’s pretty good. If you’re doing a mobile-specific version of a site, you’re in even better shape. If someone can test it on Windows Phone, lemme know.
Firefox 19- is a bit buggy and you’ll need to watch it. For instance, in this demo I wasn’t able to figure a way to force the sidebars to actually be 20%. The just collapse to the width of the content inside, which is a bit arbitrary as it’s text. I also needed -moz-box-flex: 1;
on the main content (60%) otherwise it would stretch to be as wide as the widest paragraph as if it had white-space: nowrap
, which is just inexplicable to me.
Demo
Check out this Pen!
Flexbox is definitely something worth learning. Thanks for this clean tutorial Chris. :)
Great info Chris, for me I’m wondering (aside from re-ordering content visually) what the benefits of using Flex over traditional code like simple widths with floats are?
This talk write-up might help explain the background: http://adactio.com/journal/6049/
Nice article. Fans of this might want to check out the Flexy Boxes flexbox playground that generates legacy and modern flexbox syntax similar to what’s written here.
Thanks to the author, Chris Coyier. Using flexbox makes sence, especially when we work with modern browsers (some time in a close future, I hope).
Pete B: You added the link to Flexy Boxes which makes great sence: a Webapp to help us getting started using flexbox – thanks.
Too bad that there is no lower than IE 10 support. Then it would be perfect.
html5please.com suggest to avoid it for now http://html5please.com/#flexbox
here is a polyfill for Flexbox I haven’t tested it thought https://github.com/doctyper/flexie
But as it’s compatible with even IE9 I would not use it for desktop websites
if you’re considering using a polyfill, you might as well just target .flexbox and .flexboxlegacy in your CSS with Modernizr. i mean unless your heart is completely set on having your flex boxed layout show in IE9. i tend to leave older browsers behind when it comes to stuff like this. if they don’t have flex box, then they just get the non flex boxed layout. then again, i’m only using flex box for larger screens targeted with media queries, so yeah I wouldn’t recommend flex box for a default layout.
Anyone know of a good polyfill that can fill in support for IE8 or at least IE9 with this syntax? Has anyone tried Flexie?
Not a complete polyfill but here’s how you can do something similar in IE8 and IE9: http://codepen.io/CalebKester/pen/eLDzm
Note, that was pretty quickly done but shows you it’s still is possible to get the core layout done. You have to reorganize your html but it’s still not that bad.
The advantages of FlexBox (in answering Andy Howells’ question) are not only the ordering, but mainly the automatic filling of spaces and very clever positioning:
• You can position an element in a parent in much better ways (centre, centre bottom, top right, etc.) without having to
position: absolute;
• You can have equal0height columns and columns that automatically fill horizontal space (as seen here), and these can also fill the space following ratios
• All positioning is made simpler (although it is an almost new syntax to learn)
I never really fully realized the power of flexbox until i just googled for flexbox polyfill and came across this awesome library called Flexie:
http://flexiejs.com/playground/?random
Unfortunately it only supports the old model, but it seems to do so quite well. If nothing else, the awesome playground i linked to gives you a great understanding of the capabilities of flexbox. I really had no idea!
Demo works great on Windows Phone 8
Yup, works great – not much surprise there though, since mobile IE10 runs basically on the same rendering engine as desktop one.
Just a heads up, flexie.js uses the OLD syntax so you should probably avoid it until its updated. The developer has posted it’s ~35% complete currently.
https://github.com/h5bp/html5please/pull/221
Nokia Lumia windows phone IE. If you’re in the details mode of codepen and rotate to landscape the container takes up half width. Portrait looks ok in edit mode but not detail.
Codepen in portrait mode doesn’t take up the full width though. I can send you screenshots if you want.
It seems to me that the ideal way to proceed, if you want to use flexbox, is to only use the latest syntax, and simply provide an alternate layout for browsers that don’t support it.
Example (of an element that’s inside a flexbox container:
Sure, make two completely different layouts for the same website. As if we don’t have to do enough anyway.
Pretty neat stuff Chris. Was wondering if anyone had an idea of support on BlackBerrys. Over 70% of the mobile traffic we get from the company I’m with comes from BlackBerry devices and can be really frustrating. Unfortunately, BrowserStack doesn’t support BlackBerry devices at the moment (._. )
Hey Chris!
Tested on IE9 mobile (Nokia lumia 800) and the divs kept static like you did nothing.
Never know about Flexbox before. Thank you for writing detailed article on using Flexbox. I like ordering of elements based on priority, pretty cool. I think there is a lot of room to improve your code, still very useful. I tested it on IE10 and its working fine.
Cool! Here’s everything from this post in Sass mixin form: http://codepen.io/bensmithett/pen/neuyI
Thanks for the Sass mixin Ben! I took the liberty of converting it to SCSS for anyone who wants to use that sytax:
http://codepen.io/adamjohnson/pen/savzI
There’s actually a few things that can’t be directly translated between the specifications, so you can’t just drop your values into the prefixed properties like that. There’s subtle differences between the specs like “flex-start” vs “start” or “space-between” vs “justify”. The “order” property indexs at 0, while “box-ordinal-group” indexes at 1.
Compass users can use these mixins (I plan on submitting them to the Compass project once I’m confident they’re good): https://gist.github.com/cimmanon/4461470
It should be noted that no browser following the 2009 spec ever implemented wrapping. Despite Firefox adding support for the standard spec, they’re excluding support for wrapping for a while.
I just tested with FF19 beta. Had to set
layout.css.flexbox.enabled = true
inside about.config, but that made it work even without-moz-box-flex: 1;
Oh, and the
-moz
-Prefix will be dropped soon (see here)It appears that Dominic is correct. Changing the
layout.css.flexbox.enabled
totrue
appears to fix the issues you were experiencing in Firefox. Great article nonetheless and thanks again, Chris. I look forward to being able to use Flexbox reliably across browsers in the very near future.Nice to see ARIA landmarks being used too ;)
I’ve made a small experiment to play with flex box and created a sort of flexible font :
http://etienne.pouvreau.free.fr/#fantome
Just for fun & testing of course :-)
Your post will help me to make it better… Thank you.
Pretty good method, it will be widely used in future.
Now if only Compass had a mixin that would do all of this stuff for me…
One major limitation I’ve found with flexbox is that it only works on direct children. This is a major issue when your content elements are part of a column placeholder, rather than a single main parent as this article shows. A full explanation of this issue:
http://stackoverflow.com/questions/14148162/does-the-css-flexbox-module-work-on-direct-child-elements-only
My only main concern is the lack of IE support (I think for < IE10). At this stage I just cannot justify using Flexbox in a commercial manner.
Great to have such a decent support for Flexbox, but what’s it worth if you have to come up with an alternative solution for almost every IE?
I’m a big advocator for graceful degradation and usually don’t care much about oldIE, but in the case of Flexbox it’s not ready for production work until oldIE dies out (which won’t happen) or there is a polyfill. If you just have to care about Webkit, i.e. Apps, Flexbox is definitely the way to go, but for a normal website it’s by far too much effort in my eyes.
BTW, here’s a decent overview of mine for the new Flexbox syntax: http://www.sitepoint.com/flexbox-css-flexible-box-layout/
Firefox has a bug with (setting widths in percentage)[https://bugzilla.mozilla.org/show_bug.cgi?id=529761]
people invented
<
table> again
Except that flexbox is semantic and responsive.
Right…
Gr8 Article :)
it is very easy to use and implement
Flexbox gets me excited about CSS again. Now if only there were a solid polyfill, at least for IE9.
Thanks you very much chris…. test it on IE10 working superb !
Great info. This post shows the current state (2/22/13) of Flexbox: What an effin’ disaster.
Looks interseting and I can definietely see the benefit, but IE10+ support kills it for me.
Will this method require ‘skip to nav’ links, or is it quick enough to tab past the content?
@Peter, Not sure if I misunderstood your comment, but instead of using the ‘skip to nav’ links (which I think it would be ‘skip to main content‘ or ‘skip navigation‘ instead), you could use WAI-ARIA Landmark Roles.
According to WAI-ARIA Best Practices Editors’ Draft:
Landmarks are a vast improvement over the rudimentary “skip to main content” technique employed prior to WAI-ARIA. If possible it is best to use these as landmarks.
Cheers.
Shouldn’t source/dom and visual order match?
110% agree.
Not only causes usability issues but there are also serious SEO implications as well.
Your source code order should reflect your content hierarchy.
Usually Mobile IEs have the same features as their desktop counterparts. So Windows Phone 7 with IE9 wouldn’t support Flexbox, but on Windows Phone 8 with IE10 it should work with your “tweener” solution.
I actually have put together a LESS Mixin Project to make this easier. Check out the demo page!
how does one style an element based on its order in a flexbox? nth-child(n), first-child etc work on position in mark-up
but what about styling for the element with order:1.
is this possible since this requires css matching against presence of another style???
It’s a bit of a hack, but to work around the FF percentage bug, you can use -moz-calc and the vw unit. Subtract the body margin (8px twice) and padding (2em twice) from the full viewport width, then multiply by a decimal instead of a percentage (.2):
-moz-calc((100vw - 4em - 16px) * 0.2)
. Obviously not a good solution for more than the most basic formulas.Wondering why page is being refreshed upon submission, rather than using some sort of jQuery to update the page!
Sorry for all this garbage! I’m just testing.
Feel free to remove my posts.
That’s really awesome! Finally CSS has something that allows us to have fixed-width sidebars with flexible-width content column! Up till now, only damn old table was able to accomplish it!
I made a little test, setting min-width and max-width together with %-based width to sidebars and leaving content with no width set. It worked great. If I lower browser width, content gets very narrow and sidebars remain with min-width. And if I get browser in my 3 monitors, content gets very large while sidebars stay on their max-width! If I use column css attributes in content, I’m able to get a really nicely readable website optimized for large monitors!
Now I must find a way to hide/move to bottom both sidebars when in wacky-ugly-devil-born phones :p
I write a test case. It looks fine in chrome, but it doesn’t seem to work for IOS.
IOS 6.1 uses the OLD syntax.
http://jsbin.com/aqunam/1372/edit/
The concept is simple, I have a container box with three item in it. However, the width don’t distributed equally in container.
What am I doing wrong?
with table and 3d transform:
http://codepen.io/yukulele/pen/KLsnv
jQuery code, much shorter….
$(document).ready(function(){
$( “.main-content” ).insertAfter( $( “.main-nav” ) );
});
Ist it possible to use a fixed width for the sidebars?