CSS: Potential Enhancements

W3C Note 19-Aug-1997

Latest version:
This version:
Previous (W3C member only) version:
, Adobe Systems

Status of this document

This document is a NOTE made available by the W3 Consortium for discussion only. This indicates no endorsement of its content, nor that the Consortium has, is, or will be allocating any resources to the issues addressed by the NOTE. This document is being distributed to solicit public comment (to www-style@w3.org on the value of various proposed CSS extensions documented here. There is no commitment to turn these proposals into a recommendation.


This document describes a smaller number of properties which could be added to CSS1 to create a richer language that solves some of the most common problems encountered when using CSS1.

CSS 1.0 Cleanup

Length Units

When two length units are specified on 'margin', 'padding', 'border' and 'border-width', the "y" value comes before "x".

Magnification Property

Property Name: magnification

Value: percentage

Applies To: all elements

Initial: 1

Inherited: always

Specifies a magnification factor that will be applied to all lengths in the element.

Line Breaks

Property Name: break

Value: block-before | block-after | line-before | line-after | auto

Applies To: all elements

Initial: auto

Inherited: No

Determines whether the element causes a line break. If the value is after, then there is a line-break after the element. If the value is before, then there is a line-break before the element. If the value is auto, the normal box-layout algorithms determine line breaking. The following example shows how the BR element could be defined using this property:

BR { break: line-after; }

length unit on vertical align

Property Name: vertial-align

Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length>

Applies To: inline elements

Initial: baseline

Inherited: no

Percentage Values: refer to the 'line-height' of the element itself

The only change is the addition of <length> at the end.

Consider this source text:

    ... some <IMG SRC="img.jpg" ALT="shadowed"> text...

where img.jpg is a 16x150 pixel image of the word "shadowed" with a fancy effect. The intended "baseline" of the text inside the image is at 4 pixels from the bottom. The image should therefore be lowered 4 pixels below the baseline of the surrounding text

.To properly align the image, this style sheet will do:

IMG {line-height: 16px; vertical-align: -25%}

because 25% of 16px is 4px. This one would work as well:

IMG {line-height: 4px; vertical-align: -100%}

But the most simple solution would be:

IMG {vertical-align: -4px}

A typical source of such inline images is the LaTeX2html converter, which produces inline GIF images for all mathematical formulas. The MathML draft shows the same phenomenon (see e.g., http://www.w3.org/TR/WD-math/section1.html#sec1.2.2 )

marker pseudo element

In order to specifies fonts, colors, images, etc. for the markers used in lists, a new pseudo element will be created called marker. Here is an example:

UL:marker { color: red } 
OL:marker { font-family: times }

Text Shadows

Text shadow effects can be achived in CSS1 using negative margins and duplicated text. The results can be visually stunning, but have unfortunate side-effects for non-visual readers and people using browsers that odn't support style sheets. It is therefore impotant that a new property gets deployed before authors start using negative margins:

Property Name: text-shadow-color

Value: none | <color>

Initial: none

Inherited: no, but see clarification below

Percentage Values: indicate transparency

This property describes shadowing effects on the text of an element:

P { text-shadow: black }

The example above creates a black text shadow down and to the right of the text.

Note This creates increases the size of the box for this element.

Multiple shadows can be specified in comma-separated lists:

text-shadow: red 0.1em 0.1em, blue -0.1em -0.1em 80%;

The shadows are specified in top-to-bottom order. In the example above, the red shadow would be on top of the blue shadow.

The position and transparency values are:

Property Name: offset

Value: <length>{1,2}

Initial: 0.1 em

Offset values are relative to the text that is shadowed. If one length unit is specified, it describes both the x and y offsets. If two length units are specified, they describe x and y offsets respectively.

Generated text & counters

We are working on methods for adding generated text and counters. Specifically we want to have much richer control over the autonumbering and bulletting of list items, headings and other elements.


Property Name: cursor

Value: auto | crosshair | default | hand | move | e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize| text | wait | help

Initial: auto

Inherited: Yes

Specifies the type of cursor to be displayed for the mouse pointer.

auto: The UA determines the cursor to display based on the current context.

crosshair: a simple crosshair

default: The platform-dependent default cursor. Usually an arrow.hand: A hand

move: indicates something is to be moved

*-resize: indicates that the edge is to be moved

text: Used to indicate editable text. Usually an I-bar.

wait: A cursor to indicate that the program is busy and the user should wait. Usually a watch or hourglass.

help: Help is available for the object under the cursor. Usually a question mark or a balloon.

Filters & Text Effects

We are working on methods of applying a rich set of special effects to text and images such as image blurring and glow effects. The purpose of this is to use CSS to modify existing structural elements to be presented in a variety of ways. Rather than creating extra image information to accomplish the same effect.

Multi Column Layout

To flow content into several columns, two new CSS properties are proposed., columns and column-rule.

The formatting model of CSS1 is changed to include the new properties. Elements can now specify that their content, including child elements, should be flowed into columns. That means that the width of those child elements is derived from the column width instead of the parent's full width.

By default, i.e., when there is only one column, the sum of margin, border, padding and width for any block element is still equal to the width of the parent element. But when there are more columns, the sum is equal to the column width.

| <---------------------- width ----------------------> | 
|                                                       | 
|                                                       | 
|                         | * |                         | 
|                         | * |                         | 
|  #####################  | * |  # |               | #  | 
|  # .---------------. #  | * |  # |               | #  | 
|  # |               | #  | * |  # |               | #  |  
|  # |               | #  | * |  # |               | #  | 
|  # |               | #  | * |  # |               | #  | 
|  # |               | #  | * |  # |               | #  | 
|  # |               | #  | * |  # `---------------' #  | 
|  # |               | #  | * |  #####################  | 
|  # |               | #  | * |                         | 
|  # |<child's width>|    | * |                         | 
|  #                      | * |                         | 
|   ^-- child's padding     ^-- column rule             | 
   ^-- child's border 
  ^-- child's margin       ^-^-- 2 x 1/2 gutter

One can either specify the number of columns or the desired width of a column. All columns have the same width. The gutters and optional vertical rules between the columns can also be given. If the number of columns is specified, the actual column width is found by dividing the element's width by it. To be precise (n = number of columns, w = actual column width):

 width = n * w + (n - 1) * (gutter + column-rule) (1)

If the desired column width is specified instead, the number of columns is found by dividing the width by the desired column width and rounding to the nearest integer (w' = desired column width):

 width = n' * w' + (n' - 1) * (gutter + column-rule) (2) n = round(n') (3)

The actual width can thus be different from the desired width. For example: if the width of the element is 50em and the desired column width is 10em, with a 2em gutter and no rules, there is room for 4.3 columns (by equation 2), which rounds to 4 (by equation 3). The actual column width then works out to be 11em (by equation 1), or just a little larger than the desired width.

The formatter should try to divide the contents over the columns in such a way that all columns are of equal height (balanced columns).

Property Name: columns

Value: [ <length> | <number> ] [ <length> | <percentage> ]?

Applies To: block-level elements

Initial: 1

Inherited: no

Percentage Values: relative to element's width

The first part of the columns property sets the ideal column width of an element. If the column width is a length value, the number of columns will increase as the canvas is enlarged:

 DIV { columns: 20em }            /* relative to the font size */

To indicate a fixed number of columns, a number can be used:

 BODY { columns: 4 } /* 4 columns */

All values, length or number, should only be used to determine the number of columns. Once found, the available space should be split into columns with equal widths and the same space between them.

The space between the columns (called gutter), can optionally be specified by putting a second value on the columns property. The default is UA dependent. If a percentage is given, it is relative to the element's width.

If there is a rule between columns (see `column-rule' below), half of the gutter is at each side of the rule.

The gutter is transparent, which means the parent's background shines through.

Property Name: column-rule

Value: <width> <height>? || <style> || <url> || <color>

Applies To: all block elements

Initial: medium 100% none

Inherited: no [[yes?]]

Percentage Values: relative to own width and height, respectively.

If the style of the rule is not `none', the gutter is split in two halves and the rule is put in between.


The width (thickness) of the rule can be: [ thin | medium | thick | <length> | <percentage> ]. Thin, medium and thick are the same widths as for the border property. If the value is a percentage, it is relative to the element's width. Initial value is `medium'.


If there is a second length value, it represents the height of the rule. A percentage refers to the element's height. Initial value is 100%.


The style is a keyword from: [ none | dotted | dashed | solid | double | groove | ridge | inset | outset ]. If no value is specified, `none' is assumed. See the `border' property for the meaning of each keyword.


A URL for an image that is tiled to cover the rule. If a URL is specified and it can be loaded, the <style> is ignored.


The color of the rule. If omitted the value is UA dependent. The color is used to fill transparent regions of the image, while loading the image from the URL, if no URL is specified.

Possible enhancements

If the height of an element is known beforehand and (because the `height' property is not `auto' or the formatter is working within a fixed frame height), it should be possible to specify that the columns should not be balanced. This could be done, e.g., by adding a keyword `unbalanced' to the `columns' property.

What happens if the height is specified but is too small? CSS1 says that the element gets a (vertical) scroll bar. Another option is to add extra columns and a horizontal scrollbar instead. Maybe this latter option should be indicated on the `columns' property as well, e.g., by adding the keyword `fixed-height'.

`Fixed-height' and `unbalanced' could actually be combined into a single keyword, applying both to the case that the specified height is too large and too small.

Instead of adding a keyword `unbalanced' or `fixed-height' to `columns' to change the meaning of `height', one could also add a new property `column-height', which is `auto' by default, but implies unbalanced columns and/or a horizontal scrollbar when set to any other value.

A child element of an element with columns might be allowed to span several columns. A property `column-span' could be added for that purpose. An element cannot span more columns than are available to its right.

New properties are needed to control breaking text between columns, e.g., to force a header to start in a new column.

Maybe a way to specify a minimum and maximum width for the columns is needed as well, with a way to say where the remaining unused space is put.

Formatting example

 DIV { 
  columns: 20em 3em; 
  width: auto; 
 H1 { columns: 1 }  
  <P>This is the first paragraph. The first paragraph comes first,  
     before the second.  
  <P>After the first paragraph comes the second paragraph which 
     you are reading now.  
  <P>The third paragraph is the last paragraph. Not much more to say 
     about that. 

Since the value of `columns' is specified in a length unit, the number of columns will depend on the available width, i.e., the width of the BODY element. A User Agent may use two columns when started:

This is the first   graph which you 
paragraph.          The are reading now. 
first paragraph 
comes first, be-    The third para- 
fore the second.    graph is the last 
                    paragraph. Not 
After the first     much more to say 
paragraph comes     about that. 
the second para- 

If the canvas is enlarged, three columns may be used instead:

 This is the first     After the first    The third para- 
 paragraph. The        paragraph comes    graph is the last 
 first paragraph       the second para-   paragraph. Not 
 comes first, before   graph which you    much more to say 
 the second.           are reading now.   about that.

Margin, border and padding values should be honored within the columns. If the columns are not wide enough to display content properly, the UA may decide to reduce the number of columns.

Attribute based addressing

The CLASS attribute has been added to the HTML specifications with style sheets in mind, and enjoys a special shorthand notation as described in the CSS1 specification. Also, other attributes/values could be used in addressing:

  A[HREF] { color: red }          /* the HREF attribute exists */
  H1[CLASS = huge] { font-size: 60pt } /* another way of writing H1.huge */
  DIV[LANG = fr]  { font: 12pt/14pt Galliard } /* special styling for French text */

Sequential Addressing

CSS Level 1 contains functionality for addressing elements based on its ancestors. In level 2, one could also address based on siblings. A typical example is making the first paragraph after a headline bold:

 /H1/ P { font-weight: bold }

The '/' indicates the start of a sequential pattern search. All property declarations are performed on the last element of the search pattern.

Combined with the hierarchical search patterns, one has powerful context-sensitive addressing:

H1                  -- every H1 
H1, H2              -- every H1 and every H2 
(H1) EM             -- EM inside H1 
(DIV) (H1) EM       -- EM inside H1 inside DIV 
/H1/ P              -- P that immediately follows H1 
(DIV) /H1/ P        -- P that immed. follows H1 inside DIV 
(DIV) /H1/ (P) EM   -- EM inside P that immed. follows H1 inside DIV 
// P                     -- P that follows nothing (i.e., P that is 1st child) 

Note that the last example could have been written (DIV.chap) P.

Constants &environment variables

[interesting, but potentially complex issue]

The following environment variables are available for use in style sheets:

  • $AGE: the age of the document as reported in the HTTP header
  • $WIDTH: window width
  • $HEIGHT: window height ï
  • $DWIDTH: display width
  • $DHEIGHT: display height
  • $BASE: the document's URL

The following two are only defined inside an element that contains a hyperlink:

  • $FETCHED: percentage of document fetched
  • $FIRSTVISIT: time since first visit to that link
  • $LASTVISIT: time since most recent visit to the link

One could then change the color of a hyperlink with:

 a[href] { color: dark-red << $LASTVISIT/30d >> dark-blue }

The combination of constraints and environment variables can be quite interesting. Set the left margin to be 1/10 of the window width, but always more than 2em and less than 20em:

 { margin-left:  2em << $WIDTH/10 >> 20em }

Let the color of the background fade from white to yellow as the document ages. After two days (2d), the fading process is complete:

  { background: white << $AGE/2d >> yellow }

Let the color of text links change from red to blue as the document loads:

  { text-link: red << $FETCHED >> blue }

Addressing environment properties

[This section is under fire. Among the strongest charges against it is the possible introduction of asymmetry ("the user can do this, but not the author"). If you would like to see it survive, you should voice your opinion.]

While the main focus of this specification is to define a standard for attaching style to HTML, the users' WWW browsing environment has additional elements. Applications have a user interface, they show you the HTML source on request, and GUI clients have a window size. While one normally would leave user preferences to the application and a configuration file, the notion of cascading style sheets has the potential of addressing all issues of style through one interface. The user's personal style sheet can be used to set the fonts of the browser buttons as well as incoming documents' H1 elements. Authors should be careful when trying to influence environment properties, and clients could choose to ignore them.

It is important to syntactically mark the difference between style properties of the environment and HTML elements. One should be careful when picking names. Here are some possibilities:

$HTML-SOURCE { font-family: courier, font-size: 12pt } 
$CLIENT-WINDOW { width: 600px, height: 800px } 
$CLIENT-WINDOW { font-family: helvetica } 
$HTML_ERROR { color: yellow, background: red

An initial '$' marks environment elements.