CSS: The Definitive Guide, 3rd Edition (54 page)

Read CSS: The Definitive Guide, 3rd Edition Online

Authors: Eric A. Meyer

Tags: #COMPUTERS / Web / Page Design

Captions

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 property
caption-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, the
caption
element can appear only after the opening
table
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 its
display
value were
block
.

caption-side

Values:

top
|
bottom

Initial value:

top

Applies to:

Elements with the
display
value
table-caption

Inherited:

Yes

Computed value:

As specified

Note:

The values
left
and
right
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 the
caption
element inherits the
color
value
white
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 the
table
element, which is considered to be the containing
block of the caption. These same results would occur if you changed the value of
caption-side
to
bottom
, 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 property
text-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;}
Tip

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.

Table Cell Borders

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 property
border-collapse
.

border-collapse

Values:

collapse
|
separate
|
inherit

Initial value:

separate

Applies to:

Elements with the
display
value
table
or
table-inline

Inherited:

Yes

Computed value:

As specified

Note:

In CSS2, the default was
collapse

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 value
collapse
is in effect, then the collapsing borders model is used. If the
value is
separate
, then the separated borders model
is used. We'll look at the latter model first, since it's actually much simpler to
describe.

Separated Cell Borders

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 onecell two
cell threecell 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 attribute
cellspacing
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.

Border
spacing

There may be situations where you want the table cell
borders to be separated by some distance. This is easily accomplished with the
property
border-spacing
, which provides a more
powerful replacement for the HTML attribute
cellspacing
.

border-spacing

Values:

? |
inherit

Initial value:

0

Applies to:

Elements with the
display
value
table
or
table-inline

Inherited:

Yes

Computed value:

Two absolute lengths

Note:

Property is ignored unless
border-collapse
value is
separate

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, then
border-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 write
border-spacing
:
1px
5px;
. If two lengths are supplied, the first is always the horizontal
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 the
table
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 a
border-spacing
value, it's executed on the table
itself, not on the individual cells. If
border-spacing
had been declared for the
td
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.

Handling empty
cells

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 the
empty-cells
property.

If
empty-cells
is set to
show
, the borders and background of an empty cell
will be drawn, just as with table cells that have content. If the value is
hide
, then no part of the cell is drawn,
just as if the cell were set to
visibility
:
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 an
empty-cells
value of
hide
, then the entire row is treated as if the row element were set to
display
:
none
.

empty-cells

Values:

show
|
hide
|
inherit

Initial value:

show

Applies to:

Elements with the
display
value
table-cell

Inherited:

Yes

Computed value:

As specified

Note:

Property is ignored unless
border-collapse
value is
separate

Tip

As of this writing,
empty-cells
is not
fully supported by Internet Explorer.

Collapsing Cell Borders

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 a
    display
    of
    table
    or
    inline-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.

Collapsing border layout

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
)

Each
border-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 value
n
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.

Border collapsing

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 a
    border-style
    of
    hidden
    , it
    takes precedence over all other collapsing borders. All borders at this
    location are hidden.

  • If one of the collapsing borders has a
    border-style
    of
    none
    , it
    takes the lowest priority. There will be no border drawn at this location
    unless all of the colliding borders have a value of
    none
    . Note that
    none
    is the
    default value for
    border-style
    .

  • If at least one of the collapsing borders has a value other than
    none
    and none of the collapsing borders has a
    value of
    hidden
    , 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 is
    dashed
    while
    the other is
    outset
    , 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-11-21-31-4
2-12-22-32-4
3-13-23-33-4
4-14-24-34-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's
    double
    style is defined to be "more interesting" than 3–4's
    dotted
    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 the
    table
    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

Other books

Bilgewater by Jane Gardam
Heretic Dawn by Robert Merle
Rescuing Rayne by Susan Stoker
Narration by Stein, Gertrude, Wilder, Thornton, Olson, Liesl M.
Twilight Zone The Movie by Robert Bloch
Fearless in High Heels by Gemma Halliday
The Courtesy of Death by Geoffrey Household