
Flexbox or ‘The Flexible Box Layout Module’, to give its official title, has had quite a colourful history given its short lifespan. Flexbox is a completely new way to think about layout. It has been designed from the ground up to be a superior alternative to using floats and bending CSS to our layout whims in ways the original authors never intended. It was conceived with web applications and the advanced sorts of responsive layouts that we’ve become accustomed to.
First introduced in 2009, it’s already been through three revisions – each supported to varying degrees by browsers. We’re going to be covering the latest version, released in September 2012. The W3C recommend its use and outside of Internet Explorer (only version ten supports the June 2012 syntax) it enjoys 76.52 per cent browser support. Additionally, Chrome announced that it was going to unprefix the properties, which is great news as it will now be joining Firefox and Opera. The fundamental changes Flexbox brings to CSS can be daunting at first but this tutorial will guide you through building your first responsive Flexbox site and show you just how easy it is.
Box sizing
We’ll start by adding box-sizing: border-box; to all of our elements. This causes padding to be included within the calculated width of an element – so if you have two elements with 50 per cent width and 1em of padding they will sit nicely beside each other. The only browsers that have issues with this are <IE8.
{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
Flex it
Here we come to the core of the module. To declare an element as a Flexbox element we simply add display: flex. Unfortunately this isn’t straightforward if you want to cover all possible bases – if you are supporting the buggy implementations then you’ll have to add a few more – but the following will cover all modern browsers.
.flex {
display: -ms-box;
display: -webkit-flex;
display: flex;
}
Navigation HTML
Our aim is to create a stripped down version of the Wikipedia homepage, exclude all content and leave nothing but the bare boxes. The difference will come in how easily we can adjust this to different widths (hint: it’s not called flex for nothing). We’ll start with the navigation on the left-hand column.
001 <nav class=”site-navigation flex”> 002 <ul> 003 <li>Home</li> 004 <li>About</li> 005 <li>Contact</li> 006 </ul> 007 </nav>
Containers and items
Flex elements have a host of properties available to them. There are two important distinctions to make: flex containers and flex items. Containers are the elements with display: flex; the immediate children are known as flex items. We’ll add some basic properties here to visually separate the navigation.
001 .site-navigation
002 {
003 background: lightblue;
004 margin-right: 1em;
005 padding: 1em;
006 }
Flex columns
The following properties position the flex items vertically (by using column), while the default layout is to display them horizontally (known as row). Each flex item will be positioned vertically along the ‘main axis’ (explained in the diagram). The main axis is the x axis in flex-direction: row and along the y axis in flex-direction: column.
001 .site-navigation {
002 -webkit-flex-direction: column;
003 -ms-flex-direction: column;
004 flex-direction: column;
005 }
Flex property
The flex property is shorthand (like margin: 0 1em 2em 0; instead of margin-right) for flex-grow, flex-shrink, and flex-basis, ie how much you want it to grow/shrink compared to its siblings and how wide it should ideally be. If there is a flex of 2, it will shrink/grow at twice the rate.
001 .site-navigation {
002 -webkit-flex: 1 13em;
003 -ms-flex: 1 13em;
004 flex: 1 13em;
005 }
Self-alignment
Flex items have a property of their own called align-self which allows specific items to be aligned separate to its siblings. In this instance we want the navigation to sit with the natural flow (left on left-to-right languages and right on right-to-left languages) but the logo to sit centrally – while still maintaining its flexibility.
001 .site-navigation .logo {
002 -webkit-align-self: center;
003 -ms-flex-item-align: center;
004 align-self: center;
005 }
006 nav ul {
007 list-style: none;
008 }
Main markup
We’ve concentrated on the navigation layout, now let’s turn our attention to the rest of the design. The great thing about this is the navigation will stretch the entire height of the page without any JavaScript or absolute positioning. We’ll also use the HTML 5.1 element Main to signify the main content for the page.
001 <main role=”main” class=”flex”> 002 <!-- nav --> 003 <section> 004 <header> 005 <h1>I am a header, I rule all below me.</h1> 006 </header> 007 <!-- next step --> 008 </section> 009 </main>
Flexible elements
We’ll place this inside the section tag – the markup is fairly typical of a content pod that has a heading, some text, and an image. We’ll repeat this twice so we have two articles side by side and a third beneath them both spanning the entire width. Certain browsers require margin: auto to ensure images sit correctly.
001 <div class=”flex”> 002 <article> 003 <h2>Header</h2> 004 <p>Lorem ipsum</p> 005 <figure> 006 <img src=”http://placekitten. com/g/500/500” alt=”A cute kitten.”> 007 <figcaption>A cute kitten.</ figcaption> 008 </figure> 009 </article> 010 <!-- repeated --> 011 </div>
Article flexing
Next we want our articles to sit side-by-side but not have a defined width, so they sit nicely in the parent element. To do this without resorting to floats we use the shorthand flex property again; this is the equivalent of saying that both items should grow and shrink at the same rate as each other.
001 section article {
002 -webkit-flex: 1;
003 flex: 1;
004 padding: 1em 1em 0 0;
005 }
Responsive images
There’s just one last technique before we get into building its responsive layout. By setting a maximum width of 100 per cent on all images used, we are ensuring that they will never spill over their container. This doesn’t really beat serving the right size images in the first place, but with fluid layouts that change on orientation and resize this isn’t always possible and can be difficult.
001 img {
002 max-width: 100%;
003 }
Media query
Just in case you’re not familiar with media query syntax, we’re telling the browser that only devices with screens with a maximum width of 50ems (this equates to 800 pixels given a base font size of 16px on the body element) should apply the following rules:
001 @media only screen and (max-width: 50em) { /* 800/16 */
002 /* next step */
003 }
Adjusting articles
Next we’ll use the nth-child selector to select the first article and tell it to flex, or grow, at twice the rate of its sibling. Using this simple property we can expand items that may be of more importance at different widths. In this case, the first article will take precedence.
001 section article:nth-child(1) {
002 -webkit-flex: 2;
003 -ms-flex: 2;
004 flex: 2;
005 }
Small screen widths
Our next breakpoint will be at 40em (which equates to 640 pixels with our base font size) and deliver our single column layout. Although 640 pixels is a common breakpoint it’s important to add breakpoints when it feels right for the content to change, not just because certain devices adhere to it.
001 @media only screen and (max-width: 40em) { 002 /* 640/16 */
003 body {
004 padding: 0 1em;
005 }
006 /* next steps */
007 }
Changing direction
In one fell swoop we can convert our entire layout to a single column that is optimised for smaller widths. By changing the flex-direction we change the main axis (the one that flex items are aligned across) from horizontal to vertical which causes it to behave as though all our elements with the class of flex have display: block on them.
001 .flex
002 {
003 -webkit-flex-direction: column;
004 -ms-flex-direction: column;
005 flex-direction: column;
006 }
Change flex basis
Remember that the flex property is shorthand for flex-grow, flex-shrink, and flex-basis? Now the navigation is stretching downwards with a height of 13em but we want it to simply be the height of it’s contents (auto). There’s no IE10 equivalent to flex-basis so it’ll look slightly larger unless you manually set a height.
001 .site-navigation {
002 margin-right: 0;
003 -webkit-flex-basis: auto;
004 flex-basis: auto;
005 }
A new order
We’re going to move the navigation list before the logo. One of the most exciting things about Flexbox is that it can move where items are on the page without having to use JavaScript to move elements around. This is easily done by changing the order property – but it must be a positive integer, so no 1.1 or -13 values.
001 .site-navigation ul {
002 -webkit-order: 1;
003 -ms-flex-order: 1;
004 order: 1;
005 }
Moving the logo
All items have an order of 0 unless specified so we’ll change the order property on our logo to move it beneath the navigation. Note that IE10 uses the older syntax so has a slightly different property name. That’s all there is to it! You should now see the logo dip beneath the navigation on small-screen widths.
001 .site-navigation .logo
002 {
003 -webkit-order: 2;
004 -ms-flex-order: 2;
005 order: 2;
006 }
Adding boxes
We’ve made some big blocky elements flex and bend to our layout but we haven’t looked at the items within them much. They’re capable of flexing just as much as their container and there’s some very easy ways to accomplish complex layouts. First we’ll create some coloured boxes to play with.
001 .small-box {
002 width: 6.25em; height: 6.25em;
003 border: 0.0625em solid;
004 background: #E74C3C;
005 }
006
007 <div class=”justify”>
008 <div class=”small-box”></div>
009 </div>
Justifying placement
We want our boxes to sit neatly alongside each other with an even amount of spacing between them, no matter what the widths. We could do something complicated with margins and percentages, or we could just use the justify-content property with a value of space-between – another useful value is space-around.
001 .justify {
002 display: -webkit-flex;
003 display: -ms-box;
004 display: flex;
005 -webkit-justify-content: space-between;
006 -ms-flex-pack: justify;
007 justify-content: space-between;
008 }
Inline flexing
We’re basically done with our responsive layout but there’s another important display value to cover: inline-flex. Like other inline elements, this will collapse its width to that of its items. Applying it to our justify class causes the boxes to sit next to each other as justify-content doesn’t have extra space to distribute them.
001 .justify {
002 display: -webkit-inline-flex;
003 display: -ms-inline-box;
004 display: inline-flex;
005 }
Bi-directional
Flexbox is a powerful tool that can be used to develop complex layouts using relatively little CSS. Browser support isn’t brilliant but it is getting there. One final bonus, it all switches direction so if your users read right-to-left then your layout can easily accommodate it thanks to it’s direction agnosticism.
001 body {
002 direction: rtl;
003 }