Read CSS: The Definitive Guide, 3rd Edition Online
Authors: Eric A. Meyer
Tags: #COMPUTERS / Web / Page Design
A table
caption is about what you'd expect: a short bit of text that describes the nature of
the table's contents. A chart of stock quotes for the fourth quarter of 2003,
therefore, might have a caption element whose contents read "Q4 2003 Stock
Performance." With the propertycaption-side
, you
can place this element either above or below the table, regardless of where the
caption appears in the table's structure. (In HTML, thecaption
element can appear only after the openingtable
element, but other languages may have different
rules.)
Captions are a bit odd, at least in visual terms. The CSS specification states
that a caption is formatted as if it were a block box placed immediately before (or
after) the table's box, with a couple of exceptions. The first is that the caption
can still inherit values from the table, and the second is that a user agent ignores
a caption's box when considering what to do with a run-in element that precedes the
table. Therefore, a run-in element that comes before a table will not run into a top
caption or into the table, but will instead be treated as if itsdisplay
value wereblock
.
caption-side
top
|bottom
top
Elements with thedisplay
valuetable-caption
Yes
As specified
The valuesleft
andright
appeared in CSS2 but were dropped from
CSS2.1 due to a lack of widespread support
A simple example should suffice to demonstrate most of the important aspects of
caption presentation. Consider the following, illustrated in
Figure 11-5
:
caption {background: gray; margin: 1em 0;
caption-side: top;}
table {color: white; background: black; margin: 0.5em 0;}
Figure 11-5. Styling captions and tables
The text in thecaption
element inherits thecolor
valuewhite
from the table, while the caption gets its own background. The
separation between the table's outer border edge and the caption's outer margin edge
is one em because the top margin of the table and bottom margin of the caption have
collapsed, as described in
Chapter 7
. Finally,
the width of the caption is based on the content width of thetable
element, which is considered to be the containing
block of the caption. These same results would occur if you changed the value ofcaption-side
tobottom
, except that the caption would be placed after the table's box, and
collapsing would occur between the top margin of the caption and the bottom margin of
the table.
For the most part, captions are styled just like any block-level element; they can
have padding, borders, backgrounds, and so on. For example, if you need to change the
horizontal alignment of text within the caption, you use the propertytext-align
. Thus, to right-align the caption in the
previous example, you would write:
caption {background: gray; margin: 1em 0;
caption-side: top; text-align: right;}
As of mid-2006, the styling of captions is still a risky thing. Some browsers
honor top and bottom margins on captions, while others do not; some browsers
calculate the caption's width in relation to the table's width, while others
choose a different path. Listing all the behaviors would be fruitless, since this
is an area where rapid change is expected. This note is intended primarily to give
readers a heads-up that they may encounter problems.
There are actually two
quite distinct border models in CSS. The separated border model takes effect when cells
are separated from each other in layout terms. The other option is the collapsed border
model, in which there is no visual separation between cells, and cell borders merge, or
collapse, with each other. The former is the default model, although in an earlier
version of CSS the latter was the default.
An author can choose between the two models with the propertyborder-collapse
.
border-collapse
collapse
|separate
|inherit
separate
Elements with thedisplay
valuetable
ortable-inline
Yes
As specified
In CSS2, the default wascollapse
The whole point of this property is to offer the author a way to determine which
border model the user agent will employ. If the valuecollapse
is in effect, then the collapsing borders model is used. If the
value isseparate
, then the separated borders model
is used. We'll look at the latter model first, since it's actually much simpler to
describe.
In this model, every cell in the table is separated from the other cells by some
distance, and the borders of cells do not collapse into each other. Thus, given the
following styles and markup, you would see the result shown in
Figure 11-6
:
table {border-collapse: separate;}
td {border: 3px double black; padding: 3px;}
cell one | cell two |
cell three | cell four |
Figure 11-6. Separated (and thus separate) cell borders
Note that the cell borders touch but remain distinct from one another. The three
lines between cells are actually the two double borders sitting right next to each
other.
The HTML attributecellspacing
was included in
the previous example to make sure the cells had no separation between them, but its
presence is likely a bit troubling. After all, if you can define separate borders,
then there ought to be a way to use CSS to alter the spacing between cells.
Fortunately, there is.
There may be situations where you want the table cell
borders to be separated by some distance. This is easily accomplished with the
propertyborder-spacing
, which provides a more
powerful replacement for the HTML attributecellspacing
.
border-spacing
inherit
0
Elements with thedisplay
valuetable
ortable-inline
Yes
Two absolute lengths
Property is ignored unlessborder-collapse
value isseparate
Either one or two lengths can be given for the value of this
property. If you want all your cells separated by a single pixel, thenborder-spacing
:1px;
would suffice. If, on the other hand, you want cells to be
separated by one pixel horizontally and five pixels vertically, you'd writeborder-spacing
:1px
. If two lengths are supplied, the first is always the horizontal
5px;
separation, and the second is always the vertical.
The spacing values
are also applied between the borders of cells along the outside of a table and the
padding on the table element itself. Given the following styles, you would get the
result shown in
Figure
11-7
:
table {border-collapse: separate; border-spacing: 3px 5px;
padding: 10px; border: 2px solid black;}
td { border: 1px solid gray;}
td#squeeze {border-width: 5px;}
Figure 11-7. Border spacing effects between cells and their enclosing table
In
Figure 11-7
, there are
3 pixels of space between the borders of any two horizontally adjacent cells, and
there are 13 pixels of space between the borders of the right- and left-most cells
and the right and left borders of thetable
element. Similarly, the borders of vertically adjacent cells are 5 pixels apart,
and the borders of the cells in the top and bottom rows are 15 pixels from the top
and bottom borders of the table, respectively. The separation between cell borders
is constant throughout the table, regardless of the border widths of the cells
themselves.
Note also that if you're going to declare aborder-spacing
value, it's executed on the table
itself, not on the individual cells. Ifborder-spacing
had been declared for thetd
elements in the previous example, it would have been
ignored.
In the separated border model, borders cannot be set for
rows, row groups, columns, and column groups. Any border properties declared for
such elements must be ignored by a CSS-conformant user agent.
Because every cell is, in a visual sense, distinct
from all the other cells in the table, what do you do with cells that are empty
(i.e., have no content)? You have two choices, which are reflected in the values
of theempty-cells
property.
Ifempty-cells
is set toshow
, the borders and background of an empty cell
will be drawn, just as with table cells that have content. If the value ishide
, then no part of the cell is drawn,
just as if the cell were set tovisibility
:hidden
.
If a cell contains any
content, it cannot be considered empty. "Content," in this case, includes not only
text, images, form elements, and so on, but also the nonbreaking space entity
(
) and any other whitespace
except
the CR (carriage-return), LF (linefeed), tab, and
space characters. If all the cells in a row are empty, and all have anempty-cells
value ofhide
, then the entire row is treated as if the row element were set todisplay
:none
.
empty-cells
show
|hide
|inherit
show
Elements with thedisplay
valuetable-cell
Yes
As specified
Property is ignored unlessborder-collapse
value isseparate
As of this writing,empty-cells
is not
fully supported by Internet Explorer.
While the collapsing cell model largely describes how
HTML tables have always been laid out when they don't have any cell spacing, it is
quite a bit more complicated than the separated borders model. There are also some
rules that set collapsing cell borders apart from the separated borders model. These
are:
Elements with adisplay
oftable
orinline-table
cannot have any padding, although they can have
margins. Thus, there is never any separation between the border around the
outside of the table and the edges of its outermost cells.
Borders can be applied to cells, rows, row groups, columns, and column
groups. The table element itself can, as always, have a border.
There is never any separation between cell borders. In fact, borders
collapse into each other where they adjoin, so that only one of the collapsing
borders is actually drawn. This is somewhat akin to margin collapsing, where
the largest margin wins. When cell borders collapse, the "most interesting"
border wins.
Once they are collapsed, the borders between cells are centered on the
hypothetical grid lines between the cells.
We'll explore the last two points in more detail in the next two sections.
To better understand how the collapsing-borders model works, let's look at the
layout of a single table row, as shown in
Figure 11-8
.
Figure 11-8. The layout of a table row using the collapsing-borders model
For each cell, the padding and content width of the cell is inside the borders,
as expected. For the borders between cells, half of the border is to one side of
the grid line between two cells, and the other half is to the other side. In each
case, only a single border is drawn along each cell edge. You might think that
half of each cell's border is drawn to each side of the grid line, but that's not
what happens.
For example, assume that the solid borders on the middle cell are green and the
solid borders on the outer two cells are red. The borders on the right and left
sides of the middle cell (which collapse with the adjacent borders of the outer
cells) will be all green, or all red, depending on which border wins out. We'll
discuss how to tell which one wins in the next section.
You may have noticed that the outer borders protrude beyond the table's width.
This is because, in this model,
half
the table's borders are
included in the width. The other half extends beyond that distance, sitting in the
margin itself. This might seem a bit weird, but that's how the model is defined to
work.
The specification includes a layout formula that I'll reproduce here for the
benefit of those who enjoy such things:
row width = (0.5 * border-width
0
) + padding-left
1
+ width
1
+ padding-right
1
+
border-width
1
+ padding-left
2
+...+ padding-right
n
+ (0.5 * border-width
n
)
Eachborder-width
i
refers to the border between cell
i
and the next cell; thus,border-width3
refers
to the border between the third and fourth cells. The valuen
stands for the total number of cells in the row.
There is a slight exception to this mechanism. When beginning the layout of a
collapsed-border table, the user agent computes an initial left and right border
for the table itself. It does this by examining the left border of the first cell
in the first row of the table and by taking half of that border's width as the
table's initial left border width. The user agent then examines the right border
of the last cell in the first row and uses half that width to set the table's
initial right border width. For any row after the first, if the left or right
border is wider than the initial border widths, it extends into the margin area of
the table.
In cases where a border is an odd number of display elements (pixels, printer
dots, etc.) wide, the user agent must decide what to do about centering the border
on the grid line. It might shift the border so that it is slightly off-center,
round up or down to an even number of display elements, or do anything else that
seems reasonable.
When two or more borders are adjacent, they collapse into each other. In fact,
they don't collapse so much as fight it out to see which of them will gain
supremacy over the others. There are some strict rules governing which borders
will win and which will not:
If one of the collapsing borders has aborder-style
ofhidden
, it
takes precedence over all other collapsing borders. All borders at this
location are hidden.
If one of the collapsing borders has aborder-style
ofnone
, it
takes the lowest priority. There will be no border drawn at this location
unless all of the colliding borders have a value ofnone
. Note thatnone
is the
default value forborder-style
.
If at least one of the collapsing borders has a value other thannone
and none of the collapsing borders has a
value ofhidden
, then narrow borders lose
out to wider ones. If more than one of the collapsing borders have the same
width, then the border style is taken in the following order, from most to
least preferred:double
,solid
,dashed
,dotted
,ridge
,outset
,groove
,inset
. Thus, if two borders with the same width
are collapsing, and one isdashed
while
the other isoutset
, the border at that
location will be dashed.
If collapsing borders have the same style and width, but differ in color,
then the color used is taken from an element in the following list, from
most to least preferred: cell, row, row group, column, column group, table.
Thus, if the borders of a cell and a column (identical in every way except
color) collapse, then the cell's border color (and style and width) will be
used. If the collapsing borders come from the same type of element, such as
two row borders with the same style and width but different colors, then the
color is taken from borders that are the topmost and leftmost (in
left-to-right languages; otherwise, topmost and rightmost).
The following styles and markup, presented in
Figure 11-9
, help illustrate each of the
four rules:
table {border-collapse: collapse;
border: 3px outset gray;}
td {border: 1px solid gray; padding: 0.5em;}
#r2c1, #r2c2 {border-style: hidden;}
#r1c1, #r1c4 {border-width: 5px;}
#r2c4 {border-style: double; border-width: 3px;}
#r3c4 {border-style: dotted; border-width: 2px;}
#r4c1 {border-bottom-style: hidden;}
#r4c3 {border-top: 13px solid silver;}
1-1 | 1-2 | 1-3 | 1-4 |
2-1 | 2-2 | 2-3 | 2-4 |
3-1 | 3-2 | 3-3 | 3-4 |
4-1 | 4-2 | 4-3 | 4-4 |
Figure 11-9. Manipulating border widths, styles, and colors leads to some unusual
results
Let's consider what happened for each of the cells, in turn:
For cells 1–1 and 1–4, the five-pixel borders were wider than any of
their adjacent borders, so they won out not only over adjoining cell
borders, but over the border of the table itself. The only exception is the
bottom of cell 1–1, which was suppressed.
The bottom border on cell 1–1 was suppressed because cells 2–1 and 2–2,
with their explicitly hidden borders, completely removed any borders from
the edge of the cells. Again, the table's border lost out (on the left edge
of cell 2–1) to a cell's border. The bottom border of cell 4–1 was also
hidden, so it prevented any border from appearing below the cell.
The three-pixel double border of cell 2–4 was overridden on top by the
five-pixel solid border of cell 1–4. Cell 2–4's border, in turn, overrode
the border between itself and cell 2–3 because it was both wider and "more
interesting." Cell 2–4 also overrode the border between itself and cell 3–4,
even though both are the same width, because 2–4'sdouble
style is defined to be "more interesting" than 3–4'sdotted
border.
The 13-pixel top silver border of cell 4–3 not only overrode the top
border of cell 3–3, but it also affected the layout of content within both
cells
and
the rows that contain both cells.
For cells along the outer edge of the table that weren't specially
styled, their one-pixel solid borders were overridden by the three-pixel
outset border on thetable
element
itself.
This is, in fact, about as complicated as it sounds, although the behaviors are
largely intuitive and make a little more sense with practice. It's worth noting,
though, that the basic Netscape 1-era HTML table presentation can be captured with
a fairly simple set of rules, described here and illustrated by
Figure 11-10
:
table {border-collapse: collapse; border: 2px outset gray;}
td {border: 1px inset gray;}
Figure 11-10. Reproducing old-school table presentation