Fun with Flexbox
In the course of the past few days I have discovered parts of CSS that I never knew existed, but have often wished did in some form or another. Amongst these is the calc() function which lets you calculate values for properties, such as calc(100% - 3em).
The one I’m most excited about for the moment is Flexbox or the Flexible Box Layout Model. I first discovered this from Paul Irish, on his flexbox tutorial over on html5rocks.com however as warned I soon discovered the issues with the changing spec of flexbox and the many versions implemented (or not implemented) by different browsers.
The issue is as browsers implement moving specification and then it changes drastically so much to break everything. So now there exists the 2009 spec (display: box) which is in quite a few browsers, some mixed up 2011 stuff from a transitionary period which doesn’t exist in browsers but is scattered across the internet in various guides as ‘how to use the new flexbox’ (display: flexbox) and lastly the current implementation (at time of writing) which is implemented (at least partially) in all modern browsers.
From what I can see there don’t seem to be many guides (if any) that cover the current specification. So mostly for my benefit in any future working with flexible box layout here’s my quick summary of flexbox, I hope it helps anyone else who happens to stumble across my blog.
The css properties you need are:
- … flex …
- sets the display mode to flex - this needs to be a wrapper/container for the items.
- Shorthand setter for the listed properties. Sets how the items fill the space.
- Flex grow factor. Sets the ratio to grow by compared to the other flex items.
- Flex shrink factor. Sets the ratio to shrink by compared to the other flex items.
- Like width, sets the main size before the free space is distributed according to grow & shrink
- Shorthand setter for the listed properties. Sets how the items are laid out.
- **row** | row-reverse | column | column-reverse
- How the items are laid out horizontal, vertical or reverse ordered.
- **nowrap** | wrap | wrap-reverse
- Selects if all items have to be on a single line, or multiple lines are allowed.
- **flex-start** | flex-end | center | space-between | space-around
- How items are distributed in space, only effective when flex factors are not set as it's calculated afterwards. Affects alignment on the main axis.
- flex-start | flex-end | center | space-between | space-around | **stretch**
- How items are distributed in space, only effective on multiline (flex-wrap). Affects positioning on the cross axis.
- flex-start | flex-end | center | baseline | **stretch**
- Same as justify-content but in the perpendicular axis. Affects alignment on the cross axis.
- **auto** | flex-start | flex-end | center | baseline | stretch
- Same as align-items, but this is set on the individual items. Affects alignment on the cross axis.
- The display order for the items. Laid out in ascending order, unless reverse is set in the direction.
For making this all work in Chrome (and other webkits - though they are not fully compatible yet) the
-webkit- prefix needs to be added to all the properties, other than display which needs it added to the value ie.
And then I got to firefox which ‘supports’ it. Or rather it will support it in version 20 (stable at time of writing is 17, Dev/Aurora is 19). In 18 and 19 it can be enabled by changing the flag
layout.css.flexbox.enabled to true and even then only single line is supported.
Making my layout
So the project I’m working on that brought this flexboxing all about needs a header/footer with left, right & centre, and centred content that always stays in those relative positions no matter what the display size is. This is why flexbox is ideal in my situation, however I would say building an entire website structure from flexbox for the majority of applications is probably not a good idea. The best layout model is probably CSS Grid, however as no browser has got round to implementing it yet, that wil have to wait.
My standard method for doing such a layout would be floats, however I wanted to give this a go. So taking my code: