Future of CSS: The Flexible Box Model

As always with this new fangled CSS, support is pretty thin on the ground. Here’s a list of the properties and how they’re supported, in no particular order. (As of February 15th, 2010)

Gecko
Firefox
Webkit
Chrome/Safari
Trident
Internet Explorer
Presto
Opera
box-flex Yes* Yes No No
box-direction Yes* Yes No No
box-align Yes* Yes No No
box-flex-group Yes* Yes No No
box-lines Yes* Yes No No
box-ordinal-group Yes* Yes No No
box-orient Yes* Yes No No
box-pack Yes* Yes No No


* Only Supported with the prefix -moz (i.e. -moz-box-pack
Only Supported with the prefix -webkit (i.e. -webkit-box-pack)

‘course, as you’ve probably realised it wouldn’t have mattered what order they were in anyway, since only Firefox and Chrome/Safari support the flexible box model at this point. This is a bit troublesome, since we can’t go ahead and use this in all our projects because it’s not supported by Internet Explorer (>60% of market) or Opera (about 2%). In the future though this is really gonna improve how we make websites (when it’s supported by everyone).

In fact the way that Gecko and Webkit support the box model is completely different, so I’ve tried to give you as much solid information as I can from observations on both platforms.

How it Works

Nowadays websites are often split into many columns, to accomplish a sort of newspaper-esque layout. Of course, we can accomplish this with the float property in CSS2, but CSS2 really wasn’t designed with an easy way to make columns. Traditionally web designers would design columnar layouts like this:


#left-column {
      float: left;
}

#right-column {
      float: left;
}

Initiating your Box

With the flexible box model things are a little different, but different in a good way. Words can’t describe how wonderful I think this specification is, so I’ll use code instead. Here’s a piece of code that I want to columnize, so to say.

<div class="container">
	<div class="blue">
		This is some content.
	</div>
	<div class="blue">
		Only there are four columns!
	</div>
	<div class="blue">
		Four columns!
	</div>
	<div class="blue">
		Amazing.
	</div>
</div>

And here’s the CSS:

.container {
        width: 1000px;

	display: -webkit-box;
	display: -moz-box;

	-webkit-box-orient: horizontal;
	-moz-box-orient: horizontal;

}

.blue {
	background: #357c96;
	font-weight: bold;
	margin: 2px;
	padding: 20px;
	color: #fff;
	font-family: Arial, sans-serif;
}

It’s as easy as that! (It’ll be even easier when we don’t have to do browser specific elements). You can totally ignore the .blue class, that’s just some styling. The container class sets the display mode to box, and sets box-orient to horizontal. This gives you something like this:

You can also set the box orient to vertical if you wish for vertically stacked divs.

Box Flex

As you probably have already figured out, the actual structure of these elements looks like this:

As you can see there’s a bit of a gap at the end of the 4th column element. This is where the box model is so useful. Whereas before you would have to juggle around with pixels until you finally got a good combination where the columns filled the space. With the flexible box model you can stretch out certain elements to fill the space.

.flexible {
        -webkit-box-flex: 1;
        -moz-box-flex: 1;
}

If we were to add this flexible class to the 3rd column element, you would end up with this:

The remaining space is divided amongst the elements by their box-flex. Since there is only one box-flex element, all the extra space is given to the element with a box-flex of 1. If you had 2 box-flex elements with a value of 1, the space would be distributed evenly between these two.

For instance, lets say you gave the first 2 column elements in our example the ‘flexible’ class. Both elements would have a box-flex value of 1, so you would end up with something like this:

If you’re more mathematically minded you can think of it as if the two columns are in a 1:1 ratio, so the space is spread out in a 1:1 ratio.

So, for example, if there was 400px of extra space, each element would get an extra 200px. Similarly if one of the box-flex properties were 3, the two elements would be in a 3:1, so one box would get 300px extra, while the other would gain 100px. This allows you to easily expand your boxes to your needs.

Orientation

Orientation i another key element to the flexible box model. Lets take a look at our earlier example. We could reverse the order (so it would be going 4, 3, 2, 1 instead of 1, 2, 3, 4) by adding this to our container element:

        -moz-box-direction: reverse;
        -webkit-box-direction: reverse;

You can use the box-ordinal-group element to alter the position of columns too. Simply put, the element with the highest box-ordinal-group will be moved to the end. If you have set box-direction to reverse, the end will be the left hand side, otherwise the right hand side will be the end. An example of a box ordinal group may be as follows:

        -moz-box-ordinal-group: 2;
        -webkit-box-ordinal-group: 2;

Alignment

Aligning boxes is pretty easy to do. There are two properties you want to watch out for. box-align and box-pack.

If you have your boxes orientation set to horizontal, then box-align will decide how that element is aligned vertically inside your box. Similarly if it’s set to vertical, it will decide how its aligned horizontally. The box-pack element is the complete opposite, applying to horizontal when your box is orientated horizontally, and vertical when your box is orientated vertically. Using both you can center your box elements in any way you want when there’s some extra space left over.

A Recap

Here are all the elements again, their default properties and the properties you can apply to them.

Default Possible Values
box-flex 0.0 number
box-direction normal normal | reverse | inherit
box-align stretch start | end | center | baseline | stretch
box-flex-group 1 integer
box-lines single single | multiple
box-ordinal-group 1 integer
box-orient inline-axis horizontal | vertical | inline-axis* | block-axis* | inherit
box-pack start start | end | center | justify

*inline-axis and *block-axis are equivalent to horizontal and vertical respectively.

And here’s a quick reference table so you can see what each element does.

Function
box-flex Allows the boxes children to “flex out” and expand into the space left over at the end. Can be put into a ratio by giving one element a box-flex of 2, and another a box-flex of 1, giving them a 2:1 ratio
box-direction The direction the boxes children should go in. Normal or revere.
box-align Set how the boxes children are aligned in the box. If the orientation i horizontal it will decide the alignment vertically and vice-versa
box-flex-group Assign a group to flexible elements
box-lines Normally the column will continue on forever in the orientation you chose. If you set box-lines to multiple, the columns will go onto a new line whenever it runs out of space in the parent box.
box-ordinal-group Determines how the boxes children are ordered. A smaller box-ordinal-group will go to the beginning of the box, while a bigger one will go to the end. The start is the left if the direction is normal, and vice versa if it’s reverse.
box-orient How the boxes children should be aligned. Horizontal to stack them horizontally, and vertical to stack them vertically.
box-pack Sets the alignment of the box along the box-orient axis, so if box-orient is horizontal it will chose how the boxes children are aligned horizontally, and vice versa.

Where do I go from here?

Did you find this useful? Please share this and check out some related posts! We'll love you forever

Don't forget, if you loved reading this as much as I loved writing it, follow me on    twitter or maybe    subscribe to our rss feed. Heck, you could even    like us on facebook.

 

Share This

   



1 Wonderful Comment

  1. Humberto Gengler says:

    Really great, practicly explained and useful tips.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>