CSS: create layouts with table values

In this article I'll explain how to use the table values of the CSS display property to format certain sections of a simple three-columns layout.

The final layout is shown in the picture below.

The relevant sections that will be formatted with such values are highlighted in the following picture.

Navigation, sub-header and post title

We start with the following markup:

<div id="header">
<h1>CSS Magazine</h1>
<ul id="nav">
<li><strong>Home</strong></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Tests</a></li>
<li><a href="#">Tutorials</a></li>
</ul>
</div>

As you can see, the navigation menu (#nav) is contained in the #header section, where there is also the main title of the page (an h1 element. The styles could be the following:

#header {
height: 8em;
min-height: 80px;
border-bottom: 1px solid #333;
background: #fff url("img/banner.png") no-repeat 0 0;
position: relative;
}
#header h1 {
position: absolute;
top: -1000em;
}
#nav {
display: table;
position: absolute;
top: 0;
right: 0;
height: 100%;
border-left: 1px solid;
margin: 0;
padding: 0;
border-collapse: collapse;
width: 15%;
}
#nav li {
display: table-row;
}
#nav li a, #nav li strong {
display: table-cell;
border: 1px solid #000;
font-size: 120%;
width: 100%;
padding: 0 0.3em;
text-decoration: none;
}
#nav li a:hover {
background: #800;
color: #fff;
}
#nav li strong {
background: #800;
color: #fff;
}

View the example - View the screenshot

The first two rules give a basic formatting to our header. We've set a height in ems and a minimum height in pixels. The latter equals the height of the background image that we'll use as a banner. A minimum height gives a full visibility to our background image even when the user decreases the base font size or when the specified font used on the page is not available. The last declaration of the first rule creates a new context positioning through the value relative of the position property. Thanks to this declaration, we can absolutely position our navigation menu by taking the header section as a reference and not the whole viewport. Then we want to get rid of the heading's text, since it must be replaced by the background image. We use absolute positioning with an enormous negative value for the top property. This value will actually make the text disappear from the page.

Then comes our navigation menu. The first declaration of the third rule turns our unordered list into a table. Since we're working now with tables, we should be sure that there will be no extra space between the cells. For that reason, we use the border-collapse property set to collapse. By doing so, the borders of the single cells will collapse to form an unique border. Tables can be floated and absolutely positioned, since they're actually block-level elements or, more precisely, elements that work in a block-level formatting context. Our menu will be absolutely positioned on the right and with a left border. Its height will equal the height of its container, while its width will be 15% of the container's width.

Now we need table rows to host our cells. We turn the list items into table rows by declaring display: table-row on each li element.

Finally, we create the table cells in the fifth rule by declaring display: table-cell on the a and strong elements. The border of these cells will collapse to form an unique border, as said above. The width of the cells will be 100% of the total, plus a 0.3em of left and right padding. In case you're wondering, the content of the cells will not overflow its container because of the type of table layout set on our menu. Tables can have two types of layout, controlled by the table-layout property: auto and fixed. The first value is used by default on all tables and it's used also on our menu. With this value, the global width of the table will be determined by the width (and the content) of its single cells. In other words, we have a fluid table that will expand automatically together with its cells.

The sub-header

The sub-header is marked up as follows:

<div id="subheader">
<p id="issue">Issue 1, August 2008</p>
<form id="search" action="#">
<div>
<label for="text">Search:</label>
<input type="text" name="text" id="text" />
<input type="submit" id="btn" name="btn" value="Go" />
</div>
</form>
</div>

We want to put the #issue element on the left and the search form on the right. The code could be the following:

#subheader {
display: table;
width: 100%;
height: 1.4em;
border-bottom: 1px solid #000;
font-size: 120%;
}
#subheader #issue {
display: table-cell;
width: 30%;
vertical-align: middle;
font-weight: bold;
padding: 0 0.5em;
text-transform: uppercase;
}
#subheader form {
display: table-cell;
width: 68%;
text-align: right;
vertical-align: middle;
padding: 0.5em;
}
#subheader form label {
font-weight: bold;
}
#subheader form input {
font: 1em Verdana, sans-serif;
}
#subheader form input#text {
border: 1px solid #000;
background: #fff;
color: #333;
}
#subheader form input#btn {
background: #800;
color: #fff;
font-weight: bold;
border: 1px solid #800;
}

View the example - View the screenshot

The first rule turns the sub-header section into a table, sets a global height and width plus a bottom border. The second rule turns the #issue element into a table cell, sets a width on the element plus the vertical alignment of the text inside the cell (middle). The third rule turns the form into a table cell. As for the previous element, also in this case the vertical margins of this element will be resetted, since table cells cannot have vertical margins. The width of this element covers almost all the available space and this is actually our intended purpose. In fact, with the declaration text-align: right we push the form elements to the right of the sub-header, as we do want. Also in this case the elements will be vertically aligned, thanks to the declaration vertical-align: middle. The fifth rule deserves a further explanation: since the dimensions of form elements are determined also by the type and size of the used font, a good way to get consistency across browsers is an explicit declaration of font type/size on the elements we want to format (in this case, input).

The post title

The markup for this section is really simple, as you can see below.

<div class="art-title">
<h2>Lorem ipsum</h2>
<p class="date">8/17/2008</p>
</div>

The post title has been inserted through a h2 element and the date of the post is marked up with a paragraph having .date as its own class. The styles could be the following:

.art-title {
background: #800;
color: #fff;
display: table;
width: 100%;
margin-top: 1em;
padding: 0.3em 0;
}
.art-title h2 {
font-size: 1.4em;
display: table-cell;
width: 40%;
vertical-align: middle;
color: #fff;
padding-left: 3px;
}
.art-title .date {
display: table-cell;
width: 60%;
vertical-align: middle;
text-align: right;
padding-right: 3px;
font-style: italic;
font-weight: bold;
}

View the example - View the screenshot

Again, we've turned the outermost container into a table and its children into table cells. The vertical alignment of the text is controlled by the vertical-align property. The width of each element can be adjusted in order to satisfy particular needs. In this case, we could change the value 40% with 60%, since the content of a date doesn't require so much space.

Download

examples.zip

This entry was posted in by Gabriele Romanato. Bookmark the permalink.

One thought on “CSS: create layouts with table values”

Leave a Reply

Note: Only a member of this blog may post a comment.