W3C: Cascading Style Sheets, level 1

W3C Working Draft 23-Nov-95

URL: http://www.w3.org/pub/WWW/TR/WD-css1-951123.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 machanism (CSS1). CSS1 is a simple style sheet language that allows authors and readers to influence the presentation of HTML documents. E.g., a publisher can suggest font families, colors and layout for a document, while the reader can ask for the document to be magnified. By attaching style to HTML elements, document structure and device-independence is preserved.

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 HTML style sheets.

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, but it is not yet stable enough for a specification.
declaration
a property (e.g. 'font-size) and a corresponding value (e.g. '12pt')
designer
the designer of a style sheet
document
parsed SGML document. In technical terms, the document's ESIS (Element Structure Information Set).
element
SGML 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. The CSS specification defines a list of properties
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 apply 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
UA
User Agent. Often a "web browser" or "web client".
user
synonymous with "reader"

Basic concepts

Designing simple style sheets is easy. One 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, 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. One of the fundamental features of CSS is that style sheets are combined.

The selector is the link 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 are defined in this specification.

Containment in HTML

In order for the style sheet to influence the presentation, the user agent (UA, often a "web browser" or "web client") must be aware of its existence. Another W3C working draft will describe how to link HTML with style sheets. The example below is sure to be obsoleted by the forth-coming document, but describes how style sheet containment is implemented in the Arena browser:

<HEAD>
  <TITLE>Title</TITLE>
  <LINK REL=STYLESHEET HREF="bill.style" TITLE="Bill's own style">
  <STYLE NOTATION=CSS>
    H1 { color: blue }
  </STYLE>
</HEAD>
The LINK element references an external style sheet, while the proposed STYLE element has a style sheet as content.

By declaring the NOTATION, the STYLE element can be used for other style sheet notations as well. For LINKed style sheets, the HTTP Content-Type field will declare the notation. The TITLE attribute assigns a name to a style sheet for user interaction purposes.

CSS rules can possibly also be included in HTML attributes:

  <H1 STYLE="font-family: helvetica">Headline</A>
  <P STYLE="font: 12pt helvetica bold">Paragraph</A>
This use of the style language mixes content with style, and one loses the corresponding advantages of traditional style sheets.

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;
       font-leading: 2pt; 
       font-family: helvetica; 
       font-weight: bold; 
       font-style: normal
     }
In addition, some properties have their own grouping syntax:
  H1 { font: 12pt/14pt helvetica bold normal }
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 surrounding element, i.e. it will also appear in blue. Other style properties are likewise inherited, e.g. font family and size.

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

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

Class as selector

To increase the granularity of control over elements, HTML3 introduces 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 NOTATION=CSS>
    H1.punk { color: #00FF00 }
  </STYLE>
 </HEAD>
 <BODY>
  <H1 CLASS=punk>Way too green</H1>
 </BODY>
</HTML>

ID as selector

The HTML 'ID' attribute has a unique value, and can therefore be of special importance as a style sheet selector:
  [ID="z098y"] { font-size: xx-large }
The notation is borrowed from CSS2 which will allow addressing based on any attribute.

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 pseudo-classes:
  A.link { color: red }       -- unvisited link --
  A.visited { color: blue }   -- visited links --
  A.active { color: orange }  -- active links --

Pseudo-elements

The '$CANVAS' pseudo-element can be used to address the canvas (e.g. computer window or sheet of paper):
  $CANVAS { background: blue/red }
On a screen, the above example describes a background which is blue at the top of the screen and fades into red at the bottom of the screen.

Context sensitivity

This part is optional in CSS1

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

  H1   { color: blue }
  EM   { color: light-blue }
When this style sheet is in effect, all emphasized sections, within or outside H1 will turn light-blue. Probably, one only wanted EMs within H1 to turn light-blue. One can specify this with:
  (H1) EM { color: light-blue }
The selector is now a search pattern. Only the last element of the search pattern is addressed (in this case the EM element), and only so if the search pattern matches. In the example above, the search pattern matches if EM is a descendant of H1, i.e. if EM is inside an H1 element.
  (LI) (LI) P      { font-size: small }    
  (LI) (LI) (LI) P { font-size: x-small }
Here, the first selector matches P elements with at least two LI ancestors. The second selector matches a subset of the first matches, i.e. P elements with at least three LI ancestors. The conflict is resolved by the second selector being more specific (due to the longer search pattern).

Search patterns can contain elements and/or classes:

  (P.reddish) punk  { color: red }
This selector matches all elements with subclass 'punk' and an ancestor of element P and subclass 'reddish'.

Comments

Textual comments in a CSS style sheet start and end with two dashes:

  EM { color: red }  -- red, really red!! --

CSS1 ambitions

The CSS1 specification defines a list of style properties that a style sheet can influence. The goal is to be able to describe typography at the level of common desktop publishing. The following example, which includes a drop-cap initial and small-caps text, suggests the bounds of current properties:

<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE NOTATION=CSS>
   P { 
       text-effect: drop-cap,
       font-size: 12pt,
       alt-font-size: 24pt      -- assuming leading is zero --
     }
   EM { font-style: small-caps }
  </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 example shows the need for a new generic character-level element in HTML which doesn't bring with it any rendering conventions. We suggest adding a short HTML tag (e.g. 'C') for this, but the definition is outside the scope of this specification.

The cascade

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
a style sheet designer can combine several (incomplete) style sheets into one to reduce redundancy:
  @import "http://www.style.org/punk.css"

  H1 { color: red }     -- override imported sheet --

In case of a direct conflict, the imported style sheet has lower weight than the one from where it is being imported.

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

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 is less that 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 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 a UA may not be able to retrieve a externally linked style sheet.

Cascading order

Conflicting rules are intrinsic to the CSS mechanism, and should be resolved in the following manner:

  1. Reduce rules with identical selectors setting the same property. If the rules differ in imported-level, the least imported should live, while the other rules are discarded. Then, if there still are rules with identical selectors setting the same property, the one specified last should live, while the others are discarded.
  2. Find all declarations that apply to the element in question.
  3. Sort the declarations by explicit weight: declarations marked '!important' or '!legal ..' are heavier than unmarked (normal) declarations.
  4. Sort by origin: incoming style sheets override the reader's style sheet.
  5. Sort by specificity of selector: the "longer" the selector, the more specific it is. The exact definition of "length" is not yet clear, but intuitively this holds:
      'HTML' < 'LI' < '(UL) (OL) LI' < '(UL) (OL) LI.red'.
    
  6. Resolve conflicts between properties: individual declarations will override compound declarations. E.g, setting 'margin-left' will override the setting of the left margin in the 'margin' property.
  7. Sort by order specified: if two rules still 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.

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 style sheets, 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 element that implies a line break (e.g. H1 and P, but not EM) is surrounded by a frame. The size of the frame is the sum of the formatted content (e.g. text or image), the padding and the margins. The background of the content and padding area is controlled with the 'background' property, while the margins are transparent. The width of the margins specify the minimum distance to the edges of surrounding elements.

The following example with pseudo-constants shows how margins and padding format:

    <STYLE NOTATION=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.

Multi-column layout

Horizontally, boxes inherit the width of the parent element (i.e. after the margin and padding have been deducted).

Vertically, all boxes are attached to the above box. Note that the above box doesn't necessarily contain the preceding HTML 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 & box)                          |
 |  ______________        _____________________  |
 | |              |;;;;;;|                     | | 
 | | (H1 box)     |;;;;;;| (P box)             | |
 | |              |;;;;;;|                     | |
 | | Headline...  |;;;;;;| While.the.paragraph | | 
 | | comes.here.  |;;;;;;| starts.here.and.... | |
 | |______________|;;;;;;| continues.below.the | |
 | ;;;;;;;;;;;;;;;;;;;;;;| box.to.the.left.... | |
 | ;;;;;;;;;;;;;;;;;;;;;;|_____________________| |
 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
 |_______________________________________________|
                                               
   ^              ^      ^                     ^
   0%            35%    50%                   100%    
The above could be realized through:
  H1 { 
       margin-left: 0%; 
       margin-right: 65%   -- (100% minus 35%) --
     }
  P  {
       margin-left: 50%; 
       margin-right: 0%
     }
The percentages are relative to the width of the parent element.

[A property to describe if an element "float upwards" should be added]

Horizontal margins and width

Five properties influence the horizontal dimensions of an element: 'width', 'padding-left', 'padding-right', 'margin-left' and 'margin-right'. 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. 'padding-left'
  2. 'padding-right'
  3. 'width'
  4. 'margin-left'
  5. 'margin-right'
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'.

CSS1 properties

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

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 resources available, some properties can prove hard to incorporate into existing UA implementations (e.g. 'text-effect' and 'flow'), and can be considered optional. [strengthen definition]

Also, an ASCII-based UA in a monochrome environment is not able to honor color values, but may try to do layout based on the style properties.

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: UA specific
Example: font-size: 12pt

Font sizes can either be set to an absolute height using 'font-size', or to a relative index using 'font-size-index'. If defined, 'font-size' will take precedence.

If the value is an integer number, it is to be interpreted as an index. Index 0 corresponds to 'medium' (the actual size is application dependent and/or set-able by the user). 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). If the number is a floating point, the UA should interpolate a font size if possible. Otherwise, it should round off to the closest integer index.

Percentage is relative to the font-size of the parent element.

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
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> | <percetnage>
Initial: 0
Example: font-weight: demi-bold

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

If the desired font weight is not available, the UA selects a substitution order. Non-integer font weights are allowed.

Percentage values refer to the font weight of the parent element.

font-style

Value: italic | oblique | small-caps | normal
Initial: normal
Example: font-style: italic

If the preferred font style cannot be accomplished, the following substitutions should be attempted by the UA:

italic -> oblique
oblique -> italic
* -> normal

If 'small-caps' are not available, capitals letter of a smaller font size can be used to render small characters if the resolution of the output medium is appropriate for this.

font-leading

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

Leading refers to the extra space between lines. A percentage unit is relative to the font size. E.g.:

  P { font-leading: 20%; font-size: 10pt }
Here, the leading would be 2pt.

font

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

This is a conventional shorthand notation from the typography community to set font-size, font-leading, font-family, font-style, and font-weight. Setting the properties individually override the shorthand notation if the weight is otherwise the same.

Note that it is the line height, not the leading, that is specified. The relationship is: line-height = font-size + font-leading.

Color and background

color

Value: <color>
Initial: UA specific
Example: color: #F00

See the section on units for a description.

[should image URIs be allowed?]

background

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

This property does not inherit, but unless set explicitly the parent'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'). The resulting background is a fade between 'bg1' and 'bg2'. The 'bg-light-source' property specifies from where 'bg2' is to be "emitted".

bg-style

Value: [ repeat | repeat-x | repeat-y | no-repeat | scroll | fixed ] +
Initial: repeat scroll
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%
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.

[should one have to address $CANVAS to make something go into the lower right corner of the wendow?]

bg-light-source [another name?]

Value: N | NW | W | SW | S | SE | E | NE [ N | NW | W | SW | S | SE | E | NE ]
Initial: SE SW
Example: bg-light-source: SE NW

[A new property with great potential]

The values are shorthands for north, north-west, west etc.

This property specifies the point or vector from where 'bg2' (if defined in the 'background' element) is to be "emitted". If only a point is defined (e.g. SW as indicated on the chart below), it will aquire the 'bg2' background. As one moves away from the point, the background will gradually change to 'bg1'.

 NW    N    NE


 W           E


 SW    S    SE

If a vector is specified with two points, the light-source changes accordingly.

Text

text-spacing

Value: <percentage>
Initial: 0
Example: text-spacing: 20%

Default text spacing is 0%. The UA is free to select the text spacing algorithm, but both the word spacing and the letter spacing should be affected. The specified percentage is the target vertical length of the formatted text as compared to the standard text spacing. E.g., a text spacing of 20% will make the formatted text 20% longer.

text-decoration

Value: [ none | underline | overline | line-through | box | shadowbox | box3d | cartouche | blink ] +
Initial: none
Example: text-decoration: underline

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

The color of the decoration is based on the color of the text.

text-position

Value: <number> | sub | super
Initial: 0
Example: text-position: sub

The property affects the vertical positioning of text: 'sub' will make the text subscripted, while 'super' will superscript the text.

text-transform

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

'capitalize' uppercases the first character of each word.

'none' is used to neutralize an inherited value.

text-effect

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

All text effects are rendered using the alternate properties.

initial-cap
the first alphabetical character of the element is rendered using the alternate properties. There is no case conversion. [strengthen definition]
drop-cap
the first alphabetical character of the element is rendered using the alternate properties and "dropped" into the box enclosing the paragraph. [strengthen definition]
alt-firstline
the first line (as formatted by the UA) of the paragraph is rendered using the alternate properties.

text-align

Value: left | right | center | justify
Initial: human language dependent
Example: text-align: center

This property describes how text is aligned. It applies only to elements that have a break before them (i.e. only block-level elements in CSS1).

text-indent

Value: <length> | <percentage>
Initial: 0
Example: text-indent: 3em

This property is not inherited.

Extra indent that only applies to the first formatted line. May be negative ('outdent'). The property only applies to block-level elements. 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.

Alternate properties

Some typographic styles require an alternate set of properties to be rendered. In CSS1, this is the case for 'text-effect' as well as the 'alt-firstline'.

The following properties influence the "alternate" rendering:

  alt-font
  alt-font-family
  alt-font-size
  alt-font-leading
  alt-font-weight
  alt-font-style
  
  alt-color
  alt-background

  alt-text-spacing
  alt-text-decoration
  alt-text-position 
  alt-text-transform

Layout

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

padding-top, padding-right, padding-bottom, padding-left

Value: <length> | <percentage>
Initial: 0
Example: padding-left: 20%

How much space to insert between the border of the frame and the content (e.g. text or image). The color of the padding area is controlled with the 'background' property. See the formatting model for more on these properties.

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

Padding values are >= 0.

padding

Value: <length> | <percentage> [ <length> | <percentage> [ <length> | <percentage> [ <length> | <percentage> ] ] ]
Initial: 0
Example: padding: 20% 20%

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 property is shorthand for setting 'padding-top', 'padding-right' 'padding-bottom' and 'padding-left' separately. The individual declarations take precedence if the weights are otherwise equal.

margin-left, margin-right

Value: <length> | <percentage> | auto
Initial: 0
Example: margin-left: 2em

The minimal horizontal distance between the element's box and surrounding elements.

Horizontal margins may be negative.

See the formatting model for a description of the relationship between these properties and 'width'.

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

margin-top, margin-bottom

Value: <length>
Initial: 0
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. See the formatting model for an example.

Percentage values are relative to the width of the parent element. [rationale]

Vertical margins are >= 0.

margin

Value: <length> [ <length> [ <length> [ <length> ] ] ]
Initial: 0
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 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 equal.

flow

Value: block | inline
Initial: undefined
Example: flow: block

This property decides 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.

This property is not inherited.

width

Value: <length> | auto | <percentage>
Initial: auto
Example: 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 ration of the image should be preserved.

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 'margin-left' and 'margin-right'.

display-area

Value: float-left | float-right | normal
Initial: normal
Example: display-area: float-left

With the value 'normal', the element will be displayed in the main text. 'float-left' and 'float-right' will make the element float to the margin. This property is most often used with inline images.

Frames

The frame lie between the margin and the padding of an element. They are especially useful when formatting tables.

frame-style

Value: <keyword> [ <keyword> [ <keyword> [ <keyword> ] ] ]
Initial: none
Example: frame-style: double

Keyword values are: none | dotted | single | double | thin-thick | thick-thin | beveled

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

The 'thin-thick' ('thik-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.

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

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

Additional suggested keyword values include: dotted, wavy, baroque, filet, art-deco, raised, lowered, etched. shadow.

frame-width

Value: <width> [ <width> [ <width> [ <width> ] ] ]
Initial: medium
Example: frame-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 is only one value, it applies to all sides, if there are two or three, the missing values are taken from the opposite side.

A frame-width of 0 requests the frame to be inherited from surrounding elements.

frame-color

Value: <color> | <uri>
Initial: undefined
Example: frame-color: "http://www.pat.com/pats/concrete.gif";

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

Page

The page properties are used for paged media, e.g. paper and page-oriented screen browsers.

page-break-after, page-break-before

Value: <number> | never | discourage | neutral | encourage | always
Initial: 0
Example: H1 { page-break-after: never }

Numbers can be from -2 to 2, corresponding, respectively, to the keywords. All 'pagebreak-before' and 'pagebreak-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-break-inside

Value: <number> | never | discourage | neutral
Initial: neutral
Example: PRE { page-break-inside: discourage }

Values can be -2, -1 or 0 meaning, respectively, never allow page-break inside element ('never'), discourage page-break inside element ('discourage'), or neutral about page-break inside element ('neutral').

Various properties

list-style

Value: <uri> | disc | circle | square | decimal | lower-roman | upper-roman | lower-alpha | upper-alpha | none
Initial: none
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
Example: HTML { magnification: 2.0 };

[This is possibly the most powerful property of them all]

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

Percentage values that refer to other spatial units are not scaled. [We also need a property to describe the PRE element]

Units

Length

  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)

  picas (pc)

Percentage

In most cases, a percentage unit is relative to a length unit. 'text-spacing' is an example of a property that is not relative to a length unit.

Color

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 color names with 'light-' or 'dark-' is allowed, e.g. 'light-blue' and 'dark-gray'.

The RGB color model is being used in color specifications. Other color models should be kept in mind for later extensions.

Different ways to specify red:

  EM { color: #F00 }
  EM { color: #FF0000 }
  EM { color: 255 0 0 }      -- integer range: 0-255   --
  EM { color: 1.0 0.0 0.0 }  -- float range: 0.0 - 1.0 --
  EM { color: red }

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.

Notes on tables

Tables do not easily lend themselves to the tree-structured approach of SGML, and some special rules apply to the presentation of tables. All examples in this section are written according to current version of the HTML3 table model.

In many cases, writing style sheets for HTML tables 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 --

Some style properties are especially useful in tables:

  TR.europe { frame-style: double }

The example above requests for row elements with subclass 'europe' to get a double border around them. Note that the 'frame-style' attribute does not inherit, so only the outside frame of the row, not each cell within the row, will get this style. Similarly, columns can be addressed with the 'COL' and 'COLGROUP' element:

  COLGROUP { frame-style: none single; -- set vertical, no horizontal --
             frame-color: "http://www.style.com/cool/bg.gif" blue;
             frame-width: 0.5cm }

Note! One fundamental principle of CSS is that properties attached to one element only applies to that element and descendants. Attaching style to 'COL' and 'COLGROUP' breaks with this principle as they have no content, and the properties assigned may influence the presentation of other elements. We are working on a general model to easier support various table models.

The example above gives all 'COLGROUP' elements a 0.5cm single vertical border between them. The border will be blue when the requested image is not available. There is no horizontal border.

Table formatting model

Frame widths between adjacent cells do not add up. Rather, the distance between two adjacent cells is the maximum of the two corresponding frame widths:


  [ID=foo] { padding: a b c d;
             frame-width: x x e x;
           }

  [ID=bar] { padding: A B C D;
             frame-width: E x x x;
           }

   _______________________
  |    a   padding         |
  |    ________________    |
  | d | cell content   | b |
  |   | ID=foo         |   |
  |   |________________|   |
  |    c                   |
  |________________________|
            
       max (e, E)   frame 
   _______________________
  |    A   padding         |
  |    ________________    |
  | D | cell content   | B |
  |   | ID=bar         |   |
  |   |________________|   |
  |    C                   |
  |________________________|

Note that the elements inside 'TABLE' do not include the margin properties. The only exception is the 'CAPTION' element and its children.

Table precedence order

When rendering table cells, there may be conflicts between frames of adjacent cells. E.g., the requested 'frame-style' of a single cell may conflict with the requested 'frame-style' of the row to which the cell belong. Conflict resolution is partially based on the normal cascading order, which are followed to and including step number 4. From there, the following rules apply until a non-ambigous order is found:
  1. Table elements have the following priority: 'TABLE' > ('THEAD' | 'TBODY' | 'TFOOT') > 'COLGROUP' > 'COL' > 'TR' > 'TH' > 'TD'. Matches in 'CLASS' or 'ID' attributes do not alter this order, but has significance for otherwise equal elements.
  2. left > right
  3. top > bottom

Aliases

Some terms may have spellings in different traditions. The following aliases should be accepted:

color  : colour
italic : italics

Formal grammar

[The grammar is slightly out or date, but will be updated ASAP]

This is the grammar for CSS. It consists of two parts: a context free grammar in Yacc/Bison format and a lexical analyzer in Lex/Flex format. The formal grammar supports both CSS1 and CSS2. Although CSS1 grammar is a little simpler, we encourage implementation to parse style sheets of both levels.

Yacc/Bison grammar

%expect 2
/*
   There are two shift/reduce conflicts in more_terms,
   because op can be empty
 */

%token IMPORT DEFINE ARCHFORM IMPORTANT LEGAL
%token INTERPOLATEHI INTERPOLATELO PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ
%token STRING HEXCOLOR
%token IDENT ENVVAR
%token NUMBER LENGTH EMS NCHARS PERCENTAGE

%%

stylesheet
 : imports defs rules
 ;
imports
 : imports IMPORT url
 | /* empty */
 ;
url
 : STRING
 ;
defs
 : defs constant_def
 | defs archform_def
 | /* empty */
 ;
constant_def
 : DEFINE unique_id '=' value ';'
 ;
unique_id
 : IDENT
 ;
archform_def
 : ARCHFORM attrname
 ;
attrname
 : IDENT
 ;
rules
 : rule_seq media_rules
 ;
media_rules
 : media_rules medium rule_seq
 | /* empty */
 ;
medium
 : ':' IDENT other_media ':'
 ;
other_media
 : other_media '&' IDENT
 | /* empty */
 ;
rule_seq
 : rule_seq rule
 | /* empty */
 ;
rule
 : selector_seq '{' declaration_seq '}'
 ;
selector_seq
 : selector_seq ',' selector
 | selector
 ;
selector
 : toplevel
 | ancestors predecessor_opt elemspec
 ;
toplevel
 : '*'
 ;
ancestors
 : ancestors predecessor_opt ancestor
 | /* empty */
 ;
ancestor
 : '(' elemspec ')'
 ;
predecessor_opt
 : predecessor
 | /* empty */
 ;
predecessor
 : '/' elemname '/'
 ;
elemname
 : IDENT
 | IDENT '.' IDENT
 ;
elemspec
 : elemname attrspec_seq
 | attrspec_seq
 ;
attrspec_seq
 : attrspec_seq attrspec
 | /* empty */
 ;
attrspec
 : '[' attrname constval_opt ']'
 ;
constval_opt
 : '=' constval
 | /* empty */
 ;
constval
 : NUMBER
 | STRING
 | IDENT
 ;
declaration_seq
 : declaration_seq ',' declaration
 | declaration
 ;
declaration
 : property ':' value priority_opt
 | property op_eq value priority_opt
 ;
priority_opt
 : IMPORTANT
 | LEGAL STRING
 | /* empty */
 ;
property
 : IDENT
 ;

/*
 * Operator precedence: high to low
 * 5:  + -      (monadic plus, monadic minus)
 * 4:  * / %    (multiply, divide, remainder)
 * 3:  + -      (plus, minus)
 * 2:  << >>    (interpolate low, interpolate high)
 * 1:           ([=space] concatenate)
 */
value
 : value1 value
 | value1
 ;
value1
 : value2 INTERPOLATELO value1
 | value2 INTERPOLATEHI value1
 | value2
 ;
value2
 : value3 '+' value2
 | value3 '-' value2
 | value3
 ;
value3
 : value4 '*' value3
 | value4 '/' value3
 | value4 '%' value3
 | value4
 ;
value4
 : '+' term
 | '-' term
 | term
 ;
term
 : LENGTH
 | EMS
 | NCHARS
 | STRING
 | HEXCOLOR
 | NUMBER
 | PERCENTAGE
 | IDENT
 | attref
 | envref
 | '(' value ')'
 ;
attref
 : '[' attrname ']'
 ;
envref
 : ENVVAR
 ;
op_eq
 : PLUS_EQ
 | MINUS_EQ
 | STAR_EQ
 | SLASH_EQ
 ;

Lexical scanner


%{
#include "y.tab.h"
#include "constants.h"
/*
    The constants include definitions similar to the following:

    #define WEEK (7 * DAY)
    #define DAY (24 * HOUR)
    #define HOUR (60 * MINUTE)
    #define MINUTE (60 * SECOND)
    #define SECOND 1
    #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]
hexcolor        #{h}{h}{h}|#{h}{h}{h}{h}{h}{h}|#{h}{h}{h}{h}{h}{h}{h}{h}{h}
ident           {nmstrt}{nmchar}*

%x COMMENT

%%

"--"                    {BEGIN(COMMENT);}

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

@import                 return IMPORT;
@archform               return ARCHFORM;
@define                 return DEFINE;
"!"{w}legal             {return LEGAL;}
"!"{w}important         {return IMPORTANT;}
"$"{ident}              {return ENVVAR;}
{hexcolor}              {return HEXCOLOR;}
{ident}                 {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}ch/{notnm}      {yylval.num = atof(yytext); return NCHARS;}
{num}{w}d/{notnm}       |
{num}{w}day/{notnm}     |
{num}{w}days/{notnm}    {yylval.num = atof(yytext) * DAY; return NUMBER;}
{num}{w}w/{notnm}       |
{num}{w}week/{notnm}    |
{num}{w}weeks/{notnm}   {yylval.num = atof(yytext) * WEEK; return NUMBER;}
{num}{w}h/{notnm}       |
{num}{w}hour/{notnm}    |
{num}{w}hours/{notnm}   {yylval.num = atof(yytext) * HOUR; return NUMBER;}
{num}{w}m/{notnm}       |
{num}{w}min/{notnm}     |
{num}{w}minute/{notnm}  |
{num}{w}minutes/{notnm} {yylval.num = atof(yytext) * MINUTE; return NUMBER;}
{num}{w}s/{notnm}       |
{num}{w}sec/{notnm}     |
{num}{w}second/{notnm}  |
{num}{w}seconds/{notnm} {yylval.num = atof(yytext) * SECOND; return NUMBER;}

"<<"                    return INTERPOLATELO;
">>"                    return INTERPOLATEHI;
"+:"                    return PLUS_EQ;
"-:"                    return MINUS_EQ;
"*:"                    return STAR_EQ;
"/:"                    return SLASH_EQ;
":"                     return ':';
"."                     return '.';
"/"                     return '/';
"*"                     return '*';
"+"                     return '+';
"-"                     return '-';
"="                     return '=';
"("                     return '(';
")"                     return ')';
"{"                     return '{';
"}"                     return '}';
"["                     return '[';
"]"                     return ']';
";"                     return ';';
"&"                     return '&';
","                     return ',';
[ \t]+                  {/* ignore whitespace */}
\n                      {/* ignore whitespace */}

.                       {yyerror("Illegal character");}

References

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

Acknowledgments

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 influential:

Through "www-style@w3.org" and other electronic media, these people have contributed: Also, thanks to Tim Berners-Lee, Vincent Quint, Cécile Roisin, Irène Vatton, Phill Hallam-Baker, Terry Allen, Daniel Connolly, Steven Pemberton and James Clark 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. top-level font family, have been added for completeness.


  -- first, set some properties to the top-level element --
  -- the will inherit nicely down the tree               --

  HTML { 
         font-family: serif;
         font-size: medium; 
         font-weight: medium;
         text-align: left;
         margin: 0.5em 0
       }

  -- the rendering instructions for the H* elements are  --
  -- quite detailed                                      --

  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 }

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