CSS tabs

A proposal for adding tab stops to CSS.


Value: [ <length> | <percentage> | none ] [ dots | line | blank ]? [ l | r | c | d ]?
Initial: none blank L
Applies to: inline elements
Inherited: no
Percentage values: relative to element's width

If an element has a tab property that doesn't start with 'none', it means that the element is anchored to a certain horizontal position. The four letters l, r, c, and d determine how it is anchored:

The position can be given in any of the normal length units, or as a percentage of the enclosing block element's width. Positive numbers start from the left margin, negative ones from the right.

Optionally, the space between the element and the preceding text can be filled with a leader. The default is 'blank', meaning no leader (i.e., just whitespace). 'dots' means that the space is filled with a dot leader, 'line' means it is filled with a solid, horizontal line.

Here is an example of a table of contents. The HTML could be:

<B CLASS=toc-chp>1 The problem</B> <span class="pgno">8</span>
<EM CLASS=toc-sec>1.1 Definitions</EM> <span class="pgno">9</span>

With this style sheet:

.toc-chp { tab: 0em /* default is left-align, no leaders */ }
.toc-sec { tab: 2em }
.pgno { tab: -0.001pt dots R }

(The position for pgno must be negative; -0pt doesn't work.) The result would be similar to this:

1 The problem . . . . . . . . . 8
    1.1 Definitions . . . . . . 9

Leaders are not considered part of the element, and thus they don't use the font, color, decoration, etc. of the element itself, but of its parent.

An author can try to make sure that there is enough width by setting the width property of the enclosing block to a fixed size, or by selecting 'pre' or 'nowrap' for the block's whitespace property. But even then there may be cases where the text doesn't fit in the allocated columns (unavailable font sizes, different font metrics, etc.). The following algorithm defines the behavior of tabs in such cases.

The first principle is: if the text of a tabbed element would overlap the preceding text (or indeed appear visually before the preceding text), the tab is moved to the next line. In some cases the tab may have to be moved down several lines. (This can occur if line wrapping is not disabled.)

If line wrapping is disabled (whitespace set to 'pre' or 'nowrap'), the width of the enclosing block element is automatically increased to hold the longest line. However, the tab positions don't change: a percentage value sets a tab at a position relative to the a-priori width, based on the inherited width or the width property, if that has been set explicitly.

If line wrapping is enabled (whitespace set to 'normal'), the content of the element wraps when it reaches the margin (note that this may be the right margin, the left margin or both). When it wraps, the wrapped part should not be put at the opposite margin, but at the tab position. An example with a left tab:

  |>.......>.........|      <--- the margins (|) and the tabs (>)
  |                  |
  |>abc    >short    |      <--- the normal case
  |                  |
  |>def    >a longer |      <--- with wrapping
  |         element  |
  |         will wrap|

An example with a right tab. Note how it wraps at the left margin and at the tab position:

  |....<.........<...|      <--- the margins (|) and the tabs (<)
  |                  |
  | abc<    short<   |      <--- the normal case
  |                  |
  | def<        a    |      <--- with wrapping
  |longer element    |
  |     will wrap<   |

W3CBert Bos
Updated 20 Mar 1996, 27 Nov 1996