Re: Tabs in CSS1

Stefan Olson wrote:
> >>I think that it is CSS1 that has caused the TAB tag to be removed when
> HTML 3.0 became 3.2.  The only thing I see missing is:
> This is left                              this is right.
> But, can be done with tables, as all other cases of tab can.<<

Not all cases can be done with tables.

Although it is true that tabs (when used correctly) serve the same
function as tables, their visual appearance is different. Ideally, you
should be able to choose a tabular or a tabbed display from the style
sheet, no matter what your original mark-up was.

Some examples (< and > indicate the tab's anchor position):

1. when the element should start at a position that is already occupied,
it moves to the next line:

    >short        >second column
    >longer than the first column
                  >second column

(didn't I see that one in a different discussion before...:-) )

2. columns can `overlap', when left/right tabs are alternated:

    >left short       a longer text aligned on the right<
    >a longer text on the left        a short text right<

3. tabs can include `leaders', which tables can't:

    Chapter 1 . . . . . . . . 4
      section 1.1 . . . . . . 4
      section 1.2 . . . . .  45
    Chapter 2 . . . . . . .  92
    Chapter 3 . . . . . . . 138

4. since tabs are in-line, it is far easier to keep the correct line
spacing between successive lines. Inside tables, the `line-height'
property will give the correct result only in simple cases, if there are
no font changes or in-line images in any of the table cells.

Back in March there was some discussion of tabs and I wrote a text with
a proposal. I don't think I ever sent it to the list, because we thought
this could wait until after CSS1. I've included it below.

But before discussing the proposal, we should answer a few questions
about tabs:

   A. Does the tab *character* (Unicode 9) have any meaning in HTML
      (outside of preformatted text)?
        - no, it is just white space
        - yes, it is a SHORTREF for <SPAN STYLE="something">

   B. Is it easier to set a position on an element (as I did in the
      proposal below), or to set a couple of (numbered) positions on the
      parent element, which are then inherited?
        - the former needs less syntax in CSS
        - the latter introduces an indirection, which may be easier to
          maintain in the long run
        - we could have both, but that might be too complicated

   C. What is the better behaviour when a tab position is already
        - skip to the next line (as I did in the example above, and as
          Scott Preece suggested)
        - go backward and overwrite existing text (as TeX does it)
        - both, subject to a CSS property

   D. What kinds of tabs are there? left, right, center, decimal, any
      others? Does `decimal' need an argument, or is the language's
      default decimal character good enough?

   E. What kinds of leaders are there? Is a small set good enough or do
      we need arbitrary characters (or images?)? If a small set, what is
      that set?

   F. How does tabbed text wrap? Like this:

          left       >tabbed text that is
                      too long wraps but
                      stays behind the tab
      Like this:

          left       >tabbed text that is
          too long wraps without
          considering that tab anymore

      Or like this:

          left       >tabbed text never wraps at all, no matter how...

   G. If a tab stop is outside the current margins, does it have any

   H. What are the internationalization pitfalls? The proposal below has
      at least one: it says that decimal tabs act as right tabs when
      there is no decimal separator. It should probably say that it acts
      as right or left, depending on the current writing direction.

CSS tabs

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