[The purpose of this document is to keep track of ideas and suggestions related to the cascading style sheet proposal. It's a scratchpad, implementor's guide and discussion room in one. By the end of 1995, we plan to have the document evolved into an internet draft. Last changed: July 3, 1995.]

Cascading Style Sheets: a draft specification

  1. Introduction
  2. Addressing
  3. Properties
  4. Units
  5. Constraints and environment variables
  6. Cascading order
  7. Shortcuts
  8. Formatting model
  9. Terminology
  10. Acknowledgements

Introduction

The purpose of this document is to keep track of ideas and suggestions related to the cascading style sheet proposal. It's a scratchpad, implementor's guide and discussion room in one. Nothing here is finalized, but the document will evolve towards an internet draft. To contribute, send comments and ideas to the stylesheet mailing list (www-style@w3.org) or to the author of this document. For background material, see the resource page on HTML style sheets.

Goals

HTML is under constant pressure to add visual presentation tags and attributes. We believe the author or publisher of a document should be able to attach presentation hints to a document, but style sheets--which are attached to documents instead of intermingled in them--are better than extending HTML itself. At the same time, readers should retain control of the presentation.

The appearance of the web can be improved by a style sheet mechanism that:

This document is a specification of a style sheet mechanism that support these goals.

While the proposed style sheet mechanism is general enough to apply to all versions of HTML, it is being developed in conjunction with HTML3 and closely matches its design guidelines. Also, this document should be general enough to apply to other DTDs than HTML.

Containment

Style sheets are located in HTML3's proposed STYLE element, or referenced through a LINK:
<HEAD>
  <TITLE>Title</TITLE>
  <STYLE notation=css>
    h1: font.family = helvetica
  </STYLE>
  <LINK rel=StyleSheet href="bill.style">
</HEAD>

Typically, a company-wide style sheet will reside in one location and be referenced through a LINK. The author may add style hints in the STYLE element. If conflicts arise, the hints inside STYLE will override those referenced through LINK.

Addressing

The attachment of style hints to content is based on HTML elements. Single HTML elements is the smallest addressable unit. This example sets properties for the P and the EM tag:
  P: font.family = helvetica
  EM: back.color = red

Element grouping

  h1, h2: font.family = helvetica
[Note that element groups replaces the previously proposed element regular expressions (h[12]: font.family = helvetica).]

Classes

To increase the granularity of control, HTML3 introduces a new attribute: CLASS. Most elements can ble subclassed, and the subclass can be addressed in the style sheet:
<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE>
    H1.punk: font.color = #00FF00
  </STYLE>
 </HEAD>
 <BODY>
  <H1 class = punk>Way too green</H1>
 </BODY>
</HTML>
[Should we add addressing based on other attributes/values?
  A{HREF} : font.color = red
  H1{CLASS = huge} : font.size = 60pt
Clearly more general]

Default properties and inheritance

Style sheets can be partial, and we need a mechanism for resolving values when none has been specified explicitly. The general rule is to take style property values from a set of document defaults if no value has been assigned.

The document default is addressed with an asterisk:

  *: font.family = futura
Note that regular expressions in general are not supported in the style sheet notation.

Character-level elements (i.e. elements that do not cause a paragraph break, as opposed to the block-level elements which do) inherit values from the surrounding block. E.g., If no color value has been assigned to EM, emphasized text will inherit the color from the surrounding text, not from the document-wide default.

Also, elements "inherit" their horizontal and vertical position from ancestors. See the Formatting Model for more on this.

Context-sensitivity

It is useful to set style properties based on the context of the element. A typical example is making the first paragraph after a headline bold:
  /H1 P/: font.style = bold
The initial "/" indicates the start of a sequential pattern search. All property assignments are performed on the last element of the search pattern. Subclasses can be specified in the search pattern:
  /H1 P.ingress/: font.style = bold
Only children of BODY are regarded in sequential search patterns.

By specifying a hierarchical search pattern, one can set properties based on the ancestors of an element. E.g., since headlines often are rendered in bold, one may want to assign a different color to the EM element within an headline:

  (H1(EM: font.color = red
[Alternative syntax:
  (H1 EM: font.color = red
  (H1(EM)): font.color = red
]

Class specifications are also allowed in a hierarchical search pattern.

Addressing environment properties

While the main focus of this document is to define a stadard for how to present HTML documents, 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 environement 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
An initial '$' marks envionment elements.

Properties

This section lists likely names of settable style properties without claiming completeness. If the list of values is specific to a property, they are described in this section, while generic units (e.g. color and length) are found in the section on units.

Font

Setting font properties will be among the most common uses of style sheets. Unfortunately, there exists no well-defined taxonomy for classifying fonts, and terms that apply to one font family may not be appropriate for others. E.g. "italics" is commonly used to label slanted text, but the term is not approriate for sans-serif fonts which should be labeled "oblique".

This document suggests a liberal terminology for describing fonts, and a level of detail similar to current desktop publishing applications:

NAMEUNITS
font.sizespatial, index
font.family
font.style
font.colorcolor
font.leadingspatial
font.spacingpercent

font.size

Font sizes are traditionally expressed in points. Since it's easy to convert between points and other length units, there is no reason not to allow other spatial units to be used:
  H1: font.size = 20pt    // points
  H2: font.size = 15px    // pixels
  H3: font.size = 1.35%   // 1.35% of the width
Also, a font size can be an index into an array of font sizes. The index is in the range of 1-7, the default being 3:
  P: font.size = 4;
  EM: font.size = +2;
In the latter example, the font size is expressed relative to the surrounding text.

font.family

Thousands of different font families exist, but your average GUI is only able to display a few of them. Since the author of a document cannot know what fonts will be available, a prioritized list of font family names can be supplied:
  H1:  font.family = futura, helvetica
  P:   font.family = new-century-schoolbook times
  PRE: font.family = courier
List items are separated by white space and/or commas. Spaces in font familiy names are replaced with dashes.

font.style

A large number of terms are used to describe different styles within font families. Some of them are ambigous (e.g. "black" and "gothic"), and this complicates the standardization of a style sheet language.

A font style can be one or more these keywords:

The list is not complete, and is grouped for overview purposes only. The end result is the addition of styles specified:
  H1: font.style = bold, italic
If two keywords are mutually exclusive, they should be regarded as a prioritized list:
  P:  font.style = demi-bold, bold
Here, "bold" is used if "demi-bold" is not available.

Most of the above keywords are well-defined in current literature, but one group of keywords demand explantaions:

KEYWORDEFFECT
small-capsAll lower-case text in a small caps region is changed to small capital letters. Also, punctuation character adjacent to affected letters are resized to match the small caps. The rendering of the letters uses the undersize.font.* properties.
big-capsAll capital letters are rendered using the oversize.font.* properties. Also, punctuation adjacent to affected letters is resized.
big-initialThe initial letter of the element is rendered using the oversize.font.* properties. Also, punctuation characters adjacent to affected letters are resized.
droppedAll characters displayed using the oversize.font.* properties are dropped below the baseline so that they vertically align with the rest of the text in the element.

Using these, commonly used typographic effects can be achived:

(Style sheet)

   EM.first : font.style = dropped big-initial small-caps
   EM.first : font.size = 12pt
   EM.first : undersize.font.size = 12pt
   EM.first : oversize.font.size = 24pt   // assuming leading is zero

(HTML)

  <EM class=first>The first</EM> few words of an article in The Economist..

(Output, very primitive version)
  ___
   | HE FIRST few words
   |of an article in the
  Economist.
The example raises a few issues: [We may want to allow for a more structured naming scheme for styles, e.g.:
  H1: font.weight = bold
  P:  font.slant = oblique
This is not only syntactic sugar, since the attributes would be expected to inherit independantly of each other.]

font.color

This property specifies the foreground color of text:
  H1: font.color = DarkRed;
  P:  font.color = #F00
The corresponding property for the background color is back.color. A more detailed description of ways to specify color can be found in the section on units.

font.leading

"Leading" is a typographic term which describes the distance between two lines of text. Fonts are ofter referred to with their size, leading and name, e.g. "12/14 Times".
  P: font.size = 12pt; font.leading = 14pt

font.spacing

  P: font.spacing = 120%

Oversized and undersized fonts

To allow for common typographic styles like an oversized initial letter at the beginning of a paragraph (e.g. "dropdown") and undersized capital letter ("small-caps"), two variations of the font.* properties exist: oversize and undersize.

Example of use:

  H1: font.style = big-caps
  H1: oversize.font.size = +3             // a la Netscape
  P:  font.style = dropped big-initial
  P:  oversize.font.size = 4x             // i.e. cover 4 line's height
  P:  oversize.font.style = sans & italic & bold

Margin

Margins set the space around an element. The background will be the one of the document.

NAMEUNITS
margin.leftspatial
margin.rightspatial
margin.topspatial
margin.bottomspatial

[is "space" a better word than "margin"?]

[Also, there should be a way of indicating how much of the margin should have the the same background as the content; the rest of the box should inherit the background from the surrounding box.]

Background

NAMEUNITS
back.colorcolor
back.imageurl

Additions

[Here we start messing with the HTML and possibly the content. Be critical!]

NAMEUNITS
add.beforehtml
add.afterhtml

Example:

  H1: add.before = <TABLE BORDER>
  H1: add.after = </TABLE>
[Is "add" a good word? text.header? enclosure.above? ]

Various non-sorted properties

NAMEUNITSCOMMENT
indentindentation of the first line, alternative is line.indent or margin.first
alignalignent of content in block
widthspatialsets the width of a box (instead of being the area betweens the margins)
heightspatialsets the height of a box (instead of being the area betweens the margins)

Links

[Some thinking left here]

Should link properties be attached to the anchor tag? This is in line with the rest of the proposal, but seems less than intuitive:

  A: font.color = #00F
  (H1(A)): font.color = #F00
Perhaps a separate property:
  html:  txtlink.color = #00F
Then, one could also set per element link properties:
  P: txtlink.color = #00F
  H1: txtlink.color = #F00
[Too much flexibility??]

Should one be able to set different values according to the type of link, e.g. text or image?

  P: text.link.color = #00F
  P: image.link.color = #0F0
  P: link.style = 3D
Will this mean we'll have to extend the language for each new media type that comes out?
  txtlink.color = blue
  txtlink.color = blue < AGE / 7d < "Background Color"
  imglink.color = default
  imglink.size = 3px
  imglink.style may be line, bevel, default, none
  txtlink.style may be underline, double underline,
     inverse, default, none
[Check out Kevin's last comments on this]

List Numbering

Tony Jebson proposes:
 *: numbering = on|off
 *: number.style = arabic|lowerroman|upperroman|loweralpha|upperalpha
 *: number.inherit = on|off

Units

Spatial

  inches (in)
  pixels (px)
  centimeters/millimeters (cm/mm)
  ems (em)
  ens (en)
  points (pt)
  characters(ch)
  picas (pa)

Color

By default, the RGB color model is being used. Other color models should be kept in mind for later extensions.

Different ways to specify red:

  EM: font.color = #F00
  EM: font.color = #FF0000
  EM: font.color = 255, 0, 0
  EM: font.color = 1.0, 0.0, 0.0
  EM: font.color = red
The conversion of color names ("red") to a corresponding RGB value is often window-system dependant. It would be beyond this specification to sanction a list of color names and their values. It is suggested that color-capable GUI clients, regardless of window systeme, support the basic colors of the english language with light and dark variations:
  H1:      font.color = Yellow
  EM:      font.color = DarkRed;
  STRONG:  font.color = LightBlue;

index

In addition to setting the font size with a spatial value, one can specify an index in the range 1-7.
  h1: font.size = 4
  h1: oversize.font.size += 2
[There should be a way for the user (only?) to set the array of fonts]

[Index could also be used to set e.g. the weight of a font?]

Constraints and environment variables

[very interesting, but potentially complex issue]

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

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:

  html : 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:
  html : color.background = white < $AGE/2d < yellow
Let the color of text links change from red to blue as the document loads:
  html : text.link = red < $FETCHED < blue
[Replace syntax with Metafont's as suggested by Bert.]

Arithmetic

Addition, substraction, multiplication and division supported. Note how other element values are referenced:
  h2: font.size = h1[font.size] * 0.8
  P : font.size = H1.foo[font.size] - 12 pt
[What's the best notation for referencing other values? Previously, this document suggested: "H1.foo:font.size"]

The notation for setting relative values:

  h1: font.size = 4
  h1: oversize.font.size += 2

Constants/Variables

Kevin proposes:
  define "My Gray" "191, 191, 191"
  P : font.color = "My Gray"
This would be a simple and workable scheme. What do we gain from going one step further and introduce variables?

Cascading order

Both readers and authors may use the style sheet language to specify preferences (the style sheet specified in, or referenced from, the initial document becomes the personal preferences of the reader). In most cases the reader will be happy to accept the style hints from the author, but human or technologial handicaps may require the overriding of the author's hints.

When the indicated preferences conflict, the style sheet mechanism needs a way to resolve the disagreement. In this proposal, both the reader and the author can associate weight with their preferences:

  font.family = helvetica ! important
  font.color = black ! insist
[Bill proposes using a standard notation for the priority, e.g. "h1: font.family=courier ; priority=insist"]

The list below indicates the hierarchy of style hints:


  reader lens               used for interactive control, e.g. "zoom in"

  reader insist             e.g. to compensate for handicaps

  author important/insist   to indicate special weight
  reader important

  author normal             default weight, no tagging needed
  reader normal             taken from initial document

  application default       hardcoded fallback values

In addition to the important and insist tags, the legal tag indicates that there are legal reasons for the choice of styles, e.g. a font size requirement:
  P: font.size = 12pt ! legal "IATA regulations"
The optional string following legal gives an explanation for its use. The client should warn the reader, and display the explanation, when style hints tagged "legal" are overridden and this isn't clear from the context.

Contexts where this should be clear:

One should also keep in mind that:

In general, the HTML3 banner area is a better place to put legal information.

Shortcuts

Vocabulary

The style sheet mechanism should be liberal in accepting alternative names, e.g. to shorthen the length of a style specification. Also, people come to the web from different platforms and bring vith them different vocabularies.
image : img
back  : background, bg 
fore  : foreground, fg
pt    : point, points
pa    : pica, picas

etc.

Grouping

As descibed above, elements grouped to reduce typing and bandwidth. Also, each element (group) can take several value assignements:
  h1: font.size = 12pt; back.color = red
  h1, h2: font.family = helvetica; font.size = 12pt
[possible font-specific grouping:
  P: font = 12/14 times bold
]

Formatting model

This doument suggests a simple box-oriented formatting model. Each element that implies a line break (e.g. H1 and P, but not EM) is surrounded by a box. The size of the box is the sum of the formatted content (e.g. text or image) plus the corresponding margins. The margins are setable in the style sheets:
  h1: margin.left = 20pt; margin.right = 30pt;
  p:  margin.top = 15pt; margin.bottom = 10pt;
Vertically, all boxes are attached to the above box. Note that the abov box doesn't necessarily contain the preceding HTML element. See the last box for an example.

Horizontally, boxes inherit the maximum space after the ancestor's margins have been deducted.

This is a very simple example that shows how an H1 element is followed by a P, and how their margins are added to the ones belonging to BODY:

  ___________________________________
 |                                   |
 | (BODY margins)                    |
 |    _____________________________  |
 |   |                             | |   white space = margins
 |   | (H1 margins)                | |   '.' = white space
 |   |                             | |   ';' = unclaimed territory
 |   |   This.is.the.headline!..   | |
 |   |_____________________________| |
 |   |                             | |
 |   | (P margins)                 | |
 |   |                             | |
 |   |   This.is.the.paragraph..   | |
 |   |   which.is.used.to.convey   | |
 |   |   how.elements.are.put.on   | |
 |   |   top.of.each.other......   | |
 |   |_____________________________| |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |___________________________________|
 
When nested lists are added, the picture becomes a bit more complicated:
  ___________________________________
 |                                   |
 | (BODY margins)                    |
 |    _____________________________  |
 |   |                             | |
 |   | (UL margins)                | |  <- first level UL element
 |   |  ________________________   | |
 |   | |                        |  | |
 |   | | (LI margins)           |  | |
 |   | |                        |  | |
 |   | |  First.item........    |  | |
 |   | |________________________|  | |
 |   | |                        |  | |
 |   | | (UL margins)           |  | |  <- second level UL element
 |   | |  __________________    |  | |
 |   | | |                  |   |  | |
 |   | | | (LI margins)     |   |  | |
 |   | | |                  |   |  | |
 |   | | |  Second.item...  |   |  | |
 |   | | |__________________|   |  | |
 |   | |________________________|  | |
 |   |_____________________________| |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |___________________________________|

Note that the left edge of the second-level UL box ends up being aligned with the above LI box since they both are children of the first-level UL element.

Since boxes are stacked vertically, some interesting effects can be achived if sequential boxes don't end up on top of each other. In this way, "hanging headlines" and simple multiple-column layouts can be supported:

  __________________________________________
 |                                          |
 | (BODY margins)                           |
 |  ______________   _____________________  |
 | |              |;|                     | | 
 | | (H1 margins) |;| (P margins)         | |
 | |              |;|                     | |
 | | Headline...  |;| While.the.paragraph | | 
 | | comes.here.  |;| starts.here.and.... | |
 | |______________|;| continues.below.the | |
 | ;;;;;;;;;;;;;;;;;| box.to.the.left.... | |
 | ;;;;;;;;;;;;;;;;;|_____________________| |
 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |__________________________________________|

The above could be realized through:
  h1: margin.left = 10%; margin.right = 60%
  p:  margin.left = 50%; margin.right = 10%
The percentages are relative to the width of the canvas

Terminology

reader
author
style sheet
property
element
document
value
hint
canvas

Acknowledgements

This document is based on active input from: Style sheet proposals from the following people have been influential: Also, thanks to Tim Berners-Lee, Phill Hallam-Baker and Terry Allen for constructive discussions.
Håkon Lie (howcome@w3.org)