CSS Getting StartED
by David Powers
Copyright © 2009 by David Powers
All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording, or by any information storage or retrieval
system, without the prior written permission of the copyright owner and the publisher.
ISBN-13 (pbk): 978-1-4302-2543-0
ISBN-13 (electronic): 978-1-4302-2544-7
Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1
Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence
of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark
owner, with no intention of infringement of the trademark.
Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring Street, 6th Floor,
New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail orders-ny@springer-sbm.com,
or visit www.springeronline.com.
For information on translations, please e-mail info@apress.com, or visit www.apress.com.
Apress and friends of ED books may be purchased in bulk for academic, corporate, or promotional use.
eBook versions and licenses are also available for most titles. For more information, reference our Special
Bulk Sales–eBook Licensing web page at http://www.apress.com/info/bulksales.
The information in this book is distributed on an “as is” basis, without warranty. Although every precaution
has been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability to
any person or entity with respect to any loss or damage caused or alleged to be caused directly or
indirectly by the information contained in this work.
The source code for this book is freely available to readers at www.friendsofed.com in the Downloads
President and Publisher:
Paul Manning
Lead Editor:
Ben Renow-Clarke
Technical Reviewer:
Peter Elst
Editorial Board:
Clay Andres, Steve Anglin, Mark Beckner, Ewan
Buckingham, Tony Campbell, Gary Cornell, Jonathan
Gennick, Michelle Lowman, Matthew Moodie, Jeffrey
Pepper, Frank Pohlmann, Ben Renow-Clarke, Dominic
Shakeshaft, Matt Wade, Tom Welsh
Coordinating Editor:
Kelly Moritz
Copy Editor:
Heather Lang
BIM Indexing and e-Services
April Milne
Interior Designer:
Anna Ishchenko
Contents at a Glance
Contents at a Glance .................................................................... iv
Contents .................................................................................... v
About the Author........................................................................ xv
About the Technical Reviewer .......................................................xvi
Acknowledgments ......................................................................xvii
Introduction ............................................................................. xix
Chapter 1: What Is CSS, and Why Should I Learn It? ...............................1
Chapter 2: How Do I Improve the Look of Text and Links? ..................... 39
Chapter 3: How Can I Improve the Layout of My Text?.......................... 85
Chapter 4: How Can I Flow Text Around Images?............................... 121
Chapter 5: How Do I Add Backgrounds and Borders to
Improve the Look of My Page? ..................................... 155
Chapter 6: How Do I Solve the Mysteries of Width and Height? ............. 199
Chapter 7: How Do I Create Differently Styled Sections? ..................... 243
Chapter 8: How Do I Style Lists and Navigation Menus? ....................... 275
Chapter 9: How Do I Style Tables? ................................................. 325
Chapter 10: How Do I Position Elements Precisely on the Page?............ 363
Chapter 11: Are There Any Guidelines for Basic Page Layout? .............. 403
Chapter 12: How Do I Create Styles for Printing? .............................. 453
Appendix: CSS Properties and Selectors.......................................... 495
Index..................................................................................... 535
Chapter 9
How Do I Style Tables?
Tables seem to be the most divisive of all HTML elements—you either love ’em
or hate ’em. For years, they were the only way to build a grid structure to lay
out web pages. But tables work in a unique way. The height of each row is
determined by the tallest object in the row, and the width of each column is
determined by the widest object in the column. Just when you think you have
everything nicely aligned, you add something slightly bigger in a table cell, and
the whole table structure shifts.
Thankfully, tables are no longer necessary—or indeed recommended—for page
layout. Normally, they should be used only for the display of data that needs to
be presented in a grid format—timetables, price lists, sports results, and so on.
That’s the focus of this chapter: styling tables that contain data.
In this chapter, you’ll learn about the following:
Styling borders around tables and individual cells
Moving the position of the table caption
Suppressing the display of empty cells
Adjusting the space between table cells and inside them
Preventing columns from exceeding a fixed width
Styling table columns
Most of this chapter is descriptive, but there are numerous examples in the
download files demonstrating the effect of different style rules. The chapter
concludes with an exercise that puts all the information to practical use styling
a table of weather data.
Before diving into the details of styling tables with CSS, it’s important to
understand the basic structure of tables and how browsers lay out the various
Getting StartED with CSS
Understanding the anatomy of a table
Assuming you’re not a complete beginner at web design who happens to have
opened this page at random, you should be familiar with the structure of an
HTML table. The first section covers very basic knowledge, so you might want
to skim through it very quickly. However, I also describe the role of less
frequently used table elements—including <colgroup> and <tbody>—that play
an important role in styling tables with CSS.
Basic table structure
In an HTML table, everything is wrapped in a pair of <table> tags; each row is
contained in <tr> tags; and individual cells are created using <td> tags. The
following code produces the table shown in Figure 9-1 (the code is in
table_01.html in the download files for this chapter):
<table width="200" border="1" cellpadding="5">
<td>Row one - cell 1</td>
<td>Cell 2</td>
<td>Row two - cell 1</td>
<td>Cell 2</td>
Figure 9-1. A simple table
Notice that the opening <table> tag has the border attribute set to 1. This puts
a 1px border around the whole table and each individual cell, producing the
effect of a raised double border around each table element. The other
attribute in the opening tag, cellpadding, is set to 5, adding 5px of padding
around the content of each cell.
If you increase the value of border to 10, you get the result shown in Figure 9-2
(the code is in table_02.html):
Chapter 9: How Do I Style Tables?
Figure 9-2. HTML draws the wider border only around the table.
The border around the table is increased, but the border around the table cells
remains unchanged.
Changing the value of cellpadding adds the same amount of space around each
side of the content in each cell. All cells are treated exactly the same, and
there is no way to add different amounts of padding to each side of the
content. With cellpadding, it’s a case of “one size fits all.” However, as you’ll
see later, CSS gives you control not only over padding on each side but also
over the amount used in individual table cells.
The other main control that HTML offers over tables is the cellspacing
attribute, which controls the amount of space between each table cell. Like
cellpadding, the same value is applied around all sides of every cell. If you set
cellspacing to 0, the space between cells is eliminated. However, each cell
and the table still retain their own borders. Consequently, even when border is
set to 1, the actual border is 2px (see Figure 9-3 and table_03.html).
Figure 9-3. Setting cellspacing to 0 eliminates the space between cells.
In addition to <td> tags, you can use <th> tags to indicate that a cell should be
regarded as a row or column heading. The code for the table in table_04.html
looks like this:
<table width="200" border="1" cellpadding="5" cellspacing="0">
<th>Header 1</th>
<th>Header 2</th>
<td>Cell 1</td>
<td>Cell 2</td>
Getting StartED with CSS
By default, browsers display text in <th> tags centered and in a bold font, as
shown in Figure 9-4.
Figure 9-4. Text in header cells is normally bold and centered.
Using HTML tags to define sections of a table
Because tables have been so widely used for layout, many web developers are
unaware that tables have several other tags, all of which are optional but
which can enhance the look of a table used for data.
The <caption> tag displays a caption for the table. By default, it’s displayed
above the table (see Figure 9-5), but the tag itself must come immediately
after the opening <table> tag like this (the code is in table_05.html):
<table width="200" border="1" cellpadding="5" cellspacing="0">
<caption>This is a caption for the table</caption>
Figure 9-5. Table captions are normally displayed above the table.
Between the caption and the first table row, you can add several tags to define
columns and special header and footer rows.
Defining table columns
The ability to define table columns in HTML appears to be one of the Web’s
best-kept secrets, probably because columns are formed automatically by
adding cells to table rows. However, if you take the trouble to define columns,
you can use CSS to apply borders, backgrounds, and width to them. You should
also be able to use CSS to control the visibility of columns, but at the time of
this writing, IE8 is the only browser that does this correctly.
To define table columns, add one or more <colgroup> tags immediately after
the table caption. If the table doesn’t have a caption, the <colgroup> tags
come immediately after the opening <table> tag. As the name suggests, a
Chapter 9: How Do I Style Tables?
<colgroup> tag creates a column group. The <colgroup> tag optionally takes an
attribute called span, which specifies the number of columns in the group. So,
let’s say you have a five-column table, and you use the first column for labels
and the remaining columns for data, you could define the column groups like
<colgroup span="1" class="labelcol" />
<colgroup span="4" class="datacol" />
Alternatively, if you want to apply different styles to columns within a group,
you can list individual columns by creating <col> tags inside a pair of
<colgroup> tags like this:
<col class="labelcol" />
<col class="oddcol" />
<col class="evencol" />
<col class="oddcol" />
<col class="evencol" />
The <col> tag also accepts the span attribute, so you can apply the same class
to multiple columns like this:
<col class="labelcol" />
<col span="3" class="datacol" />
<col class="lastcol" />
Obviously, the number of columns in the table must equal the number of
columns specified in the <colgroup> and <col> tags.
Although few web designers seem to use <colgroup> and <col> tags, they
have been around for a long time and are supported by all current
browsers. In fact, Internet Explorer has supported them since version 4
was released way back in 1997. So, you can use <colgroup> and <col> tags
to style table columns in all browsers—yes, even IE6—as you’ll see in the
exercise at the end of this chapter.
Getting StartED with CSS
Defining table header and footer rows
Immediately after the column definitions, you can define table header and
footer rows. The table header comes first and consists of one or more table
rows enclosed in a pair of <thead> tags. The table footer comes immediately
after the table header and consists of one or more table rows inside a pair of
<tfoot> tags.
The principal advantage of using <thead> and <tfoot> is that browsers should
add the header and footer rows at the top and bottom of each page when
printing a long table. Although it seems counterintuitive, the <tfoot> section
must come before the main body of the table. You’ll see how this works in the
next section.
Grouping table rows into sections
If you want to divide your table into horizontal sections, you can wrap one or
more rows in pairs of <tbody> tags. For example, a company results table might
be divided into sections for each quarter using <tbody> tags. Together with
header and footer sections, the code looks like this (the code is in
table_sections.html in the download files):
<tbody id="q1">
Chapter 9: How Do I Style Tables?
<tbody id="q2">
Without any styling, the <tbody> tags don’t make any difference to the way the
table is displayed, but they perform a similar function to <div> tags by dividing
the table into sections that can be styled independently. The screenshot on the
left of Figure 9-6 shows the table with some simple styles added. Note how the
<tfoot> section is displayed at the bottom of the table, even though it comes
before either of the <tbody> sections. This is not the result of the CSS styles.
It’s the way the HTML works. You can verify this by turning off all the styles in
the browser (in Firefox, select View ➤ Page Style ➤ No Style). The <tfoot>
section is still at the bottom of the table, as shown in the screenshot on the
right of Figure 9-6.
Figure 9-6. The position of the table footer remains the same even when CSS is
disabled (right).
Getting StartED with CSS
How browsers lay out tables
That excursion into the lesser known table tags was necessary for two reasons:
as a prelude to the exercise at the end of the chapter, and more importantly,
to help you understand how browsers lay out tables and the effect this has on
the rendering of CSS. Browsers assemble tables in six stages, as follows:
Column groups
Individual columns
Row groups
Individual rows
Individual cells
To see how styles are applied on top of each other in this six-stage process,
load table_06.html into a browser. All browsers, including IE6, implement the
same process, so you should see the same results as in Figure 9-7 whichever
browser you use.
Figure 9-7. Browsers build tables in stages, starting with the whole table, followed
by columns, rows, and cells.
Chapter 9: How Do I Style Tables?
The basic structure of all six tables in table_06.html looks like this (the same
structure is used for many of the subsequent examples in this chapter):
<table width="300">
<colgroup span="1" />
<col />
<col />
<caption>Description of table</caption>
All six tables have a red background color. The first table has no other styles,
but in each successive table, a class has been added to one of the table
elements in the same order as the stages browsers use to build a table. So,
table 2 applies an orange background to the second column group, and table 3
applies a blue background to one column within that group. Because of the way
browsers apply styles, the orange background is painted over the red
background, and the blue background is painted over the orange.
In table 4, the green background applied to the second row group overwrites
the color of all columns in the bottom two rows. Table 5 shows how a style
applied to an individual row takes precedence over the row group.
Finally, in table 6, a class is applied to table cells 8 and 11 to restore the blue
background to the center column.
Getting StartED with CSS
If you keep this six-stage process in mind, it will help you understand why
a background or style is being applied in a particular way—or more often,
why a style isn’t working as expected. Even IE6 works this way, so you can
use this approach with confidence.
Styling tables with CSS
Styling the content that you put into table cells works exactly like everything
you have studied in previous chapters, but the CSS2.1 specification also has
five properties dedicated to controlling the structure of tables. These are listed
in Table 9-1. Also listed are three properties you have already met—overflow,
text-align, and vertical-align—which are frequently used with tables.
Table 9-1. CSS Table Properties
Initial Value
Controls the way borders are
handled. By default, the
table and each cell have
independent borders.
Borders are merged by
setting the value of this
property to collapse.
Controls the spacing
between table cells in a
similar way to the HTML
cellspacing attribute.
Horizontal and vertical
spacing can be controlled
Determines whether the
table caption is displayed
above or below the table.
Chapter 9: How Do I Style Tables?
Initial Value
If set to hide, turns off the
display of borders and
backgrounds associated
with empty table cells. If all
cells in a row are empty, the
entire row is removed from
the display when bordercollapse is set to collapse.
Controls what happens to
content that is too big to fit
into a table cell.
Determines whether a table
automatically expands to
accommodate oversized
content. If set to fixed, the
width of each column is set
in the column definitions or
the first row.
See description Yes
Controls the horizontal
alignment of content in table
cells. In languages that are
written from left to right, the
default value is left.
Controls the vertical
alignment of content in table
The following sections describe how to use each of these properties.
Using CSS for table borders
The big difference between using CSS and the HTML border attribute to create
table borders is the much finer control offered by CSS. As explained at the
beginning of this chapter, the HTML border attribute adds borders to the table
itself and to the cells it contains. With CSS, you can control each border
independently, using the same border properties described in Chapter 5.
Getting StartED with CSS
The first implication of this is that applying a border to a table with CSS applies
it only to the table, and not to the table cells. It also means that you can use
any of the border styles supported by CSS2.1. The table style block in
table_07.html defines the border like this:
border: #000 double 10px;
This produces the result shown in Figure 9-8.
Figure 9-8. With CSS, you can use any border style for a table; the cells are not
In fact, you don’t need to declare a border or use the same style on every side,
as you can see in Figure 9-9.
Figure 9-9. Tables can have different style borders or none at all on each side.
The table in Figure 9-9 uses the following style rules (the code is in
border-top: #000 double 10px;
border-bottom: #999 solid 5px;
Adding borders to table cells
Because adding a table border with CSS has no effect on the table cells, you
need to create a separate style for the cells. This also gives you the freedom to
choose a different color and/or style for the cell borders. The style rules in
table_09.html add a 1px solid red border to all table cells like this:
td {
border: #F00 solid 1px;
Chapter 9: How Do I Style Tables?
As you can see in Figure 9-10, the border around each cell is separate from the
table border, and there is a small gap between each cell.
Figure 9-10. By default, there is a space between each cell border.
As you will see later in this chapter, this separation of borders can be used to
good effect. However, in most cases, you will want to eliminate it by using the
CSS equivalent of cellspacing. Doing so also opens up the possibility of
creating borders on columns and rows.
How do I stop border widths from being doubled?
By default, browsers insert a gap of about 2px between table cells. The normal
way to eliminate this gap in HTML is to set the table’s cellspacing attribute to
0. You can still use cellspacing with CSS, but it has a potentially undesirable
effect. To demonstrate what happens, table_10.html sets cellspacing to 0 and
adds a 5px red border to each table cell with the following style rule:
td {
border: #F00 solid 5px;
Setting cellspacing to 0 removes the gap between the cells but leaves the
separate borders intact. As a result, you end up with borders twice as thick as
you probably intended.
To avoid this problem, use the CSS border-collapse property, and set its value
to collapse.
In table_11.html, I have removed cellspacing="0" from the opening <table>
tag and added border-collapse to the table style block like this:
table {
margin: 20px auto;
border: #000 solid 5px;
border-collapse: collapse;
Figure 9-11 shows the difference between cellspacing and border-collapse.
The screenshot on the left shows table_10.html with cellspacing set to 0; the
Getting StartED with CSS
borders are doubled to 10px. The screenshot on the right shows table_11.html,
which uses border-collapse; the borders are merged to produce a 5px border
all round.
Figure 9-11. Even with cellspacing set to 0, the borders are doubled (left), whereas
border-collapse (right) produces the desired size.
Using border-collapse has another effect that you might not notice
immediately in Figure 9-11, because this book is printed in glorious black and
white. The black border around the table has disappeared, and has been
replaced by the 5px red border of the outer cells.
The order-collapse property follows strict rules to decide how to merge
adjacent borders. Most of the time, you don’t need to worry about the
details, because the basic principle is that only the wider border is
displayed. It’s when both borders are the same width that the rules come
into play. Both have the same style, so it boils down to a question of
deciding which color should prevail. As explained earlier in this chapter,
browsers lay out tables in six steps. The cells are laid out last, so that’s
the color used.
If you make the cell borders narrower than the table border, only the table
border shows. Try it out for yourself in table_11.html. Change the style rules
for the table cells to give them a 1px border like this (if you’re feeling lazy,
you can use table_12.html instead):
td {
border:#F00 solid 1px;
Chapter 9: How Do I Style Tables?
The 5px black border around the table is restored, and the cells have a 1px red
border between them. However, there is no red border sandwiched between
the outer cells and table border. The outer edge of the outer cell borders has
merged with the table border, as shown in Figure 9-12.
Figure 9-12. The table border is wider, so it hides the outer borders of adjacent
See www.w3.org/TR/CSS21/tables.html#border-conflict-resolution
the full rules governing how borders are merged.
The border-collapse property accepts just two values, namely:
collapse: This merges adjacent borders, as just demonstrated.
separate: This is the default setting, which leaves a small gap
between table cells. To create a gap larger than the default, you need
to use another property: border-spacing, which is described shortly.
When used with cell borders, border-collapse is supported by IE6, so you can
safely use this technique on any table. All other modern browsers, including
IE8, offer full support for border-collapse, allowing you to set borders on
columns and rows.
Getting StartED with CSS
Don’t confuse border-collapse with the HTML rowspan and colspan
attributes that merge table cells. The border-collapse property affects
only the way borders are drawn around table elements. To merge table
cells, use the rowspan and colspan attributes in the normal way in your
HTML markup.
Adding borders to columns and rows
As long as border-collapse is set to collapse, you can define borders for table
columns and rows. There are three tables in table_13.html. The following style
rule creates a 1px red border on the columns in table1, on the table rows in
table2, and on the table row groups (<tbody>) in table3:
#table1 col, #table1 colgroup, #table2 tr, #table3 tbody {
border: #F00 solid 1px;
The results are shown in Figure 9-13.
Figure 9-13. With border-collapse set to collapse, you can add borders to columns
and rows.
Chapter 9: How Do I Style Tables?
IE6 and IE7 don’t support borders on columns, column groups, rows, or row
groups. However, you can create borders on columns by adding a left
border to each table cell. Similarly, you can create borders on rows by
adding a bottom border to each table cell. In both cases, border-collapse
must be set to collapse.
Applying other styles to columns
As you have just seen, you can style columns if the border-collapse property
of the table is set to collapse. Columns are unusual in that they accept only
four styles, namely:
The only legal value for visibility is collapse. When visibility is set to
collapse, the browser should hide the column and reduce the width of the
table by the column’s width. However, at the time of this writing, IE8 is the
only browser that handles this correctly (see the notes after the exercise at the
end of this chapter).
This limited toolset for styling columns isn’t due to a lack of browser
support. It’s the way the CSS2.1 specification was drawn up. Many’s the
time I’ve cursed browsers for not rendering the padding or text-align
properties on columns until I realized they’re not meant to. Tables are
listed as low priority for CSS3, so the situation is unlikely to improve in
the foreseeable future.
It’s also important to remember that border-collapse must be set to
collapse for styles to be rendered on columns and column groups.
Getting StartED with CSS
What’s the CSS equivalent of cellspacing?
Although setting border-collapse to collapse removes the gap between table
cells, the CSS equivalent of cellspacing is a different property called borderspacing. These two properties are mutually exclusive. If you want to control
the spacing between cells, border-collapse must be set to separate or omitted
altogether (it’s the default way of displaying tables).
When you think about it for a moment, it makes sense that you can’t use
border-collapse at the same time as border-spacing. You can’t add space
between cells and merge their borders at the same time.
If you set border-spacing to 0, you get the same effect as shown in the
screenshot on the left of Figure 9-11. The spacing between the cells is
eliminated, but the borders don’t merge.
Unlike cellspacing, which adds the same amount of space around all sides of
each cell, border-spacing lets you specify different values for horizontal and
vertical spacing. If you supply one value, it applies to both axes. However, if
you supply two values, the first is applied to horizontal spacing, and the second
to vertical spacing.
The table style rule in table_14.html looks like this:
table {
margin: 20px auto;
border: #000 solid 5px;
border-spacing: 10px 20px;
In most browsers, this produces the result shown in Figure 9-14. The exceptions
are IE6 and IE7, which don’t support border-spacing at all. Also, Safari 4.0 and
Chrome 2.0 incorrectly add extra vertical spacing between the two <tbody>
Chapter 9: How Do I Style Tables?
Figure 9-14. With border-spacing, you can add different amounts of vertical and
horizontal space between cells.
Now you know how CSS deals with cellspacing, what about cellpadding?
What’s the CSS equivalent of cellpadding?
Er, there isn’t one. . .
Well, actually there is: it’s the padding property you have been using since
Chapter 6. Unlike cellpadding, this gives you complete control over the
amount of padding in every table cell, and you can have different amounts of
padding on each side of the content. You can create a single rule that applies
to all cells in the table, or separate rules using classes or ID selectors.
However, it’s important to remember that table rows are always as high as the
tallest cell; and columns normally expand to accommodate the widest cell. I
say “normally” because CSS lets you control column width, as you’ll see
To demonstrate how padding works in table cells, the td style rule in
table_15.html applies a different amount of padding to each side like this:
padding: 2px 0 15px 20px;
However, the middle cell in the third row uses the following ID selector:
#eight {
padding: 20px;
This adds 18px more padding to the top of the cell and 5px more at the bottom.
As Figure 9-15 shows, this increases the height of the entire row. The extra
height also affects the top padding in the cells on either side but does not
apply the same value as in the center cell.
Getting StartED with CSS
Figure 9-15. Different amounts of padding can be added to each side of a cell.
Controlling the height of table elements continues to be the holy grail of
many web developers. The simple fact of the matter is that it can’t be
done, at least not in a standards-compliant browser. Heights are always
calculated automatically and are controlled by the tallest element in a
table row.
Controlling the position of the table caption
To add a caption to a table, you place the caption text in a pair of <caption>
tags immediately after the opening <table> tag. By default, the caption
appears above the table, but you can move it underneath the table by setting
the caption-side property to bottom. Since the caption is an integral part of
the table, you can define the caption-side property in the style rule for the
table or in a separate rule for the caption itself.
According to the CSS2.1 specification, there are only two possible values for
caption-side, namely:
bottom: Put the caption under the table.
top: Put the caption above the table. This is the default value.
In CSS2, there were two other values: left and right. However, Firefox was
the only browser to offer support, so they were removed from the official
Chapter 9: How Do I Style Tables?
Support for caption-side was added to Internet Explorer in IE8. It’s not
supported in IE6 or IE7.
Since the caption is part of the table, it inherits its text color and width from
the table. You can style a caption like any other text element, giving it a color
and font properties of its own. Most browsers support giving a caption a margin
to distance it from the table. However, Safari and Chrome ignore margins on
captions, so the only reliable method is to use padding.
There are examples of caption-side in table_06.html and table_13.html (see
Figures 9-6 and 9-13).
Handling empty cells
The empty-cells property is supported by all browsers currently in widespread
use, except IE6 and IE7. It accepts the following values:
hide: Prevent the display of an empty cell’s borders and backgrounds.
show: Draw borders and backgrounds on every cell, even if it contains
no content. This is the default setting.
An empty cell is defined as a cell that contains absolutely nothing or one that
has the visibility property set to hidden. However, setting the visibility
property of a cell to hidden also prevents the display of its borders and
background, even when the empty-cells property is set to show.
Many HTML editors, such as Dreamweaver, automatically insert the HTML
entity for a nonbreaking space (&nbsp;) into empty table cells. CSS regards
this as content, even though nothing appears in the cell when viewed in a
browser. For a cell to be treated as empty it must not contain anything
other than new lines and whitespace between the opening and closing <td>
or <th> tags.
The empty-cells property is inherited, so you can apply it to the whole table.
However, if you want to affect only a certain part of a table, you can apply it
to table row groups, table rows, or individual cells.
Figure 9-16 and table_16.html show how the empty-cells property works. In all
four tables, the second row contains only empty cells, while the visibility
property of the middle cell in the third row has been set to hidden.
Getting StartED with CSS
Figure 9-16. The use of cell borders affects the way browsers treat empty cells.
Although browsers should hide a complete row of empty cells, at the time of
this writing, all browsers that support the empty-cells property leave a small
gap for the empty row, except when border-collapse is set to collapse and
the cells have no borders (see the bottom-right table in Figure 9-16).
Figure 9-17 shows a practical example of using empty-cells and border-spacing
to display the color keywords supported by CSS. Only 17 keywords are officially
supported, so it’s necessary to hide the last three cells of the bottom row—a
trivial task with empty-cells set to hide. You can examine the code in
color_names.html in the download files for this chapter.
Figure 9-17. Imaginative use of a table and CSS styles produce a clean-looking chart.
Chapter 9: How Do I Style Tables?
How can I control the width of my table?
At times, I get the feeling that whoever drew up the HTML specification for
tables must have had a cruel sense of humor. HTML allows you to specify the
width attribute on tables, columns, and individual table cells. At the beginning,
it seems to work, but as soon as you insert oversized content, the browser
obligingly makes room and ignores the specified width. It makes herding cats
seem like child’s play.
CSS rides to the rescue with the table-layout property, which is supported by
all current browsers, including IE6. The property accepts the following values:
auto: This is the default way tables behave, expanding columns and
the overall table width to accommodate the widest element in each
fixed: The width of each column is fixed by the width attribute
specified in its <col> tag. If no width is specified there, the width is
taken from the size of each column in the first table row.
The table-layout property is not inherited, so you can also use the inherit
keyword for nested tables. However, nested tables are rarely used when
displaying data.
To demonstrate how table-layout works, the download files for this chapter
contain a series of four pages that display two oversized images in a 300-pixelwide table. The basic HTML structure in each page looks like this:
<col width="25%" />
<col width="75%" />
<td width="50%">Angel's Window</td>
<td width="50%"><img src="../images/angels_window.jpg"
width="350" height="249" alt="Angel's window" /></td>
<td>Kaibab National Forest</td>
<td><img src="../images/forest_grassland.jpg" width="325"
height="208" alt="Kaibab National Forest" /></td>
The first page, table-layout_01.html, uses the default value for table-layout,
auto. The style rules in the page look like this:
Getting StartED with CSS
table {
table-layout: auto;
border: solid #000 5px;
border-spacing: 0;
width: 300px;
td {
padding: 5px;
As you can see in Figure 9-18, the table ignores all the width specifications and
expands to accommodate the content. The table ends up about 425px wide,
and the border is drawn around the outside edge.
Figure 9-18. By default, tables ignore declared widths and adjust to fit the content.
Figure 9-19 shows what happens when you change the value of table-layout to
fixed (the code is in table-layout_02.html). The table is drawn to the correct
width (300px), and the two columns are correctly proportioned (25%:75%), as
specified in the <col> tags. The 50% widths in the <td> tags are ignored—as they
should be, because only the first declared widths are valid with a fixed table
layout. What might come as a surprise is that the oversized content spills out
of the table.
Chapter 9: How Do I Style Tables?
Figure 9-19. With a fixed layout, the table widths are honored, but oversized
content spills out.
To prevent the overspill, you need to add the overflow property. If you set
overflow to hidden, you can add it either to the table style block or to the td
one. This cuts off any oversized content, as shown on the left of Figure 9-20
and in table-layout_03.html. In theory, to generate a scrollbar for oversized
content, add the overflow property to the td style block and set its value to
auto, as in table-layout_04.html. However, at the time of this writing, the
only browser that produces the result shown on the right in Figure 9-20 is IE8.
Some browsers let the content spill out in the same way as in Figure 9-19,
while others put both horizontal and vertical scrollbars on the images.
Getting StartED with CSS
Figure 9-20. You can hide the overflow (left) or add scrollbars to make it accessible
How do I create scrolling table cells that work in
all browsers?
If you test table-layout_04.html in a variety of browsers, you’ll soon discover
that setting the value of overflow to auto usually doesn’t have the desired
effect on table cells. Even in IE8, it affects only content that is too wide.
Setting a height on a table cell or table row is meaningless if the content is too
big to fit. So, what’s the secret of creating a scrollable table cell?
The answer is to use a <div> inside the cell, give it a fixed width (and height, if
desired), and set the overflow property of the <div> to auto. In other words,
it’s the content of the table cell that needs to be scrollable, rather than the
table cell itself.
Chapter 9: How Do I Style Tables?
Tables don’t conform to the CSS box model: the border is always added
inside the table, and not outside. When table-layout is set to the default
auto or omitted, this doesn’t really matter, because the table
automatically expands to accommodate the content. However, it makes a
big difference when table-layout is set to fixed. The overall width of a
300px wide table with a 5px border all round remains 300px, and not 310px.
This affects the calculation of the size of the <div> required for a scrolling
table cell.
The images in table-layout_05.html have each been wrapped in a <div>, to
which the following class has been assigned:
.scrollable {
width: 203px;
overflow: auto;
The width of the <div> was calculated by deducting 30px from the overall
width of 300px and multiplying the remainder by 75%. The 30px consists of the
left and right borders (5px each) and the 5px padding on each side of each
table cell. If you test table-layout_05.html in a range of browsers, you’ll see
that it works reliably, even in IE6 and IE7. The only problem with the older
versions of Internet Explorer is that they spawn both vertical and horizontal
scrollbars. Everyone else gets just horizontal scrollbars.
How do I control the position of content in table
The CSS equivalents of the HTML align and valign attributes are properties
that you first met in Chapter 2. To control the horizontal position of content in
a table cell, use text-align. Vertical alignment is controlled by the verticalalign property.
When used with table cells, the text-align property takes the same values as
with text, namely: left, center, right, and justify. The values work exactly
the same way, so no further explanation is necessary.
Getting StartED with CSS
The vertical-align property has many values, but only the following four work
with tables:
top: Align the content with the top of the cell.
middle: Center the content vertically within the cell. This is the
default value.
bottom: Align the bottom of the content with the bottom of the cell.
baseline: Align the first line of content with the baseline of the tallest
similarly aligned content in the same row.
The meaning of baseline should become clear from Figure 9-21 (the code is in
table_17.html). The fourth and fifth columns both have vertical-align set to
baseline. Since the text in the fifth column is taller, the baseline of the first
line of text in the fourth column is aligned with the baseline of the first line of
text in the fifth column. The baseline value affects only the first line of
content in a cell, and is determined independently for each row.
Figure 9-21. Table cells can be vertically aligned at the top, middle, bottom, and
baseline of the current row.
That covers the theoretical side of styling tables with CSS. To end this chapter,
let’s put that knowledge to practical use by styling a data table.
Styling a weather chart
This exercise uses most of the CSS table properties described in this chapter to
convert an uninspiring weather chart into something much more attractive. The
start and finish versions are in the download files.
Copy weather_start.html from the download files for this chapter to
your work folder, and rename it as weather.html.
Chapter 9: How Do I Style Tables?
Load weather.html into a browser to assess the task ahead. The page
should look like Figure 9-22. It’s a monthly summary of the average
weather in London and South East England, and as drab as the weather
Figure 9-22. This unstyled table of weather data is desperately in need of a touch of
Let’s start the transformation by giving the table a width and center
it. Also give it a 1px border, a smart font, and move the caption to the
bottom of the table. Create the following style block in the <head> of
the page:
<style type="text/css">
table {
width: 600px;
margin: 0 auto;
border: #002F2F 1px solid;
font-family: Tahoma, Geneva, sans-serif;
caption-side: bottom;
Getting StartED with CSS
Next, smarten up the caption by creating a new style rule immediately
after the one you added in the previous step:
caption {
font-size: 18px;
font-weight: bold;
font-variant: small-caps;
padding: 10px;
I have added 10px of padding all around the caption to move it away
from the bottom edge of the table. I chose padding because Safari and
Chrome ignore margins on captions.
With data tables, it’s usual to center the data in each column by
setting the text-align property to center. However, the numbers in
each column are of varying lengths, so centering gives them a ragged
appearance. Instead, I’m going to align the columns to the right, and
use padding to reposition the figures. Add the following style rule to
the page:
td {
text-align: right;
padding: 3px 30px 3px 3px;
border-bottom: 1px solid #002F2F;
This adds 3px of padding to all sides of each table cell, except the
right, which gets 30px. I have also added a 1px border to the bottom
of each cell.
Save weather.html, and check it in a browser. It should look similar to
Figure 9-23.
Chapter 9: How Do I Style Tables?
Figure 9-23. The table is beginning to take shape.
There are several points to note:
There are gaps between the columns in the bottom borders.
There’s also a double border at the bottom. This can be fixed
by setting border-collapse to collapse.
There are no borders under the headings in the top row or
under the months. This is because they use <th> tags, rather
than <td>. If you wanted to add borders, you would need to
create a group selector for both tags (td, th). However, on
this occasion, I don’t want a border, because I’m going to style
the headings differently. Choosing different tags not only
makes more structural sense; it makes styling easier.
The columns are of varying widths. You can fix that by using
the table-layout property.
Amend the table style block like this:
table {
width: 600px;
margin: 0 auto;
Getting StartED with CSS
border: #002F2F 1px solid;
font-family: Tahoma, Geneva, sans-serif;
caption-side: bottom;
border-collapse: collapse;
table-layout: fixed;
Although you could set the size of the columns by adding the width
property to the <th> tags in the first row, defining the columns with
<colgroup> and <col> tags opens up the possibility of styling the
columns with a background color. So, add the following column
definitions at the top of the table between the <caption> and the first
table row:
<caption>Average weather in London and South East England</caption>
<col class="labelcol" />
<col class="oddcol" />
<col class="evencol" />
<col class="oddcol" />
<col class="evencol" />
This defines the five columns, assigning a class to each one. The first
one will be used to style the month labels, and the others will set
alternating background colors for odd and even columns.
To identify the table row that contains the top row of headings, you
need to assign it a class. Amend the opening tag of the first table row
like this:
<tr class="headrow">
I used a class rather than an ID in case you want to put more than one
table on the same page.
10. Now, create the three classes for the columns by adding the following
style rules to the <head> of the page:
.labelcol {
background-color: #046380;
.oddcol {
background-color: #E6E2AF;
width: 23%;
.evencol {
Chapter 9: How Do I Style Tables?
background-color: #EFECCA;
width: 23%;
This adds a deep teal background color to the label column, and two
shades of beige to the other columns. The oddcol and evencol classes
also set the width of the columns to 23%. This leaves 8% for the
labelcol class. However, there’s no need to add a width for the first
column, because the browser will work it out automatically.
I’m not being lazy by not defining the width as 8%. Rounding errors with
percentage values make it unwise to specify widths that add up to exactly
100%. I have mentioned this before, but it’s worth repeating, because it’s
such an easy trap to fall into. The fact that the numbers all add up makes
it difficult to identify the problem if your design doesn’t work as
11. The top row of headings needs the same background color as the
month labels. They also needed centering and aligning to the top of
each cell. Add the following style block:
.headrow th {
background-color: #046380;
text-align: center;
vertical-align: top;
font-variant: small-caps;
This uses a descendant selector, so the styles affect only the <th>
cells in the row with the headrow class. The other <th> cells in the
month of column labels are not affected.
12. To complete the styling of the <th> tags, add the following style rule:
th {
color: #EFECCA;
padding: 3px 10px;
text-align: right;
This sets the text color of all <th> tags to the same light beige as the
background of the evencol class. It also sets the padding for all
headings. But what about that text-align? This affects only the <th>
Getting StartED with CSS
tags in the month labels, because the .headrow th descendant
selector created in the previous step has higher specificity. So, the
headings in the top row remain centered, while the remaining <th>
tags are aligned right.
13. Save the page, and view it in a browser. The uninspiring table you
started with should now look much smarter, as shown in Figure 9-24.
Figure 9-24. The table now looks much more visually attractive.
14. To make the table more attractive and user friendly, let’s highlight
each row as the cursor passes over it. The :hover pseudo-class can be
applied to any element, not just a link. Well, as you might expect, IE6
won’t play ball, but it has been perfectly well behaved in styling this
table up to now, so I’m not going to worry about it. Add the following
tr:hover {
background-color: #FFF;
tr:hover th {
background-color: #008080;
Chapter 9: How Do I Style Tables?
The first of these rules sets the background color to white on the
whole row, while the second rule affects only the <th> cell of the
current row, setting its background color to teal.
15. Save the page, and test it again in any modern browser. As you move
your cursor over the table, the current row should be highlighted, as
shown in Figure 9-25.
Figure 9-25. The :hover pseudo-class highlights the table row when the cursor passes
over it.
IE6 supports :hover only on links. Since highlighting the current row is
merely an enhancement, you can ignore IE6. The table remains
perfectly usable without the highlighting.
16. There’s just one minor problem: the top row of <th> tags is also
highlighted when the cursor passes over it. You can fix this by
grouping a new descendant selector with the .headrow th style rule
like this:
.headrow th, .headrow:hover th {
background-color: #046380;
text-align: center;
vertical-align: top;
font-variant: small-caps;
This makes sure the same style rules are always applied to the <th>
tags in the top row.
You can check your code, if necessary, against weather_finish.html in
the download files for this chapter.
As you can see in Figure 9-24, the padding on the right of the <td> cells centers
the minimum and maximum temperature columns, but the data in the sun and
rain columns is further to the right. One way of dealing with this would be to
make the last two columns narrower. You could also increase the right padding
in these two columns. However, remember that you can apply only four
properties to columns: background, border, width, and visibility. So, the only
way to change the padding on the columns would be to apply a class to each
individual cell. My personal feeling is that centering the data is less important
than aligning the decimal points. However, the choice is yours.
Getting StartED with CSS
The new selector added in the final step of the preceding exercise applies
the :hover pseudo-class to the headrow class, and not to the descendant th
selector. This is because the style rules in step 14 apply the highlighting
not just to the cell the cursor is currently over, but to the whole table
row. Only one cell is affected if you apply :hover to the th selector like
this: .headrow th:hover.
It might seem strange combining a class with a pseudo-class like this.
However, it should be easier to understand if you prefix the headrow class
with the table row selector like this: tr.headrow:hover th. This applies to
<th> tags in a table row styled with the headrow class when the cursor is
over the row.
One final test that you might like to make with this table is to set the
visibility of some columns to collapse. According to the CSS2.1
specification, browsers should hide the affected columns and reduce the
weather_col_visibility.html, the evencol class has been amended like this:
.evencol {
background-color: #EFECCA;
width: 23%;
visibility: collapse;
At the time of this writing, IE8 is the only major browser that gets it right, as
shown in Figure 9-26.
Chapter 9: How Do I Style Tables?
Figure 9-26. IE8 correctly hides columns when visibility is set to collapse.
Firefox 3.5 manages to hide the columns but fails to reduce the width of the
table, leaving the borders, as shown in Figure 9-27.
Figure 9-27. Firefox 3.5 hides the columns but doesn’t reduce the width of the
Getting StartED with CSS
Safari 4.0, Opera 10, and Chrome 2.0 fail to hide the collapsed columns and
display the page exactly the same as Figure 9-24.
Chapter review
CSS offers many advantages when it comes to styling tables. The bordercollapse and border-spacing properties are a great improvement on
cellspacing, not only giving you control over the horizontal and vertical
spacing between table cells but also improving the look of adjacent borders.
Although there isn’t a direct equivalent of cellpadding, table cells handle
padding in the same way as the CSS box model, giving you the freedom to
adjust it independently on each side of a cell and even use different settings in
selected cells. Other advantages include the freedom to style all of a table’s
internal and external borders independently using any of the border styles
supported by CSS2.1, and to hide empty cells.
By using advanced HTML elements, such as <colgroup>, <col>, and <tbody>,
you can style tables efficiently without the need to apply classes to individual
cells. Setting table-layout to fixed also gives you precise control over the
width of columns. However, it’s important to remember that tables do not
conform to the CSS box model: borders and padding are not added to the
overall width of a table, so this needs to be taken into account when
calculating how wide each column should be when using a fixed table layout.
Although IE8 handles the overflow property on table cells successfully, in order
to create a scrollable table cell you need to use a fixed-width <div> inside
table cells and apply the overflow property to the <div> for cross-browser
What’s disappointing about CSS support for tables is the fact that columns
support only four properties: background, border, width, and visibility. It
would make life a lot easier if all properties could be applied to columns.
However, tables are a low priority for the W3C, so such support is unlikely in
the near future.
In the next chapter, I’ll delve into the mysteries of CSS positioning. In the early
days of CSS, many developers thought it was the answer to all their problems
and would replace tables for layout. That enthusiasm quickly evaporated once
they realized that positioning often creates more problems than it solves. The
next chapter will try to help you avoid those problems.
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF