W3C: Cascading Style Sheets, level 1

W3C Working Draft 22-Dec-95

URL: http://www.w3.org/pub/WWW/TR/WD-css1-951222.html

Håkon W Lie (howcome@w3.org)
Bert Bos (bert@w3.org)

Status of this document

This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than "work in progress". A list of current W3C tech reports can be found at: http://www.w3.org/pub/WWW/TR/

Note: since working drafts are subject to frequent change, you are advised to reference the above URL, rather than the URLs for working drafts themselves.


Content

Abstract

This document specifies level 1 of the Cascading Style Sheet mechanism (CSS1). CSS1 is a simple style sheet mechanism that allows authors and readers to attach style (e.g. fonts, colors and spacing) to HTML documents. The CSS1 language is human readable and writable, and expresses style in common desktop publishing terminology.

One of the fundamental features of CSS is that style sheets cascade; authors can attach a preferred style sheet, while the reader may have a personal style sheet to adjust for human or technological handicaps. The rules for resolving conflicts between different style sheets are defined in this specification.

We encourage programmers and authors to start experimenting with style sheets. Comments can be sent to the www-style@w3.org mailing list, or directly to the authors. For background material, see the resource page on web style sheets [1].

Terminology

author
the author of a document
canvas
the part of the UA's drawing surface onto which documents are rendered
CSS
Cascading Style Sheets
CSS1
Cascading Style Sheets, level 1. This document defines CSS1.
CSS2
Cascading Style Sheets, level 2. Ongoing work defines CSS2 which will be published in 1996.
declaration
a property (e.g. 'font-size') and a corresponding value (e.g. '12pt')
designer
the designer of a style sheet
document
HTML document
element
HTML element
HTML
Hypertext Markup Language, an application of SGML. CSS1 is targeted to HTML, while CSS2 will be SGML-generic.
HTTP
Hypertext Transfer Protocol
property
a stylistic parameter that can be influenced through CSS. This specification defines a list of properties and their corresponding values.
reader
the person for whom the document is rendered
rule
a declaration (e.g 'font-family: helvetica') and its selector (e.g. 'H1')
selector
a string that identifies what elements the corresponding rule applies to. A selector can be based on the name of the element, existance and values of element attributes, and the context of the element.
SGML
Standard Generalized Markup Language, of which HTML is an application
style sheet
a collection of rules
tag
HTML tag, e.g. 'H1'.
UA
User Agent, often a "web browser" or "web client"
user
synonymous with "reader"
weight
the priority of a declaration

Basic concepts

Designing simple style sheets is easy. One only needs to know a little HTML and some basic desktop publishing terminology. E.g., to set the text color of 'H1' elements to blue, one can say:

  H1 { color: blue }
The example consists of two main parts: selector ('H1') and declaration ('color: blue'). The declaration has two parts, property ('color') and value ('blue'). While the example above only tries to influence one of the properties needed for rendering an HTML document, it qualifies as a style sheet on its own. Combined with other style sheets (one of the fundamental features of CSS is that style sheets are combined) it will determine the final presentation of the document.

The selector is the link between the HTML document and the style, and all HTML tags are possible selectors. HTML tags are defined in the HTML specifications, and the CSS1 specification only defines a syntax for how to address them.

The 'color' property is one of around 40 properties that determine the presentation. The list of properties and values is defined in this specification.

CSS1 is targeted for HTML documents. HTML is an application of SGML and CSS level 2, which is being defined, will be general to SGML.

Containment in HTML

In order for the style sheets to influence the presentation, the user agent (UA, often a "web browser" or "web client") must be aware of their existence. Another W3C working draft, "HTML3 and Style Sheets" [3], describes how to link HTML with style sheets:

<HTML>
  <HEAD>
    <TITLE>title</TITLE>
    <LINK REL=STYLESHEET TYPE="text/css" HREF="http://style.com/cool">
    <STYLE TYPE="text/css">
      @import "http://style.com/basic"
      H1 { color: red }
    </STYLE>
  </HEAD>
  <BODY>
    <H1>Headline is red</H1>
    <P STYLE="color: blue">While the paragraph is blue.
  </BODY>
</HTML>
The example shows four ways to link style to HTML: using the 'LINK' element to link an external style sheet, a 'STYLE' element inside the 'HEAD' element, an imported style sheet using the CSS notation, and a 'STYLE' attribute on the element itself. The latter option mixes style with content and one loses the corresponding advantages of traditional style sheets.

The 'LINK' element references alternative style sheets that the reader can select, while imported style sheets are automatically merged with the rest of the style sheet.

Grouping

To reduce the size of style sheets, one can group selectors in comma-separated lists:
  H1, H2, H3 { font-family: helvetica }
Similarly, declarations can be grouped:
  H1 { 
       font-size: 12pt;
       line-height: 14pt; 

       font-family: helvetica; 
       font-weight: bold; 
       font-style: normal
     }
In addition, some properties have their own grouping syntax:
  H1 { font: 12pt/14pt helvetica bold }
which is equivalent to the previous example.

Inheritance

In the first example, the color of 'H1' elements was set to blue. Suppose we have an '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 parent element, i.e. it will also appear in blue. Other style properties are likewise inherited, e.g. 'font-family' and 'font-size'.

Inheritance starts at the oldest ancestor, i.e. the top-level element. In HTML, this is is the 'HTML' element. In order to set a "default" style property, one should use 'HTML' as selector:

  HTML { color: dark-blue }

This will work even if the author has omitted the 'HTML' tag (which is legal) since the parser will infer missing tags.

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., the 'background' property does not inherit, but the parent element's background will shine through by default.

Often, the value of a property is a percentage that refers to another property:

  P { font-size: 10pt }
  P { line-height: 120% }  /* relative to font-size, i.e. 12pt */

Children elements of 'P' will inherit the computed value of 'line-height' (i.e. 12pt), not the percentage.

Note that special rules apply to tables.

Class as selector

To increase the granularity of control over elements, HTML3 proposes a new attribute: 'CLASS'. All elements inside the 'BODY' element can be classed, and the class can be addressed in the style sheet:
<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE TYPE="text/css">
    H1.punk { color: #00FF00 }
  </STYLE>
 </HEAD>
 <BODY>
  <H1 CLASS=punk>Way too green</H1>
 </BODY>
</HTML>

The normal inheritance rules apply to classed elements; they inherit values from their ancestors in the logical tree.

One can address all elements of the same class by omitting the tag name in the selector:

  .punk { color: green }  /* all elements with CLASS green */
Only one class can be specified per selector. 'P.punk.rap' is therefore an invalid selector in CSS1.

ID as selector

HTML3 also introduces the 'ID' attribute which is guaranteed to have a unique value over the document. It can therefore be of special importance as a style sheet selector:
  #z098y { letter-spacing: 0.3em }

  <P ID=z098y>Wide text</P>

Context sensitivity

Inheritance saves CSS designers typing. Instead of setting all style properties, one can create defaults and then list the exceptions. To give 'EM' elements within 'H1' a different color, one may specify:

  H1 { color: blue }
  EM { color: red }
When this style sheet is in effect, all emphasized sections, within or outside 'H1' will turn red. Probably, one only wanted 'EM' elements within 'H1' to turn red. This can be specified with:
  H1 EM { color: red }
The selector is now a search pattern on the stack of open elements. Only the last element of the search pattern is addressed (in this case the 'EM' element), and only so if the search pattern matches. CSS1 seach patterns look for ancestor relationships. In the example above, the search pattern matches if 'EM' is a descendant of 'H1', i.e. if 'EM' is inside an 'H1' element.
  UL UL LI    { font-size: small }    
  UL UL UL LI { font-size: x-small }
Here, the first selector matches 'LI' elements with at least two 'UL' ancestors. The second selector matches a subset of the first matches, i.e. 'LI' elements with at least three 'UL' ancestors. The conflict is resolved by the second selector being more specific due to the longer search pattern. See the cascading order for more on this.

Search patterns can look for tags, classes or ids:

  P.reddish .punk  { color: red }
  #x78y CODE       { background: blue }

This first selector matches all elements with class 'punk' that have an ancestor of element 'P' with class 'reddish'. The second selector matches all 'CODE' elements that are decendants of the element with 'ID=x78y'.

Pseudo-classes (which are introduced in the next section) are only allowed in the last part of the selector:

  BODY P:first-letter { color: purple }
Several search patterns can be grouped together:
  H1 B, H2 B, H1 EM, H2 EM { color: red }
Which is equivalent to:
  H1 B { color: red }
  H2 B { color: red }
  H1 EM { color: red }
  H2 EM { color: red }

Comments

Textual comments in a CSS style sheet are similar to those in the C programming language:

  /* style sheet designer: robot@style.com */
  EM { color: red }  /* red, really red!! */
Comments cannot be nested. Designers are encouraged to sign their work.

Addressing the canvas

To address the canvas (e.g. the window or sheet of paper), one should set properties on the element which has the 'width' and 'height' properties set to 'from-canvas'. In HTML the 'BODY' element is given this role.
  BODY { width: from-canvas; height: from-canvas }  /* default setting */
  BODY { background: blue/red }
The above example describes a background which is blue at the top of the canvas and fades into red at the bottom.

Pseudo-classes

In CSS1, style is normally determined by an element's logical position in the document and/or its attributes. This simple model is sufficient for a wide variety of styles, but doesn't cover some common effects. The concept of pseudo-classes extends addressing in CSS1 to allow external information to influence the formatting process.

Anchor pseudo-classes

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. In CSS1, this is handled through anchor pseudo-classes:
  A:link { color: red }       /* unvisited link */
  A:visited { color: blue }   /* visited links */
  A:active { color: orange }  /* active links */
'A' elements are always in one and only one of these three pseudo-classes.

Typographical pseudo-classes

Some common typographic effects are associated not with logical elements but rather typographical items as formatted on the canvas. In CSS1 one can address two such typographical items through pseudo-classes: the first letter of an element, and the first line. An example:
  P { color: black; font-size: 12pt }
  P:first-letter { color: green; font-size: 200% }
  P:first-line { color: blue; text-transform: uppercase }
In this example, the first letter of each 'P' element would be green with a font size of 24pt. The rest of the first line (as formatted on the canvas) would be uppercase blue text.

The UA defines what characters to apply 'first-letter' properties to, e.g. if preceding punctuation is to be included, or what characters are to be defined as letters.

Since the first letter also is a part of the first line, 'first-line' properties will apply to the first letter unless the same property is set for the 'first-letter' pseudo-class.

Pseudo-classes vs. normal classes

Pseudo-classes behave similar to normal classes. The differences are:

Also, while normal classes inherit down the logical tree, children elements within pseudo-classes inherit from the visual context. This point needs clarification. While the property values themselves never inherit, the affected typographical elements may end up inside a child element:

<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE TYPE="text/css">
   P              { font-size: 12pt }
   P:first-letter { font-size: 200%; vertical-align: -100% }
   EM             { text-transform: uppercase }
  </STYLE
 </HEAD>
 <BODY>
  <P><EM>The first</EM> few words of an article in The Economist..
 </BODY>
</HTML>
If an ASCII-based UA supports these properties (we do not expect them to), the above could be formatted as:
  ___
   | HE FIRST few words
   |of an article in the
  Economist..
The initial letter of the 'P' element ('T') is inside a child element ('EM'). In this case, the first 'T' will be formatted based on:
  1. the properties set on the 'first-letter' pseudo-class
  2. other properties will be taken from the HTML element of the letter (i.e. the 'EM' element in the example above)

Pseudo-classes can be combined with normal classes in selectors:

  P.first-para:first-letter { color: red }

  <P CLASS=initial>First paragraph</A>

The above example would set the color of the initial letter of all 'P' elements with 'CLASS=initial'.

The cascade

In CSS, more than one style sheet can influence the presentation simultaneously. There are two main reasons for this feature: modularity and author/reader balance.

A style sheet designer can combine several (incomplete) style sheets to reduce redundancy:

  @import "http://www.style.org/punk"
  @import "http://www.style.org/funk"

  H1 { color: red }     /* override imported sheets */
Both readers and authors can influence the presentation through style sheets. To do so, they use the same style sheet language thus reflecting a fundamental feature of the web: everyone can become a publisher. The UA is free to chose the mechanism for referencing personal style sheets.

Sometimes conflicts will arise between the style sheets that influence the presentation. Conflict resolution is based on each style declaration having a weight. By default, the weights of the reader's declarations are less than the weights of declarations in incoming documents. I.e., if there are conflicts between the style sheets of an incoming document and the reader's personal sheets, the incoming declarations will be used.

'important' and 'legal'

Style sheet designers can increase the weights of their declarations:

  H1 { color: red ! important }
  P  { font-size: 12pt ! legal "IATA regulations" }
The '! legal ..' construct is used if there are legal reasons behind the declaration, and the trailing string is a short reference to the corresponding statutes. 'Important' and 'legal' declarations have the same weight.

An important (or legal) reader declaration will override an incoming declaration with normal weight. An important (or legal) incoming declaration will override an important (or legal) reader declaration. Users should be notified when a style sheet is in effect, and be allowed to turn style sheets on and off.

The reference to the statutes should be displayed to the reader as a warning when the UA is not able to honor a legal declaration. The reader should acknowledge the warning with an action, e.g. a mouse click. Situations where the warning should be displayed include:

In some cases, it is clear from the context that the declaration cannot be honored and there is no need to warn the reader: One should also keep in mind that the UA may not be able to retrieve externally linked style sheets.

Cascading order

Conflicting rules are intrinsic to the CSS mechanism. To find the value for an element/property combination, the following rules should be followed in the order given:

  1. Find all declarations that apply to the element/property in question. If no declarations apply, the inherited value is used.
  2. Sort the declarations by explicit weight: declarations marked '!important' or '!legal ..' are carry more weight than unmarked (normal) declarations.
  3. Sort by origin: incoming style sheets override the reader's style sheet.
  4. Sort by specificity of selector: more specific selectors will override more general ones. To find the specificity, count the number of ID attributes in the selector (a), the number of CLASS attributes in the selector (b), and the number of tag names in the selector (c). Concatinating the three numbers (in a number system with a large base) gives the specificity. Some examples:
      LI            {..}  /* a=0 b=0 c=1 -> specificity =   1 */
      UL LI         {..}  /* a=0 b=0 c=2 -> specificity =   2 */
      UL OL LI      {..}  /* a=0 b=0 c=3 -> specificity =   3 */
      LI.red        {..}  /* a=0 b=1 c=1 -> specificity =  11 */
      UL OL LI.red  {..}  /* a=0 b=1 c=3 -> specificity =  13 */ 
      "x34y"        {..}  /* a=1 b=0 c=0 -> specificity = 100 */ 
    
  5. Resolve conflicts between properties: more specific properties (e.g. 'font-size') will override compound properties (e.g. 'font').
  6. Sort by order specified: if two rules have the same weight, the latter specified should live.

The search for the property value can be terminated whenever one rule has a higher weight than the other rules who apply to the same element/property combination.

This strategy gives incoming style sheets considerably higher weight than those of the reader. It is therefore important that the reader has the ability to turn off the influence of a certain style sheet, e.g. through a pull-down menu.

Note that special rules apply to tables.

Formatting model

This document suggests a simple box-oriented formatting model. Each block-level element (e.g. 'H1' and 'P', but not 'EM') is surrounded by a box. The size of the box is the sum of the element width (i.e. formatted text or image), the padding, the border and the margins:
    _______________________________________
   |                                       |
   |           margin (transparent)        |
   |   _________________________________   |
   |  |                                 |  |
   |  |        border                   |  |
   |  |   ___________________________   |  |
   |  |  |                           |  |  |
   |  |  |     padding               |  |  |
   |  |  |   _____________________   |  |  |
   |  |  |  |                     |  |  |  |
   |  |  |  |  content            |  |  |  |
   |  |  |  |_____________________|  |  |  |
   |  |  |___________________________|  |  |
   |  |_________________________________|  |
   |_______________________________________|

            |    element width    |

   |               box width               |

The background of the content and padding area is controlled with the 'background' property. The color and style of the border is controlled with the 'border-color' and 'border-style' properties. If the border needs a background, the 'background' property is used. Margins are transparent, so the parent element will shine throught. The width of the margins specify the minimum distance to the edges of surrounding boxes.

The following example shows how margins and padding format a 'UL' element with two children. To simplify the diagram there are no borders.

    <STYLE TYPE="text/css">
      UL { 
           background: red; 
           margin: A B C D;      /* let's pretend we have constants in CSS1 */
           padding: E F G H;     /*                   "                     */
         }
      LI { 
           background: blue; 
           color: white;         /* so text is white on blue */
           margin: a b c d;      /* let's pretend we have constants in CSS1 */
           padding: e f g h;     /*                   "                     */
         }
    </STYLE>
    ..
    <UL>
      <LI>1st element of list
      <LI>2nd element of list
    </UL>
    ________________________________________________________
   |                                                        |
   |     A      UL margin (transparent)                     |
   |     _______________________________________________    |
   |  D |                                               | B |
   |    |    E   UL padding (red)                       |   |
   |    |    _______________________________________    |   |
   |    | H |                                       | F |   |
   |    |   |    a   LI margin (transparent,        |   |   |
   |    |   |        so red shines through)         |   |   |
   |    |   |    _______________________________    |   |   |
   |    |   | d |                               | b |   |   |
   |    |   |   |    e    LI padding (blue)     |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   | h  1st element of list      f |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   |    g                          |   |   |   |
   |    |   |   |_______________________________|   |   |   |
   |    |   |                                       |   |   |
   |    |   |     max(a, c)                         |   |   |
   |    |   |                                       |   |   |
   |    |   |    _______________________________    |   |   |
   |    |   |   |                               |   |   |   |
   |    |   | d |    e    LI padding (blue)     |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   | h  2nd element of list      f |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   |    g                          |   |   |   |
   |    |   |   |_______________________________|   |   |   |
   |    |   |                                       |   |   |
   |    |   |   c    LI margin (transparent,        |   |   |
   |    |   |        so red shines through)         |   |   |
   |    |   |_______________________________________|   |   |
   |    |                                               |   |
   |    |    G                                          |   |
   |    |_______________________________________________|   |
   |                                                        |
   |    C                                                   |
   |________________________________________________________|

Technically, padding and margin properties are not inherited. But, as the example shows, the placement of a rendered element is relative to ancestors and siblings.

If 'border-width' had been set (the default value is '0'), the border would have appeared between the padding and the margins.

Lists

Unless 'list-style' is set to 'none', list elements will be preceded by a label. The label is not considered to be a part of the content, and will be placed to the left of the content. The label should use the font and color properties of the list element to which it belongs.

Vertical formatting

Horizontally, boxes inherit the width of the parent element. Vertically, boxes by default are packed to attach to the box above (with margins overlapping). Note that the box above doesn't necessarily contain the preceding HTML element, and 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, border & padding)              |
 |  ______________        _____________________  |
 | |              |      |                     | | 
 | | (H1 box)     |      | (P box)             | |
 | |              |      |                     | |
 | | Headline...  |      | While.the.paragraph | | 
 | | comes.here.  |      | starts.here.and.... | |
 | |______________|      | continues.below.the | |
 |                       | box.to.the.left.... | |
 |  ______________       |_____________________| |
 | |              |      |                     | | 
 | | (H2 box)     |      | (P box)             | |
 | |              |      |                     | |
 | | Don't.move.  |      | The.2nd.paragraph.. | | 
 | | this.one.up  |      | behaves.like.the... | |
 | |______________|      | first.one,.it.moves | |
 |                       | up................. | |
 |                       |_____________________| |
 |_______________________________________________|
                                               
   ^              ^      ^                     ^
   0%            35%    50%                   100%    
The above could be realized through:
  H1, H2 { 
       margin-left: 0%; 
       margin-right: 65%   /* (100% minus 35%) */
       pack: loose;
     }
  P  {
       margin-left: 50%; 
       margin-right: 0%
     }

For the headline elements, the 'pack' property is set to 'loose' to avoid having them move up next to preceding elements.

The percentages are relative to the width of the parent element.

Horizontal formatting

Five length units influence the horizontal dimension of a box: left margin, left padding, width, right padding, right margin. Added up, these have to be equal to the width of the parent element. Therefore, one cannot specify values for all properties and expect them to be honored. The relative strengths between them are as follows:
  1. left padding
  2. right padding
  3. width
  4. left margin
  5. right margin
By default, the value of the 'width' property is 'auto' which means it will be automatically calculated based on the other properties' values. However, if 'width' is assigned another value, or the dimensions don't add up for other reasons, the property with the lowest rank will be assigned 'auto', i.e. automaticlly calculated.

CSS1 conformance

A UA conforms to the CSS1 specification if it:

CSS1 properties

Style sheets influence the presentation of documents by assigning values to style properties. This section lists the defined style properties, and their corresponding units, of CSS1.

Each element in the document can in priciple have a value assigned to every property. Moste oftenIn that case, the style sheet would be much bigger that the

The list of CSS1 properties has been kept to a minimum, while making sure commonly used styles can be expressed. Depending on the formatting model and the presentation medium, some properties can prove hard to incorporate into existing UA implementations (e.g. 'text-effect' and 'flow'). According to the conformance rules, UAs should make efforts to format documents according to the style sheets, but support for all properties cannot be expected. E.g., an ASCII-based browser is not able to honor accurate margins, but should approximate.

fobar

Fonts

Setting font properties will be among the most common uses of style sheets. Unfortunately, there exists no well-defined and widely accepted 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 (whose slanted fonts are called 'oblique').

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

font-size

Value: <length> | <percentage> | <number> | xx-small | x-small | small | medium | large | x-large | xx-large
Initial: medium
Applies to: all elements
Example: font-size: 12pt

If the value is a number, it is interpreted relative to the parent elements's font size. A scaling factor of 1.4 is suggested for a value of 1 (but this could vary depending on the medium and the conts available). E.g, if 'font-size' is set to '-1', the font size should be the parent element's font size multiplied with (-1/1.4).

A percentage value is relative to the parent element's font size.

A keyword value is an index to an absolute table kept by the UA. A scaling factor of 1.44 is suggested between adjacent indexes, e.g. if the 'medium' font is 10pt, the 'large' font could be 14.4pt (or 14pt, which may be more easily available).

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.

font-family

Value: [ <family-name> | <generic-family> ]+
Initial: UA specific
Applies to: all elements
Example: font-family: new-century-schoolbook serif

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.

In level 1, the following generic families are defined:

Style sheet writers are encouraged to offer a generic font family at the end of the list:

  font-family: univers helvetica sans-serif
Ideally, the style sheet writer should specify only one font, and the font manager should return the best alternative (perhaps by taking visual similarity, visual quality and performance into account). Unfortunately, current rendering environments do not offer this level of service, and it is beyond the style sheet mechanism to do so. Therefore, a prioritized list of alternative families can be supplied. This practice poses one problem: the UA must be able to determine if a font selection has been successful or not to know how far it should proceed in the list. One example: if the style sheet asks for 'univers' and the window system is smart enough to suggest 'helvetica' (which looks almost identical) as a replacement, is this a success or failure? This specification leaves the answer undefined for now.

font-weight

Value: extra-light | light | demi-light | medium | demi-bold | bold | extra-bold | <number>
Initial: medium
Applies to: all elements
Example: font-weight: demi-bold

If the value is a number, is is interpreted relative to the parent element's weight. A value of '1' suggests two jumps in the table corresponding to the keywords. E.g., if the parent's font weight is 'medium', a value of '-1' will make the element's font weight 'light'. Non-integer font weights are allowed.

If the desired font weight is not available, the UA selects a substitution order.

font-style

Value: [ normal | italic | oblique | small-caps ] +
Initial: normal
Applies to: all elements
Example: font-style: small-caps italic

If the preferred font style cannot be accomplished, the UA should make best efforts to find acceptable substitutions. Often, an 'oblique' font can be substituted by an 'italic' font. If 'small-caps' are not available, capital letters of a smaller font size can be used to render small characters if the resolution of the output medium is appropriate for this.

line-height

Value: <length> | <percentage>
Initial: UA specific
Applies to: all elements
Example: line-height: 120%

The property refers to the distance between to adjacent lines' baselines. A percentage value refers to the 'font-size' of the element itself. E.g.:

  P { line-height: 120%; font-size: 10pt }
Here, the 'line-height' would be 12pt.

If there is more than one element on a formatted line, the maximum 'line-height' will apply. One should therefore be careful when setting 'line-height' on inline elements.

Negative values are not allowed.

font

Value: font-size [ / line-height ] font-family [ font-weight ] [ font-style ]
Initial: not defined
Applies to: all elements
Example: font: 12pt/14pt helvetica bold

This is a traditional typographic shorthand notation to set font-size, line-height, font-family, font-style, and font-weight. Setting the properties individually override the shorthand notation if the weight is otherwise the same.

Omitted property values are set to their initial value.

Color and background

color

Value: <color>
Initial: UA specific
Applies to: all elements
Example: color: rgb 1.0 0 0

See the section on units for a description of possible color values.

background

Value: [ <color> | <uri> | transparent ]+ [ / [ <color> | <uri> | transparent ]+ ]
Initial: transparent
Applies to: all elements
Example: background: "http://www.pat.com/pats/silk.gif" blue

This property does not inherit, but unless explicitly set, the parent element's background will shine through due to the initial transparent value.

If an image is found through the URI, it takes precedence over color. The color is used:

Using the delimiting '/', two different backgrounds can be described ('bg1' and 'bg2' respectively). The resulting background is a fade between the two. The 'bg-blend-direction' property specifies the direction of the blending.

bg-blend-direction

Value: N | NW | W | SW | S | SE | E | NE
Initial: S
Applies to: all elements
Example: BODY { bg-blend-direction: NW }

This property is used to blend two background colors. It specifies the direction where 'bg2' is the background color at the edge or corner of the canvas. 'bg1' is the background color at the opposite edge or corner.

The values are shorthands for north, north-west, west etc where 'N' is the top of the canvas.

The initial value is 'S', so if 'bg1' is 'dark-blue' and 'bg2' is 'light-blue', the canvas will be 'dark-blue' at the top, smoothly blending through mid blue to 'light-blue' at the bottom.

Specifying 'bg-blend-direction': 'NW' would give 'light-blue' in the top-left corner smoothly blending through mid blue to 'dark-blue' in the bottom right corner.

If only one background color is specified, the blend direction is ignored.

bg-style

Value: [ repeat | repeat-x | repeat-y | no-repeat | scroll | fixed ] +
Initial: repeat scroll
Applies to: all elements
Example: bg-style: repeat-x scroll

This property describes how the background image should be laid out. By default, the background image is repeated in both x and y direction, and the image is scrolled along with the other content. A 'fixed' background is fixed with regard to the canvas.

bg-position

Value: <percentage> [ <percentage> ]
Initial: 0% 0%
Applies to: all elements
Example: bg-position: 50% 30%

The property describes the initial position of a background image specified with the 'background' property. If only one value is given, it sets both the horizontal and vertical offset of the background image. If two values are given, the horizontal position comes first.

With a value pair of '0% 0%', the upper left corner of the image is placed in the upper left corner of the element. A value pair of '100% 100%' places the lower right corner of the image in the lower right corner of the element.

To address the canvas, these properties should be set on the 'BODY' element.

Text

word-spacing

Value: normal | <length>
Initial: normal
Applies to: all elements
Example: word-spacing: 1em

The length unit indicates an addition to the default space between words. Values can be negative. The UA is free to select the exact spacing algorithm.

letter-spacing

Value: normal | <length>
Initial: normal
Applies to: all elements
Example: letter-spacing: 1em

The length unit indicates an addition to the default space between characters. Values can be negative. The UA is free to select the exact spacing algorithm.

text-decoration

Value: [ none | underline | overline | line-through | box | blink ] +
Initial: none
Applies to: all elements
Example: text-decoration: underline

Formatters should treat unknown values as 'box' (a simple rectangle).

The color of the decoration is the same as the color of the text.

vertical-align

Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage>
Initial: baseline
Applies to: all elements
Example: C.subscript { vertical-align: sub }

The property affects the vertical positioning of the element. One set of keywords are relative to the parent element:

'baseline'
align along the baseline
'middle'
align the middle of the element with the baseline of the parent element plus half the x-height of the parent element.
'sub'
subscript the element
'super'
superscript the element
'text-top'
align with the top of the parent element's font
'text-bottom'
align with the bottom of the parent element's font
Another set of properties are relative to the formatted line that the element is a part of:
'top'
align with the tallest element on the line
'bottom'
align with the lowest element on the line

Using the 'top' and 'bottom' alignment, unsolvable situations can occur where element dependancies form a loop.

Percentage values refer to the 'line-height' of the element itself. E.g., a value of '-100%' will lower the element to where the baseline of the next line should have been. This is especially useful when placing dropdown initials.

text-transform

Value: capitalize | uppercase | lowercase | none
Initial: none
Applies to: block-level elements
Example: text-transform: uppercase
'capitalize'
uppercases the first character of each word
'uppercase'
uppercases all letters of the element
'lowercase'
lowercases all letters of the element
'none'
neutralizes inherited value.

text-align

Value: left | right | center | justify
Initial: UA specific
Applies to: block-level elements
Example: text-align: center

This property describes how text is aligned within the element.

text-indent

Value: <length> | <percentage>
Initial: 0
Applies to: block-level elements
Example: text-indent: 3em

The property specifies indent that only applies to the first formatted line. 'text-indent' may be negative. An indent is not inserted in the middle of an element that was broken by another (such as 'BR' in HTML).

Percentage values are relative to the width of the parent element.

This property is not inherited.

Layout

See the formatting model for examples on how to use these properties.

padding

Value: <length> | <percentage> | auto (up to four values)
Initial: 0
Applies to: block-level and replaced elements
Example: padding: 20% 20%

The propery describes how much space to insert between the border and the content (e.g. text or image). The order is top, right, bottom, left. If there is only one value, it applies to all sides, if there are two or three, the missing values are taken from the opposite side.

The color of the padding area is controlled with the 'background' property. See the formatting model for more on these properties.

Padding values are >= 0.

margin-left, margin-right
margin-top, margin-bottom
margin

Value: <length> | <percentage> | auto (up to 4 values)
Initial: 0
Applies to: block-level and replaced elements
Example: margin: 2em 1em

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

The margins express the minimal distance between the borders of two adjacent elements. See the formatting model for an example.

Percentage values are relative to the width of the parent element.

Vertical margins must be >=0, horizontal margins may be negative.

The 'margin' property is shorthand for setting 'margin-top', 'margin-right' 'margin-bottom' and 'margin-left' separately. The individual declarations take precedence if the weights are otherwise the same.

display

Value: block | inline | none
Initial: according to HTML
Applies to: all elements
Example: P { display: block }

This property indicates if an element is block-level (e.g. H1 in HTML) or inline (e.g. EM in HTML). For HTML documents, the initial value will be taken from the HTML specification.

A value of 'none' turns the display of the element (including the surrounding box) off.

width

Value: <length> | <percentage> | auto | from-canvas
Initial: auto
Applies to: block-level and replaced elements
Example: IMG { width: 100pt }

This property can be applied to text, but it is most useful with inline images and similar insertions. The width is to be enforced by scaling the image if necessary. When scaling, the aspect ratio of the image should be preserved if the 'height' property is 'auto'.

Percentage values are relative to the width of the parent element.

See the formatting model for a description of the relationship between this property and the margin and padding.

The 'from-canvas' value means that the width of the element is such that the width and the margin add up to the width of the canvas. In HTML, 'BODY' has this value to allow properties on 'BODY' to use the canvas width in positioning.

height

Value: <length> | auto | from-canvas
Initial: auto
Applies to: block-level and replaced elements
Example: height: 100pt

This property can be applied to text, but it is most useful with inline images and similar insertions. The height is to be enforced by scaling the image if necessary. When scaling, the aspect ratio of the image should be preserved if the 'width' property is 'auto'.

The 'from-canvas' value means that the height of the element is such that the height and the margin add up to the height of the canvas. In HTML, 'BODY' has this value to allow properties on 'BODY' to use the canvas height in positioning.

float

Value: left | right | none
Initial: none
Applies to: block-level and replaced elements
Example: float: left

This property is most often used with inline images.

With the value 'none', the image will be displayed where it appears in the text. With a value of 'left' ('right') the margin properties will decide the horizontal positioning of the image and the text will float on the right (left) side of the image.

clear

Value: none | left | right | both
Initial: none
Applies to: block-level and replaced elements
Example: clear: left

This property specifies if elements allow floating elements (normally images) to the left or right. With 'clear' set to 'left', an element will be moved down to below any floating element on the left side.

pack

Value: tight | loose
Initial: tight
Applies to: block-level and replaced elements
Example: H1 { pack: loose }

If 'pack' is set to 'tight', element boxes will move up vertically until they hit another element. With a value of 'loose', the element will not move up beyond any element with the same value in the 'float' property. See the formatting model for an example that uses this property.

Borders

The border lies between the margin and the padding of an element. They are especially useful when formatting tables. The 'border-*-internal' properties apply only to tables.

border-style, border-style-internal

Value: none | dotted | single | double | thin-thick | thick-thin | beveled | raised (up to 4 values) Initial: none
Applies to: block-level and replaced elements
Example: border-style: double

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

The 'thin-thick' ('thick-thin') keyword requests a frame with the outer (inner) frame 'thin' and the inner (outer) frame 'thick'. The space between the two has the background color of the cell.

A border-style of 'none' requests no visible frame around the element. However, the corresponding border-width must be non-zero for this to be achieved, otherwise the frame will be inherited from surrounding elements.

This property is not inherited.

border-width, border-width-internal

Value: thin | medium | thick | <length> (up to 4 values) Initial: medium
Applies to: block-level and replaced elements
Example: H1 { border-width: 0.3em 0.2em }

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

This property is not inherited.

border-color, border-color-internal

Value: <color> | <uri>
Initial: undefined
Applies to: block-level and replaced elements
Example: border-color: "http://www.pat.com/pats/concrete.gif";

This attribute describes the color of the frame surrounding an element.

This property is not inherited.

Various properties

list-style

Value: <uri> | disc | circle | square | decimal | lower-roman | upper-roman | lower-alpha | upper-alpha | none
Initial: none
Applies to: see description
Example: OL { list-style: lower-roman }

This property applies only to the children of the element where it is specified. In HTML, it is typically used on the 'UL' and 'OL' elements.

magnification

Value: <number>
Initial: 1.0
Applies to: all elements
Example: HTML { magnification: 2.0 };

The property suggests a magnification factor for all spatial properties. E.g., by setting the magnification of the top-level element to '2.0', all length units (e.g. margins, font sizes, images) will be scaled accordingly.

Percentage values that refer to other spatial units are not scaled.

white-space

Value: normal | pre
Initial: according to HTML
Applies to: block-level elements
Example: PRE { white-space: pre }

Declares how white space inside the element should be handled: the 'normal' way (where white space is collapsed) or as the 'PRE' element in HTML.

Units

Length

  inches (in)
  pixels (px)
  centimeters (cm)
  millimeters (mm)
  ems (em)                /* ~ the width of the letter 'M'   */
  x-height (ex)           /* ~ the height of the letter 'x'  */
  points (pt)
  picas (pc)

Percentage

Percentage units are always relative to a length. Child elements always inherit the computed value, not the percentage itself.

Color

A color is a either a color name or a numerical RGB specification. The most basic list of color names include those common in the english language: black, white, red, green, blue, yellow, cyan, magenta, pink, brown, gray, orange, purple, violet. Also, prefixing color names with 'light-' or 'dark-' is allowed, e.g. 'red' and 'dark-red'.

The RGB color model is being used in numerical color specifications. Different ways to specify red:

  EM { color: red }
  EM { color: #F00 }             /* #RGB */
  EM { color: #FF0000 }          /* #RRGGBB */
  EM { color: rgb 1.0 0.0 0.0 }  /* float range: 0.0 - 1.0 */
To have room for other color models in the future, the 'rgb' keyword is required in the latter notation.

To ensure similar colors on different devices, numerical color values are in linear light and will require appropriate gamma correction.

URI

A Uniform Resource Identifier (URI) should be enclosed in quotes:

  BODY { background: "http://www.bg.com/pinkish.gif" }
Partial URIs are interpreted relative to the source of the style sheet, not relative to the document:
  BODY { background: "pink" }
The quotes in the above example indicate that the value is a URI, not the name of a color.

Notes on tables

In many cases, writing style sheets for HTML tables, as specified in the HTML3 table model, is like writing style sheets for any other HTML element. Most of the normal CSS addressing scheme and style properties can be reused:

  TABLE { font: 12pt helvetica } /* set the default font for table content */
  TFOOT { background: yellow }   /* set the default background for the footer cells */
  TH    { font-weight: bold }    /* set the default font-weight for the header cells */

However, table borders require special support from the style sheet mechanism. While CSS has a mechanism for resolving conflicts between various style sheets, table borders require a new level of diplomacy. For any given table cell, a number of elements may try to influence the borders. E.g. the borders of a 'TD' element in the lower right corner of a table may be influenced by properties set on 'TABLE', 'COL', 'COLGROUP', 'TR', 'TFOOT' and 'TBODY' elements. Normally, the inheritance rules would give priority to the most specific element (i.e. 'TD'), but there are several reasons why this strategy is not suited. First, tables do not easily lend themselves to the tree-structured approach of SGML, and it is not clear if the cell should inherit from the row or the column elements. Second, it is common to give the table a thick external border, and it is natural to set properties on the 'TABLE' element to achieve this. If priority was given to the cell elements ('TH' and 'TD'), the thick external border would be overridden.

To determine the borders of a given cell, we therefore suggest a strategy based on the width of the border. The element that assigns the thickest 'border-width' to a cell border wins, and the corresponding 'border-style' and 'border-color' will be used to render the border. If two elements set the same border width, the cascading rules for reader/author and important/legal take effect. If one still cannot resolve the conflict, sort by order specified.

It is convenient to think of table borders as internal/external: The internal border of some elements will be the external border of others. Consider the following simple table:

  <TABLE>
  <TR><TD>foo<TD>bar
  </TABLE>
Which would be formatted as:
         (a)         (b)
     ________________________
    |           |            |
 (c)|    foo   (d)   bar     |(e)
    |___________|____________|

         (f)         (g)

Here, (a), (c), (d) and (f) are external borders of the first 'TD' element, while (b), (d), (e) and (g) are external borders of the second 'TD' element. The 'TABLE' element has both external and internal borders: (a), (b), (d), (e), (f) and (g) are external, while (d) is internal.

The normal border properties ('border-width', 'border-style' and 'border-color') apply to external borders. Three new properties are introduced to address internal borders: 'border-width-internal', 'border-color-internal' and 'border-style-internal'. It is unimportant if the border width was set by the internal or external property: the thickest border wins.

The normal cascading rules are still used to:

Other properties follow the normal inheritance order, i.e. through the parent element. Since the 'COL' and 'COLGROUP' elements have no content, they are not suitable for setting other style properties than borders.

(One assumption in the above line of arguments is that the borders between adjacent cells are collapsed into one. Common desktop publishing software follows this model. However, the table implementation in Netscape has an exception: if the 'BORDER' attribute is set on the 'TABLE' element, the table is given an external border which is not collapsed with adjacent cells. Our current model is not able to represet this style.)

Formal grammar

Following is the formal grammar for CSS1. The format is optimised for human consumption and some shorthand notation beyond yacc is used:
  *  : 0 or more
  +  : 1 or more
  ?  : 0 or 1
  |  : separates alternatives
  [] : grouping 
The productions are:
stylesheet
 : import* rule*
 ;


import
 : IMPORT_SYM url			/* E.g., @import "fun.css" */
 ;
url
 : STRING
 ;


unary_operator
 : '-' | '+'
 ;
        /*
         * The only operators in level 1 are slash, space and comma.
         * An expression `a b c, d e f' stands for a list
         * [[a,b,c],[d,e,f]]. Note that `a,b,c' is the list
         * [a,b,c], *not* [[a],[b],[c]].
         */
operator
 : '/' | ',' | /* empty */
 ;
property
 : IDENT
 ;


rule
 : selector [ ',' selector ]*
   '{' declaration [ ';' declaration ]* '}'
 ;
selector
 : simple_selector+ [ ':' pseudo_class ]?
 ;
        /*
         * A simple_selector is something like H1, PRE.FOO,
         * .FOO, etc., or it is and ID: 'p004'
         *
         * DOT_WO_WS is a `.' without preceding whitespace.
         * DOT_W_WS is a `.' with preceding whitespace.
         */
simple_selector
 : element_name [ DOT_WO_WS class ]?
 | DOT_W_WS class
 | id_selector
 ;
element_name
 : IDENT
 ;
class
 : IDENT
 ;
pseudo_class
 : IDENT
 ;
id_selector
 : '#' IDENT
 ;
declaration
 : property ':' expr prio? 
 | /* empty */				/* Prevents syntax errors... */
 ;
prio
 : LEGAL_SYM STRING		 	/* !legal "with a reason" */
 | IMPORTANT_SYM	 		/* !important" */
 ;
expr
 : term [ operator term ]*
 ;
term
 : unary_operator?
   [ NUMBER | STRING | PERCENTAGE | LENGTH | EMS | EXS | LINES | IDENT ]
 ;
The following is the input to a lex/flex scanner:
%{
#include "constants.h"
/*
    The constants include definitions similar to the following:

    #define INCH (25.4 * MM)
    #define CM (10 * MM)
    #define MM 1
    #define PICA (12 * INCH/72 * MM)
    #define POINT (INCH/72 * MM)
*/
%}

%a 3000
%o 4000

urlchar		[a-zA-Z0-9:/_%~!@#$?*+{};.,|=`'-]
d		[0-9]
notnm		[^-a-zA-Z0-9]
nmchar		[-a-zA-Z0-9]|\\\.
nmstrt		[a-zA-Z]
w		[ \t\n]*
num		{d}+|{d}*\.{d}+
h		[0-9a-fA-F]
ident		{nmstrt}{nmchar}*

%x COMMENT

%%

"/*"			{BEGIN(COMMENT);}

<COMMENT>"*/"		{BEGIN(INITIAL);}
<COMMENT>\n		{/* ignore */}
<COMMENT>.		{/* ignore */}

@import			return IMPORT_SYM;
@class			return CLASS_SYM;
@define			return DEFINE_SYM;
"!"{w}legal		{return LEGAL_SYM;}
"!"{w}important		{return IMPORTANT_SYM;}
{ident}			{yylval.sym = str2Symbol(yytext); return IDENT;}
\"[^"\n]*\"		|
\'[^'\n]*\'		{yylval.str = noquotes(yytext); return STRING;}
{num}			{yylval.num = atof(yytext); return NUMBER;}
{num}{w}"%"		{yylval.num = atof(yytext); return PERCENTAGE;}
{num}{w}pt/{notnm}	{yylval.num = atof(yytext) * POINT; return LENGTH;}
{num}{w}mm/{notnm}	{yylval.num = atof(yytext); return LENGTH;}
{num}{w}cm/{notnm}	{yylval.num = atof(yytext) * CM; return LENGTH;}
{num}{w}pc/{notnm}	{yylval.num = atof(yytext) * PICA; return LENGTH;}
{num}{w}inch/{notnm}	{yylval.num = atof(yytext) * INCH; return LENGTH;}
{num}{w}px/{notnm}	{yylval.num = atof(yytext) * pixelwd; return LENGTH;}
{num}{w}em/{notnm}	{yylval.num = atof(yytext); return EMS;}
{num}{w}ex/{notnm}	{yylval.num = atof(yytext); return EXS;}

":"			return ':';

^"."|[ \t]+"."		return DOT_W_WS;
"."			return DOT_WO_WS;

"/"			return '/';
"+"			return '+';
"-"			return '-';
"{"			return '{';
"}"			return '}';
";"			return ';';
","			return ',';
"#"			return '#';
[ \t]+			{/* ignore whitespace */}
\n			{/* ignore whitespace */}

.			{yyerror("Illegal character");}

References

[1] The W3C resource page on web style sheets can be found on http://www.w3.org/pub/WWW/Style/

[2] ISO 8879. Information Processing - Text and Office Systems - Standard Generalized Markup Language (SGML), 1986. http://www.iso.ch/cate/d16387.html

[3] HTML3 and Style Sheets

[4] The HTML3 table model

Acknowledgments

During the short life of HTML, there have been several style sheet proposals to which this proposal is indebted. Especially, the proposals from Joe English and Pei Wei were influential.

Through "www-style@w3.org" and other electronic media, these people have contributed: Kevin Hughes, William Perry, Benjamin Sittler, Tony Jebson, Paul Prescod, Evan Kirshenbaum, Scott Bigham, Glenn Adams, Scott E. Preece, Greg Watkins, Jon Smirl, Chris Lilley and Mandira Virmani.

Also, thanks to Tim Berners-Lee, Vincent Quint, Cécile Roisin, Irène Vatton, Phill Hallam-Baker, Yves Lafon, Terry Allen, Daniel Connolly, Steven Pemberton, James Clark, Thomas Reardon, Chris Wilson and Lydja Williams for constructive discussions. A special thanks goes to Dave Raggett for his encouragement, suggestions and work on HTML3.

Appendix A: Sample style sheet for HTML 2.0

The following style sheet is written according to the suggested rendering in the HTML 2.0 specification. Some styles, e.g. colors, have been added for completeness.

  BODY { width: from-canvas; height: from-canvas;
         margin: 1em 1em;
         color: black; background: white;
         font-family: serif;
       }

  H1, H2, H3, H4, H5, H6, P, UL, OL, DIR, MENU, 
  LI, DT, DD, ADDRESS, BLOCKQUOTE, PRE { display: block }

  B, STRONG, I, EM, CITE, VAR, TT, CODE, KBD, SAMP { display: inline }

  H1, H2, H3, H4 { margin-top: 1em; margin-bottom: 1em }
  H5, H6 { margin-top: 1em }
  H1, H2, H4, H6 { font-weight: bold }
  H3, H5 { font-style: italic }

  H1 { font-size: xx-large; align: center }
  H2 { font-size: x-large }
  H3 { font-size: large }

  B, STRONG { font-weight: bold }
  I, CITE, EM, VAR, ADDRESS, BLOCKQUOTE { font-style: italic }
  PRE, TT, CODE, KBD, SAMP { font-family: monospace }

  PRE { white-space: pre }

  ADDRESS { margin-left: 3em }
  BLOCKQUOTE { margin-left: 3em; margin-right: 3em }

  UL, DIR { list-style: disc }
  OL { list-style: decimal }
  MENU { margin: 0 0 }
  LI { margin-left: 3em }

  DT { margin-bottom: 0 }
  DD { margin-top: 0; margin-left: 5em }

  A.link { color: red }          /* unvisited link */
  A.visited { color: dark-red }  /* visited links */
  A.active { color: orange }     /* active links */