CSS3 Layouts with Horizontal Alignment

Works with Safari, Chrome, Firefox, iPhone, iPad, Android

One of the most common features in modern Web layouts is to have some with a fixed width on one side or on both sides, with the rest of the space taken up dynamically. This is usually accomplished by floating the first item to the right and the second item to the left, or by using relative and absolute position. With CSS3 there is another, better way. No floats, no clearing floats, no positioning. Instead we use the properties of the flexible box model. The magic all starts with a new display property: box. At the moment, you’ll need to use the -moz and -webkit prefixes to implement these features. They have been supported since version 3 of both Firefox and Safari. If the majority of your users are on Firefox, Chrome and Safari, or if you’re targeting the mobile Web, you can go ahead and use these properties today and achieve the kind of layouts that previously required complex CSS frameworks or JavaScript libraries like YUI or Ext.js. The flexible box model allows us to create the equivalent of stack panels and wrap panels with HTML.

Let’s get started. We’ll create and HTML5 document with a header tag. We’ll style the header and style two links inside it to look like buttons:

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Flexible Box Model Example One</title>
	<style type="text/css">
		html, body {
			margin: 0px;
			padding: 0px;
			font: normal 14px/16px Helvetica, Sans-serif;
		}
		header {
			/* The following line is for Firefox */
			width: 100%;
			padding: 5px 0px;
			background-image: -moz-linear-gradient(top, #b0bccd, #889bb3 50%, #8195af 50%, #6d84a2); 
			background-image: -webkit-gradient(linear, left top, left bottom, from(#b0bccd), color-stop(0.5, #889bb3), color-stop(0.5, #8195af), to(#6d84a2));
		}
		.button
		{
			color: #fff;
			text-decoration: none;
			display: block;
			padding: 4px 10px;
			-webkit-border-radius: 5px;
			-moz-border-radius: 5px;
			font: normal 14px/16px Helvetica, Arial, sans-serif;
			cursor: pointer;
		}
		
		.button.black {
			background-image: -webkit-gradient(linear, left top, left bottom, 	
				from(#7d828c),
				color-stop(0.5, #303749), 
				color-stop(0.5, #121a2e), 
				to(#121a2e));
			background-image: -moz-linear-gradient(top, #7d828c, #303749 50%, #121a2e 50%, #121a2e);
			border: solid 1px rgba(79, 79, 79, 0.75);
		}
		.button.black:hover {
			background-image: -webkit-gradient(linear, left top, left bottom, 
				from(#4286f5), 
				color-stop(0.5, #4286f5),
				color-stop(0.5, #194fdb),
				to(#194fdb));
			
			background-image: -moz-linear-gradient(top, #4286f5, #4286f5 50%, #194fdb 50%, #194fdb);
		}
		.button.back {
			margin-left: 20px;
		}
		.button.next {
			margin-right: 20px;
		}
	</style>
</head>
<body>
	<article>
		<header>
			<a class="button black back">Back</a>
			<a class="button black next">Next</a>
		</header>
	</article>
</body>
</html>

This will give us a layout like this:
Initial setup for a header tag that will use the flexible box model

Now we’ll add the magic. All we have to do is give the header tag a definition of display: box, then tell it which orientation to arrange its child elements and how to pack them in. We just need to add these properties to the header tag’s CSS:

display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack:justify;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-pack:justify;

By telling the browser to pack the child elements with justification, the browser takes all the space not occupied by the buttons and spreads it out between them. This works as expected in all Webkit based browsers. Unfortunately, although Firefox has implemented every other feature of the flexible box model, they have not as yet implemented the box-pack: justify property. It’s listed on their developer site with a question mark: https://developer.mozilla.org/en/CSS/-moz-box-pack

In the next section of this post I’ll introduce a technique that requires some extra markup that will make this work in Firefox too. For now, here is how this looks in Webkit:
Header tag with buttons aligned at both end using the flexible box model

You can see it in action, or download the document.

Adding Centered Content With Dynamic Width

Now we’ll look at how to add a title into our heading. Since we already have two buttons at either end, we’ll want our title to be centered. We’ll add an h1 tag to the header directly between the two buttons:

<body>
	<article>
		<header>
			<a class="button black back">Back</a>
			<h1>Home Base</h1>
			<a class="button black next">Next</a>
		</header>
	</article>
</body>

We also need to give the h1 some suitable styling. We’re going to make it white with an indented look using a text shadow:

h1 {
	font: bold 21px/21px Helvetica, Arial, Sans-serif;
	text-shadow: 0px -1px 0px rgba(0, 0, 0, 0.5);
	color: #fff;
	margin: 0px;
	-moz-box-flex: 1;
	text-align: center;
}

This gives us the following in Webkit:
Buttons on either end and title centered

Unfortunately, Firefox still needs a couple more lines of code to get it right. Here’s what we have at the moment:
Firefox having problems implementing the flexible box model

There is one more flexible box model property that we can apply to the h1 so that Firefox will display it as we want, that is box-flex. If we give this property a value of one, it tells the browser to have that elements width the equivalent of all left over space from whatever other sibling elements are in the same parent tag. We’ll also need to apply text-alignment to center the text:

h1 {
	font: bold 21px/21px Helvetica, Arial, Sans-serif;
	text-shadow: 0px -1px 0px rgba(0, 0, 0, 0.5);
	color: #fff;
	margin: 0px;
	-moz-box-flex: 1;
	text-align: center;
}

Now Firefox display the header as we want:
h1 { 	font: bold 21px/21px Helvetica, Arial, Sans-serif; 	text-shadow: 0px -1px 0px rgba(0, 0, 0, 0.5); 	color: #fff; 	margin: 0px; 	-moz-box-flex: 1; 	text-align: center; }

You can check out the finished page, or download it.

Update: October 5, 2010

I’ve update these buttons to use subpixel rendering. You can read about the technique here. You can try this out online or download the source code.

About these ads

About Robert Biggs
Front end Web developer skilled at creating interactive, dynamic interfaces using HTML5, CSS3, JavaScript, SVG. Passionate about developing awesome user experiences in the mobile space.

Comments are closed.

Follow

Get every new post delivered to your Inbox.

Join 45 other followers

%d bloggers like this: