This is the third major revision of the specification. It is on its way from a loose collection of ideas to an Internet-Draft, and we plan to finish by the end of 1995. In this version, the basic parts ("level 1") are approaching stability, and we encourage programmers and authors to start experimenting. We also encourage comments, especially with regard to the separation of levels (is level 1 still too fat?), the naming of properties and values (some have question marks behind), and the idea of using CLASS as selectors. Please send comments to the mailing list, or directly to the authors. For background material, see the resource page on HTML style sheets. Last changed: August 10, 1995

Cascading Style Sheets: a draft specification

Håkon W Lie (
Bert Bos (


  1. Background
  2. Overview
  3. Terminology
  4. Introduction: level 1
  5. Sketches of level 2 and beyond
  6. Properties: level 1
  7. Properties: level 2 and beyond
  8. Units
  9. Cascading order
  10. Shortcuts
  11. Formatting model
  12. Formal grammar
  13. References
  14. Acknowledgments


HTML is a simple structural document format much used on the World-Wide Web. Web publishers commonly request more influence over the presentation of documents, and HTML is under constant pressure to add visual markup. Allowing publishers to attach style to documents will enhance the aesthetics of the web. Also, style enhances content: some publishers consciously choose colors and fonts based on the message they want to convey.

The web needs a mechanism that allows authors to influence the presentation while preserving the device-independence and document structure of HTML. There are four ways to do this: add new style elements to HTML, add new style attributes to existing HTML elements, resort to other formats (e.g. Postscript, PDF or GIF), or introduce style sheets. The first two alternatives will start a never-ending process of extending HTML to become a presentation language. Also, by not separating style and content they make it hard to apply different styles to the same content. The third alternative offers publishers more control by using presentation-oriented format. Sometimes control is important, but most requests for stylistic influence over text can be satisfied without leaving HTML. We think the fourth alternative, style sheets, is the best way to add style to the web.

Style sheets are very similar to the "templates" of desktop publishing applications. A simple style sheet might suggest that the headlines of a document are rendered in blue on a white background. By attaching style (colors) to the structure of a document (headlines), style sheets ensure device-independence and the preservation of document structure. A style sheet can be stored separately from the document it applies to, and it's easy to change the presentation of a document by applying a different style sheet. Also, one style sheet can be applied to many documents.

HTML is an application of SGML [SGML], and the style sheet mechanism described in this specification is intentionally general enough to apply to any SGML DTD. For reasons of simplicity, all examples apply to HTML. The proposed style sheet mechanism is being developed in conjunction with HTML3 and closely matches its design guidelines.

While style sheets will open for publishers to add style to their documents, the reader should also be able to influence the presentation. Sometimes the output device on the reader's side needs special consideration (helvetica looks terrible on this screen!), sometimes personal handicaps requires special consideration (12 pt helvetica? I havn't been able to read that since I turned 80!), and readers may have their own aesthetical preferences (helvetica looks terrible on any screen). This proposal is called Cascading Style Sheets (CSS) for its ability to merge several style sheets from both readers and authors.


Publishers on the web do not request presentational control to the level of professional typography. Instead, they ask for influence over fonts, colors and space, and they want it now. In order to speed up the process of defining and implementing a style sheet mechanism on the web, levels have been introduced in this specification. Level 1 contains the most basic features of a style sheet mechanism, while retaining much of the expressive power. A tutorial of level 1 style sheets is given in the introduction. After that, sketches of level 2 and beyond can be found, most of which are still being discussed.

Similarly, the properties have been divided into levels. Level 1 properties include fonts, text and space, but leaves borders and page properties to level 2.

Implementors will also find a formal grammar for level 2.


the author of a document
the part of the UA's drawing surface onto which documents are rendered
Cascading Style Sheets.
the designer of a style sheet
parsed SGML document. In technical terms, the document's ESIS (Element Structure Information Set).
SGML element
Hypertext Markup Language, an application of SGML
a stylistic parameter that can be influenced through CSS
the reader of a document
Standard Generalized Markup Language, of which HTML is an application
style sheet
a collection of selectors and their respective style hints.
User Agent. Commonly referred to as "web browser" or "web client".
synonymous with "reader"

Introduction: level 1

Designing simple style sheets is easy. You only need to know a little HTML and some basic desktop publishing terminology. E.g., to set the text color of H1 elements to blue, you can say:
  H1: text-color = blue
The example consists of three parts: selector ("H1"), property ("text-color") and value ("blue"). The selector is the glue between the HTML document and the style, and all HTML elements are possible selectors. HTML elements are defined in the HTML specifications, and the CSS specification only defines a syntax for how to address them. Also, the list of properties and values that can be assigned to elements are defined here. The list of level 1 features has been kept to a to a minimum, while making sure commonly used styles can be expressed.


In order for the style sheet to influence the presentation, the user agent (UA, also known as "web browser" or "web client") must be aware of its existence. This can be done by putting the style sheet inside HTML3's proposed STYLE element, or reference it through a LINK:

    H1: text-color = blue
  <LINK rel=StyleSheet href="">

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

[There may be several LINKs, in descending order of priority?]


To reduce the size of style sheets, you can group selectors:
  H1, H2, H3: font-family = helvetica
Similarly, assigments can be grouped:
  H1: font-size = 12pt, text.leading = 2pt, font-family = helvetica, font-weight = bold
The above exemplified grouping mechanisms are general and can be used with all selectors and assignments. In addition, some properties have their own grouping syntax:
  H1: font = 12pt/14pt helvetica bold
which is equivalent to the previous example.


In the first example, the color of H1 elements were set to blue. Suppose we have a H1 element with an emphasized element inside:
  <H1>The headline <EM>is</EM> important!</H1>
Since no color has been assigned to EM, the emphasized "is" will inherit the color of the surrounding element, i.e. it will also appear in blue. Other style properties are likewise inherited, e.g. font family and size.

Inheritance start at the oldest predecessor. In HTML, this is is the "HTML" element (although many HTML authors omit this tag). In order to set a "default" style property, you should use "HTML" as selector:

  HTML: text-color = dark-blue       -- make dark-blue default

(Note how textual comments start with "--" and run to the end of the line.)

Alternatively, the top-level element can be addressed as "*", e.g.:

  *: text-color = dark-blue

Some style properties are not inherited from the parent to the child. In most cases, it is intuitive why this is not the case. E.g., when you set a border around a list (UL, OL, DL), you don't want each list item (LI) to have borders around them.

Context sensitivity

Inheritance saves CSS designers a lot of typing. Instead of setting all style properties, you can create defaults and then list the exceptions. If you want to give EM elements within H1 a different color, you may specify:
  H1   : text-color = blue
  EM   : text-color = light-blue
When this style sheet is in effect, all emphasized sections, within or outside H1 will turn light-blue. Probably, you only wanted EMs within H1 to turn light-blue. You can specify this with:
  (H1) EM : text-color = light-blue

The selector is now a search pattern. Only the last element of the search pattern is addressed (EM), and only so if the search pattern matches (if EM is inside an H1 element). Note that there may be several generations between EM and H1.

More properties

So far, blue colors have dominated our examples. As you may have guessed, you can specify other colors as well. Also, the style sheet will give you influence over what fonts to use:
  H1: font-family = helvetica
  H1: font-size = 12pt
[describe more features]

A more fancy example includes a drop-cap initial and small-caps text:

   P  : text-effect = drop-cap
   P  : font-size = 12pt
   P  : alt-font-size = 24pt      -- assuming leading is zero
   EM : font-style = small-caps
  <P><EM>The first</EM> few words of an article in The Economist..
On an ASCII-device, the above could be formatted as:
   | HE FIRST few words
   |of an article in the
The example shows the need for a new generic character-level element in HTML which doesn't bring with it any rendering conventions. We suggest using MARK for this.


One of the features of CSS is that more than one style sheet can influence the presentation. There are two main reasons for this feature: modularity and balance.

Modularity: a style sheet designer can combine several (incomplete) style sheets into one to reduce redundancy:

  @import ""

  H1: text-color = red       -- override included sheet

The @import .. statement is semantically equal to a <LINK REL=StyleSheet href= .. >. In case of a conflict, the imported style sheet has lower priority than the one from where it's being imported. [That's why we call in "import", not "include"]

Balance: both readers and authors can influence the presentation through style sheets. To do so, they use the same language and this reflects the philosophy of the web: everyone can become a publisher.

Typically, UAs will assume that the style sheets of your initial page (if it finds any) is your personal favorite, and apply them to all subsequent documents. If subsequent documents have their own style sheets, conflicts may arise. Conflict resolution is based on each style assignment having a weight. By default, the weights of the reader's assignments is less that the weights of the assignments in incoming documents. I.e., if an incoming document has style sheets attached, they will be used even if the reader has personal style sheets. However, the reader can add to the weights of style assignments to make them override the styles of the author:

  H1: color = red ! important
Also, if there are legal reasons behind the author's styles, this can be indicated:
  P: font-size = 12pt ! legal "IATA regulations"
The description following "! legal" is a warning that should be displayed before being overridden by the reader.

A complete description of the cascading order can be found later in this specification.


To increase the granularity of control over elements, HTML3 introduces a new attribute: CLASS. Most elements can be subclassed, and the subclass can be addressed in the style sheet:
    H1.punk: text-color = #00FF00
  <H1 class = punk>Way too green</H1>

[The use of the CLASS attribute is under discussion, and the syntax may not be stable yet. One future direction is to allow addressing based on CLASS in level 2]

[How do we deal with multiple classes?]

Attribute-based addressing

The CLASS attribute has added to the HTML3 specifications with style sheets in mind, and enjoys a special shorthand notation as described above. Also, other attributes/values be used in addressing:
  A{HREF} : text-color = red           -- the HREF attribute exists
  H1{CLASS = huge} : font-size = 60pt  -- another way of writing H1.huge
User agents commonly display newly visited anchors differently from older ones. Ideally, the style sheet mechanism should offer functionality to describe how and when anchors should change. This will be possible with the environment variables of level 2, but for level 1 we need to introduce two pseudo-attributes that can be used for addressing:
  A{HREF}{OLD} : text-color = red
  A{HREF}{NEW} : text-color = blue
[Does anyone have a better solution?]

Sketches of level 2 and beyond

In level2, the values of level 1 turn into expressions, and the addressing scheme is extended.

Sequential patterns

[needs work]

Level 1 contains functionality for addressing elements based on its ancestors. In level 2, one can 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 assignments 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)
  (DIV{CLASS=CHAP}) P -- P inside DIV with CLASS=CHAP

Multiple media

[needs work]

Could one come up with a simple set of binary conditions to describe an output medium. How about:

Then, conditional hints could look like:
  [hires & color & bitmap]
    H1: font-size = 4

    H1: font-size = 24pt

    h1: font-size = 60pt

Constraints and environment variables

[interesting, but potentially complex issue]

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

The following two are only defined inside an element that contains a hyperlink: One could then change the color of a hyperlink with:
  a{href}: text-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:
  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

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: text-color = yellow, text-background = red
An initial '$' marks environment elements.


[needs work]
  @define myred = 0.8, 0.1, 0.1

[Should one define a lexical macro, as in C, or a symbolic constant, as in Pascal?]

[What if "myred" has different definitions in various style sheets?]


[needs work]

Addition, subtraction, multiplication and division are supported.

Relative values

Ideally, one should be able to refer to other elements' values in expressions. Since values may be context-dependent, they could be hard to find.
  h2: font-size = h1[font-size] * 0.8
  P : font-size =[font-size] - 12 pt
Instead, one may rephrase expressions in terms of either the inherited property or a symbolic constant. In either case, no special syntax is required:
  font-size = font-size - 12pt       -- relative to inherited size
  text-color = myred                 -- relative to constant

Class as selectors

Should one be able to use classes as selectors, i.e., without a GI? People can then introduce new elements without writing new style rules:

  <par class=p>This is a <emph class=em>PAR</emph>, which looks like a
  <tag class=strong>P</tag>, because it is declared as being of of the
  same class.</par>

Properties: level 1

This section lists names of settable style properties and their corresponding units. The are grouped for overview purposes only.


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 appropriate for sans-serif fonts which should be labeled "oblique".

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


Value: <length>
Initial: UA specific
Level: 1
Example: font-size = 12pt

Font sizes can either be set to a certain height using "font-size", or to a relative index using "font-size-index". If defined "font-size" will take priority.

Note that an application may reinterpret an explicit size, depending on the context. E.g., inside a VR scene a font may get a different size because of perspective distortion.


[needs work]

Value: <number> | smallest | smaller | small | normal | large | larger | largest
Initial: normal
Example: font-size-index = largest

Index 3 corresponds to "normal" (the actual size is application dependent/settable by the user). It is suggested that the expression

  font-size-index = font-size-index + 1
is equivalent to
  font-size = font-size * 1.2
[Is there a shorter/better name than font-size-index?]


Value: [ <generic-family> | <family-name> ]+
Initial: UA specific
Level: 1
Example: font-family = new-century-schoolbook times

The value is a prioritized list of font family names and/or generic family names. List items are separated by white space and spaces in font family names are replaced with dashes.

[Do any font names contain '-' ?]

The user agent should stop searching as soon as a font family that fulfills the requirement is found. E.g.: = serif helvetica
If the user agent finds a "serif" font family, "helvetica" will be disregarded.

Possible generic families:


Value: extra-light | light | demi-light | medium | normal | demi-bold | bold | extra-bold | -3 | -2 | -1 | 0 | 1 | 2 | 3
Initial: 0
Level: 1
Example: font-weight = demi-bold

Where extra-light = -3, light = -2, demi-light = -1, etc.

If the desired weight is not available, the substitution order is undefined.


Value: italic | italics | roman | oblique | upright | small-caps | normal
Initial: normal
Level: 1
Example: font-style = italic

[the definitions are a bit tricky]

"italic" and "italics" are synonyms.

If "font-family" is defined, "italic" is synonymous with "oblique" and "roman" is synonymous with "upright".

If "font-family" is not defined, "italic" and "roman" will select a "serif" font family, while "oblique" and "upright" will select a "sans-serif" font family.

[Since there always will be some definition of "font-family" (in the end, the UA should have a fallback value), "not defined" should read "not defined at the same weight level". This may be a non-intuitive distinction]

If "small-caps" are not available, capital letter of a smaller font size should be used to render small characters. "small-caps" can be combined with other styles:

  H1: font-style = small-caps & italic

font-leading (or text-leading?)

Value: <length> | <percentage>
Initial: UA specific
Level: 1
Example: font-leading = 20%

"font-leading" refers to the extra space between lines. If a percentage is specified, it is relative to the font size.

[arguably, leading is not a font property but a text property. The main argument for calling it "font-leading" is that it's settable through the "font" shorthand.


Value: size [ / leading ] family [ weight ] [ style ]
Initial: not defined
Level: 1
Example: font = 12pt/14pt helvetica bold

This is equivalent to setting font-size, font-leading, font-family, font-style, and font-weight. The shorthand notation takes priority if defined.



Value: <color>
Initial: UA specific
Level: 1
Example: text-color = 0.0 0.0 0.5


Value: <color> | <uri> | none
Initial: UA specific
Level: 1
Example: text-background = ""


Value: <percentage>
Initial: 1.0
Level: 1
Example: text-spacing = 120%

[to be consistent with font-leading, perhaps the default spacing should be 0?]

text-line (a better name should be found: or text-deco, text-trimming?)

Value: under | over | through | box | shadowbox | box3d | cartouche | blink | none
Initial: none
Level: 1
Example: text-line = under

The list of possibilities may be kept short in a first version, it can always be extended later. Formatters should treat unknown values as `box' (a simple rectangle).

text-position (or text-raise)

Value: <signed number> | sub | super
Initial: 0
Level: 1
Example: text-position = -2


Value: capitalize | uppercase | lowercase | none
Initial: none
Level: 1
Example: text-transform = uppercase

"capitalize" uppercases the first character of each word. [define word]

"none" is needed to neutralize the inherited value.

[should capitalized characters be rendered in small-caps or normal capital letters when text-style is "small-caps"? Probably normal]

text-effect (previous: text-style)

Value: initial-cap | drop-cap | alt-firstline | none
Initial: none
Level: 1
Example: text-effect = drop-cap

All rendered using the alternate font/text styled defined with "alt-font" and "alt-text".

Alternate font/text/style

Alt.font/alt.text is used to render initial capital, first line, and for labels and inserted text before/after the element.
Note that alt-text-effect is not a valid property.

align (or justify)

Value: left | right | center | justify
Initial: human language dependant
Level: 1
Example: align = center

This property applies only to elements that are not inline (i.e., that require at least a paragraph break after or before).


Technically, margin properties are not inherited. In practice, margins are inherited since the placement of a rendered element is relative to ancestors and siblings. See the formatting model for more on this.

margin-left, margin-right

Value: <width>
Initial: 0
Level: 1
Example: margin-left = 2em

The vertical space between two blocks of text is the maximum of all bottom margin and top margin specifications between the two. For example, between `abc' and `def' in the fragment "</P></LI></OL><P>def..." the space is the maximum of the bottom margins of P:margin, LI:margin, OL:margin and the top margin of P:margin.

Horizontal margins may be negative.

margin-top, margin-bottom

Value: <width>
Initial: 0
Level: 1
Example: margin-top = 2em

The vertical space between two blocks of text is the maximum of all bottom margin and top margin specifications between the two. For example, between `abc' and `def' in the fragment "</P></LI></OL><P>def..." the space is the maximum of the bottom margins of P:margin, LI:margin, OL:margin and the top margin of P:margin.

Vertical margins must be positive.


Value: <width> [ <width> [ <width> [ <width> ] ] ]
Initial: 0
Level: 1
Example: margin = 2em 1em

The four widths apply to top, right, bottom and left respectively. If there's only one, it applies to all sides, if there are two or three, the missing widths are taken from the opposite side.

The property is shorthand for setting "margin-top", "margin-right" "margin-bottom" and "margin-left" and separately.


Value: <length>
Initial: 0
Level: 1
Example: indent = 3em

This property is not inherited.

Extra indent to apply to the first line only. May be negative (`outdent'). Only applies if the element starts a paragraph (either because it implies a break itself, or because it happens to follow a break.) An indent is not inserted in the middle of an element that was broken by another (such as BR in HTML).


Value: <length> | auto
Initial: undefined
Level: 1
Example: width = {WIDTH}

This property can be applied to text, but it's most useful with inline images and similar insertions. The width is to be enforced by scaling the image if necessary.


Value: <length> | auto
Initial: undefined
Level: 1
Example: height = 50pt

Only applies to inline images and other insertions.

For images, the width is to be inforced by scaling the image if necessary.

Properties: level 2


[The box drawing properties seem to be complete, except that the effect of boxes is not clear in case of elements that are neither block-like nor inline (break before or break after, but not both)]

border-style (or box-style)

Value: none | normal | raised | lowered | beveled | etched | shadow
Initial: none
Level: 2
Example: border-style = normal

This property is not inherited. If UL has a border around it, you don't want each LI inside to inherit this border.

Additional possibilities include: single, double, thin-thick, thick-thin, dotted, wavy, baroque, filet, art-deco.

[Perhaps `border' should be changed to `box', because of the proposed box-background (see below) and because it's shorter. Disadvantage is that box-width sounds less natural. I believe both are equally accepted terms in the printing industry.]

border-width (or box-width)

Value: <width> [ <width> [ <width> [ <width> ] ] ]
Initial: medium
Level: 2
Example: border-width = thick thin

A width is either a length or one of the keywords `thin', `medium' or `thick'. The four widths apply to top, right, bottom and left respectively. If there's only one, it applies to all sides, if there are two or three, the missing widths are taken from the opposite side.

The box is drawn inside the space set by margin.*.

border-offset (or box-offset)

Value: <length> [ <length> [ <length> [ <length> ] ] ]
Initial: 0
Level: 2
Example: border-offset = 1em 3em

How much space to insert between the frame and the text. Again, the order is top, right, bottom, left.

border-color (or box-color)

Value: <color> | <uri>
Initial: inherited (init: appl. dep.)
Level: 2
Example: border-color = "";

URL must point to an image, which is tiled around the border.

Spacing and Margins

Margins set the space around an element. The background is transparent: whatever background ancestors have put there will shine through.


Value: block | blockbefore | blockafter | linebefore | lineafter | inline
Initial: inline
Level: 2
Example: break = block

[What should be default: `block' or `inline'? In Panorama, the default is block. Alternative keywords might be `both' for `block' and `none' for `inline'.]

"linebefore" and "lineafter" break the line but ignore margin-top and margin-bottom.


Value: <display-type> [ <string> ]
Initial: normal
Level: 2
Example: display = note map

How to display the content. The display-type can be:

Paged and scrolling media should interpret these as best they can, e.g., note could become a footnote.

The string after the keyword is a hint for the label of the button (if any). It follows the syntax of insert-before, so that "note map" causes an button to be inserted with the map entity from the WWW icons.


Value: <uri> | none
Initial: none
Level: 2
Example: replace = {SRC}

Replace the element with a rectangle that contains the document that the URL points to. Usually applied to inline images (IMG or FIG).




Value: <number>
Initial: 0
Level: 2
Example: H1: page-after = -2

Numbers can be from -2 to 2, meaning, respectively, no page break allowed, break discouraged, don't care, good breakpoint, forced break. All "page-before" and "page-after" values that apply between two elements are combined according to the following table:

	  |-2 -1  0  1  2
	-2|-2 -2 -2 -2  2
	-1|-2 -1 -1  1  2
	 0|-2 -1  0  1  2
	 1|-2  1  1  1  2
	 2| 2  2  2  2  2
In algorithmic terms: take the one with the largest absolute value; if they are the same, use the positive value.

page-inside ????

Value: <number>
Initial: 0
Level: 2
Example: PRE:page.inside=-1

Values can be -2, -1, or 0, meaning, respectively, keep on same page, page break discouraged, and don't care.

{Question: maybe this is not the best name for the property.]


[you can mess with the content, but not the HTML. Be critical!]



Value: <string>
Initial: ""
Level: 2
Example: insert.before = "title: "

Uses altfont. Note that the string can be an expression:

  insert.before = caution " class = " {CLASS} 1em

This is a concatenation of a symbol entity `caution', a string, an attribute value and 1em of whitespace.

The concatenation operator is implicit. Keywords in the expression can be either entity names (ISO character entities or WWW symbol entities), properties of type length (such as margin.left), or other properties. Entities are replaced by their symbol, lengths are replaced by that amount of horizontal whitespace, other properties are converted to a string. Sub-expressions of type length are evaluated and converted to that amount of whitespace.

Various non-sorted properties

List Numbering

 *: numbering = on | off
 *: number-style = arabic | lowerroman | upperroman | loweralpha | upperalpha
 *: number-inherit = on|off

[Needs some work, level 2 issue?]


[Level 2 issue]


[Level 2+ issue]



  percent (%)         -- relative to another length unit
  inches (in)
  pixels (px)
  centimeters (cm)
  millimeters (mm)
  ems (em)            -- the width of the character 'M'
  ens (en)            -- half the width of an em
  points (pt)
  characters (ch)     -- should be dropped in favor of ems?
  picas (pc)


A color is a either a color name, 3-tuple or a hex-color. A short list of supported color names should be added, e.g., black, white, red, green, blue, yellow, cyan, magenta, pink, brown, gray, orange, purple, turquoise, violet. Also, prefixing coler names with "light-" or "dark-" is allowed, e.g. "light-blue" and "dark-gray".

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: text-color = #F00
  EM: text-color = #FF0000
  EM: text-color = 255 0 0        -- integer range: 0-255
  EM: text-color = 1.0 0.0 0.0    -- float range: 0.0 - 1.0
  EM: text-color = red

Cascading order

Conflicts are intrinsic to the CSS mechanism. As long as a well-defined conflict resolution method is defined, conflicts enhance the mechanism and should not be avoided. For each style sheet assignment, a weight is computed based on four factors:

  1. source priority: implied by origin (reader or author), sometimes with explicit additions ("! important or "!legal ..")
  2. how specific the selector is: "P:" is more specific than "*:"
  3. linked and imported style sheets come with less weight
  4. some properties override other properties
The list is in descending order of weight. E.g., a more specific selector will be overridden by a less specific selector if the latter has a higher source priority.

Source priority

[asymmetry is introduced?]

Both readers and authors may use the style sheet language to specify preferences. A possible convention is that style sheets attached to the initial document become 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 technological handicaps may require the overriding of the author's hints. On the other side, authors may face legal requirements on the presentation, e.g. the font size. The priority of the different weights are as follows:
reader lensInteractive control, UA specific
author legalE.g.: font-size = 12pt ! "IATA requirement"
reader importantE.g.: font-size = 12pt ! important
author defaultdefault for incoming style
reader defaultdefault for reader's personal style
UA defaultsUAs should always have fallback values

The 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.


[Here, computer science clashes with usability. While the parser writer wants a unique syntax, usability increases with aliases. How important are shortcuts?]

The style sheet mechanism should be liberal in accepting alternative names, e.g. to shorten the length of a style specification. Also, people come to the web from different platforms and bring with them different vocabularies.

back  : background, bg 
fore  : foreground, fg
pt    : point, points
pa    : pica, picas


Formatting model

This document 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 can be specified in the style sheets:
  h1: margin 15pt 30pt 10pt 40pt  -- top, right, bottom, left
Vertically, all boxes are attached to the above box. Note that the above box doesn't necessarily contain the preceding HTML element. See the last example.

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

In the following examples, border-offset and border-width are assumed to be zero.

The first example 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,
 |   |!..   | |         
 |   |_____________________________| |
 |   |                             | |
 |   | (P margins)                 | |
 |   |                             | |
 |   |   | |
 |   |   | |
 |   |   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.list........    |  | |
 |   | |________________________|  | |
 |   | |                        |  | |
 |   | | (UL margins)           |  | |  <- second level UL element
 |   | |  __________________    |  | |
 |   | | |                  |   |  | |
 |   | | | (LI margins)     |   |  | |
 |   | | |                  |   |  | |
 |   | | |  Second.list...  |   |  | |
 |   | | |__________________|   |  | |
 |   | |________________________|  | |
 |   |_____________________________| |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |

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 achieved if sequential boxes don't end up on top of each other. In this way, "sideheads" and simple multiple-column layouts can be supported:

 |                                          |
 | (BODY margins)                           |
 |  ______________   _____________________  |
 | |              |;|                     | | 
 | | (H1 margins) |;| (P margins)         | |
 | |              |;|                     | |
 | | Headline...  |;| While.the.paragraph | | 
 | |  |;| | |
 | |______________|;| continues.below.the | |
 | ;;;;;;;;;;;;;;;;;| | |
 | ;;;;;;;;;;;;;;;;;|_____________________| |
 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |

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

Formal grammar

This is a grammar for the Cascading Style Sheets. It consists of two parts: a context free grammar suitable for a LL(1) parser, and a lexical analyzer in Lex format.

The CFG uses brackets ([]) for grouping, a postfix asterisk (*) to mean zero or more, a postfix plus (+) for one or more, a postfix question mark (?) for zero or one, and a vertical bar (|) for separating alternatives.

Context Free Grammar

A style sheet starts with zero or more references to imported style sheets, followed by optional declarations, followed by the style rules themselves.

EOL* imports decls rules;
[ IMPORT url EOL+ ]*;

There are two kinds of declarations: constants and architectural forms. Constant declarations define symbolic constants for use in the right hand side of properties. An architectural form defines which attribute to use as the architectural form, by default this is `CLASS'. Although the syntax allows multiple architectural form declarations, what happens when there is more than one is application dependent.

The `value' in the rhs of a constant declaration follows the same syntax as the value in property specifications (defined below), but it has a restriction in that it must be evaluated context independently, which means in practice that it cannot refer to attributes or values of properties.

[ constant_decl | archform_decl ]*;
DEFINE unique_id '=' value EOL+;
ARCHFORM attrname EOL+;

The style rules may be divided into sections for different media. The first part refers to all media, after a medium specification, the rules apply only to output on that medium. A medium is something like `[speech]', `[hicolor]' `[monochrome]', etc.

rule* section*;
'[' medium ']' EOL+ rule*;

A style rule consists of one or more selectors, a colon, one or more properties, and an optional priority.

address [ ',' address ]* ':' property [ ',' property ]* priority?;
toplevel | context? elemspec;

An address, if not *, consists of a element name (GI and/or class), optionally followed by attribute specification and optionally preceded by a context.

A context is best viewed from right to left. It can consist of the element's immediate predecessor (elder sibling), and any number of ancestors, each of which can also be prefixed with its immediate predecessor. Ancestors are enclosed in parentheses (), predecessors in slashes //. Predecessors can only be indicated by their GI or class, ancestors can be further qualified by attributes.

predecessor [ ancestor ancestor* context ]?;
'(' elemspec ')';
'/' elemname '/';
IDENT [ '.' IDENT ]?;
elemname attrspec*;
'{' attrname [ '=' constval ]? '}';
signed_val | STRING | HEXCOLOR | IDENT;
[ '+' | '-' ]? [ length | NUMBER ];

A priority consists of an exclamation mark, a keyword, and an optional string. The keyword is redundant, since the presence of the exclamation mark plus the fact if the rule came from a local style sheet or a remote one, completely determines the priority. The optional string is displayed to the user as a warning when the formatter is ignoring the rule for some reason.

'!' priotype STRING?;

A property consists of a name and a value, where the value is actually an expression. Note that the operator between terms can be empty. The empty operator creates a list.

Unfortunately, there is an ambiguity because of this: 7+8 could mean (7) (+8) or (7+8). The parser should use the latter.

propname [ '=' value | op_eq value ];
monadic? term [ op monadic? term ]*;
length | STRING | HEXCOLOR | NUMBER | IDENT | attref | propref | envvar | '(' value ')';
'{' attname '}';
'$' IDENT;
'+' | '-';
'+' | '-' | '*' | '/' | = INTERPOLATELO | INTERPOLATEHI | /* empty */;

Lexical scanner

The terminals of the grammar above are defined with the following Lex specification.

  nmstrt    [a-zA-Z]
  nmchar    [a-zA-Z0-9.-]
  ident     {nmstrt}{nmchar}*
  d         [0-9]
  number    {d}+|{d}*\.{d}+
  h         [0-9a-fA-F]
  hexcolor  #{h}{h}{h}|#{h}{h}{h}{h}{h}{h}
  w         [ \t]*


  "\n"              return EOL;
  <<EOF>>           return EOL;
  "@import"         return IMPORT;
  \"([^"]|\\\")*\"  |
  \'([^']|\\\')*\'  return STRING;
  "@define"         return DEFINE;
  {ident}           {yylval.string = yytext; return IDENT;}
  "@archform"       return ARCHFORM;
  {hexcolor}        {yylval.string = yytext; return HEXCOLOR;}
  {number}          {yylval.number = atof(yytext); return NUMBER;}
  {number}"%"       {yylval.number = atof(yytext)/100; return NUMBER;}
  {number}{w}in     |
  {number}{w}inch   {yylval.number = atof(yytext)*INCH; return LENGTH;}
  {number}{w}cm     {yylval.number = atof(yytext)*CM; return LENGTH;}
  {number}{w}mm     {yylval.number = atof(yytext)*MM; return LENGTH;}
  {number}{w}pica   |
  {number}{w}pc     {yylval.number = atof(yytext)*PICA; return LENGTH;}
  {number}{w}pt     {yylval.number = atof(yytext)*POINT; return LENGTH;}
  {number}{w}px     {yylval.number = atof(yytext)*pixel; return LENGTH;}
  {number}{w}ch     {yylval.number = atof(yytext); return NCHARS;}
  {number}{w}em     {yylval.number = atof(yytext); return EMS;}
  "<<"              return INTERPOLATELO;
  ">>"              return INTERPOLATEHI;
  "+="              return PLUS_EQ;
  "-="              return MINUS_EQ;
  "*="              return STAR_EQ;
  "/="              return SLASH_EQ;
[synchornize terminology (rule, term, assignment, hint etc) throughout the document]


ISO 8879. Information Processing - Text and Office Systems - Standard Generalized Markup Language (SGML), 1986.


During the short life of HTML, there have been several style sheet proposals to which this proposal is indebted. The following people's proposals have been very influential:

Through and other electronic media, these people have actively contributed: Also, thanks to Tim Berners-Lee, Vincent Quit, C. Roisin, I. Vatton, Phill Hallam-Baker and Terry Allen for constructive discussions.