Mark Eschbach

Software Developer && System Analyst

Holy Grail Layout using Flex

Back in the heyday of CSS2 the holy grail layout was much sought-after and could be very difficult to build. At the crux of the layout, there were up to five sections. The header and footer would span the entire width of the page. Within the center section there were three panels, consuming the entire horitonzal area. Generally, the two flanking panels would contain a predetermined width, while the center was intended to consume the remainder.

A common method was to utilize floats, however keeping the entire horizontal area consumed was difficult. The CSS Flexible Box ("Flexbox") Layout Module was released in September 2012 and greatly eases the layout of this center section. Most browsers, such as Chrome, Firefox, and IE11, have implemented the core features. We can implement the layout using two flexes. One outer flex for describing the vertical layout intents with the header, primary content area, and footer. The second flex will be applied to the primary content area to describe the horizontal layout of the content section.

Describing the heights

The first task at hand is to change the direction of the layout from horizontal to vertical. For this the flex-direction property may be given the value column. From here, all elements will stack vertically.

The vertical space constraints on this layout are simple. The header and footer should fit their content naturally, however they should neither grow nor shrink with the window. The main area should at least fill the remaining vertical area availble within the window. flex uses two properties to determine space distribution: flex-shrink controls how many pixels are removed from an element when the screen real estate is too small; while flex-grow controls how many pixels are added to an element when more space is available in the parent element than the child.

flex-grow and flex-shrink both use an abstract unit, not directly tied to pixels. Depending on the operation, growing or shrinking, space is distributed based on the number of units multiplied by the change in logical pixels. Setting either property to 0 will result in no changes when that operation is to occur.

Peachy. Now time to apply this to the layout. (TODO: Needs to be displayed better)

body {
	min-height: 100vh;

	display: flex;
	flex-direction: column;
}

header, footer {
	flex-grow: 0;
	flex-shrink: 0;
}

main {
	flex-grow: 1;
	flex-shrink: 1;
}

Making the folds

Or, ya know, the left and right hand gutters. To make these, use the default flex-direction of row. Using the same technique above, we fix the left and right gutters of the main content area.

main {
	display: flex;
}

main > div.left-gutter, main > div.right-gutter  {
	flex-shrink: 0;
	flex-grow: 0;
}
main > div.center {
	flex-shrink: 1;
	flex-grow: 1;
}

IE10 Compatability

Prior to this, MS jumped the wagon to implement the Candidate Recommendation for IE10, which causes some incompatability. Microsoft thankfully uses an augmented set of properties and values to make our lives easier. The value -ms-flexbox is mostly equivalent when using the associated vendor-prefixed properties. Setting the direction utilizes the property -ms-flex-direction, which for the veritcal segment needs to be set to column overriding the default row. With this vendor extension you may not set the flex grow and shrink properties individually. The property -ms-flex takes three values: the growth rate, shrink rate, and the perfered size which defaults to auto.

/*
 * Vertical space
 */
body {
	min-height: 100%;

	display: -ms-flexbox;
	-ms-flex-direction: column;
}

header, footer {
	-ms-flex: 0 0;
}

main {
	-ms-flex: 1 1;
}

/*
 * Horizontal display
 */
main {
	display: -ms-flexbox;
}

main > div.left-gutter, main > div.right-gutter  {
	-ms-flex: 0 0;
}
main > div.center {
	-ms-flex: 1 1;
}