This is the fourth major revision of the specification. It is on its way from a loose collection of ideas to an Internet-Draft, and we plan to finish by the end of 1995. In this version, the basic parts ("level 1") are approaching stability, and we encourage programmers and authors to start experimenting. Comments, especially we encourage comments with regard to the separation of levels, 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. Last changed: October 6, 1995


Cascading Style Sheets: a draft specification

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

Content

  1. Background
  2. Overview
  3. Terminology
  4. Level 1 features
  5. Formatting model
  6. Level 1 properties
  7. Units
  8. Cascading order
  9. Aliases
  10. Formal grammar
  11. References
  12. Acknowledgments
  13. Appendix A: Sketches of level 2
  14. Appendix B: Suggested level 2 properties

Background

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

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

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

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

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

Overview

Publishers on the web do not request presentational control to the level of professional typography. Instead, they ask for influence over fonts, colors and space, and they want it now. In order to speed up the process of defining and implementing a style sheet mechanism on the web, levels have been introduced in this specification. Level 1 contains the most basic features of a style sheet mechanism, while retaining much of the expressive power. Level 2 will add new capabilities to the style sheet language, but all it's features haven't been worked out yet. Sketches of level 2 are included in the appendices.

Terminology

assignment
a property and a corresponding value, e.g. "font-family = helvetica"
author
the author of a document
canvas
the part of the UA's drawing surface onto which documents are rendered
CSS
Cascading Style Sheets, a style sheet mechanism defined in this document.
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. All style sheet examples in the CSS specification apply to HTML.
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 who for whom the document is rendered
rule
an assignment and its selector, e.g. "H1 { font-family = helvetica }"
selector
the part of a rule which defines what elements the rule applies to
SGML
Standard Generalized Markup Language, of which HTML is an application
style sheet
a collection of rules
UA
User Agent. Commonly referred to as "web browser" or "web client".
user
synonymous with "reader"

Level 1 features

Designing simple style sheets is easy. You only need to know a little HTML and some basic desktop publishing terminology. E.g., to set the text color of H1 elements to blue, you can say:
  H1 { text-color = blue }
The example consists of two main parts: selector (H1) and assignment (text-color = blue). The assignment has two parts, property (text-color) and value (blue). While the example above only tries to influence a small fraction 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 partial style sheets are combined into complete ones.

The selector is the glue between the HTML document and the style, and all HTML elements are possible selectors. HTML elements are defined in the HTML specifications, and the CSS specification only defines a syntax for how to address them. Also, the list of properties and values 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. In HTML, this can be done by putting the style sheet inside the proposed STYLE element, or reference it through a LINK:

<HEAD>
  <TITLE>Title</TITLE>
  <LINK REL=STYLESHEET HREF="bill.style" TITLE="Bill's own style">
  <STYLE NOTATION=CSS>
    H1 { text-color = blue }
  </STYLE>
</HEAD>

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 that can be used in user interaction.

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

A document can contain several LINK and several STYLE elements. The reader should be able to choose between several style sheets, e.g. through a pull-down menu with the names of all listed style sheets. STYLE elements without their own TITLE attribute are combined with the preceding titled style sheet following the normal cascading rules. If no preceding titled style sheet exits, the UA should assign a title to the style sheet and treat it as any other titled style sheet. If two style sheets have the same title, they should be combined using the normal rules for cascading.

Grouping

To reduce the size of style sheets, you can group selectors in comma-separated lists:
  H1, H2, H3 { font-family = helvetica }
Similarly, assignments can be grouped:
  H1 { 
       fonts-size = 12pt, 
       font-leading = 2pt, 
       font-family = helvetica, 
       font-weight = bold 
     }
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 surrounding element, i.e. it will also appear in blue. Other style properties are likewise inherited, e.g. font family and size.

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

  HTML: text-color = dark-blue

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

  * { text-color = dark-blue }

Some style properties are not inherited from the parent to the child. In most cases, it is intuitive why this is not the case. E.g., the first line indent property (indent) does not inherit.

Class as selector

To increase the granularity of control over elements, HTML3 introduces a new attribute: CLASS. Most elements can be sub-classed, and the subclass can be addressed in the style sheet:
<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE NOTATION=CSS>
    H1.punk { text-color = #00FF00 }
  </STYLE>
 </HEAD>
 <BODY>
  <H1 CLASS = punk>Way too green</H1>
 </BODY>
</HTML>

Classes can also be selectors independent of HTML elements:

<HTML>
 <HEAD>
  <TITLE>Title</TITLE>
  <STYLE NOTATION=CSS>
    punk { text-color = green }
  </STYLE>
 </HEAD>
 <BODY>
  <H1 CLASS = punk>Way too green headline</H1>
  <P CLASS = punk>Way too green paragraph</H1>
 </BODY>
</HTML>
One interesting use of this feature is to introduce new elements without writing new style rules:
  <par class=p>This is a <emph class=em>PAR</emph>, which looks like a
  <tag class=strong>P</tag>, because it is declared as being of of the
  same class.</par>

Context sensitivity

Inheritance saves CSS designers a lot of typing. Instead of setting all style properties, you can create defaults and then list the exceptions. If you want to give EM elements within H1 a different color, you may specify:
  H1   { text-color = blue }
  EM   { text-color = light-blue }
When this style sheet is in effect, all emphasized sections, within or outside H1 will turn light-blue. Probably, you only wanted EMs within H1 to turn light-blue. You can specify this with:
  (H1) EM { text-color = light-blue }
The selector is now a search pattern. Only the last element of the search pattern is addressed (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 --:

  EM { text-color = red }  -- red, really red!! --

Level 1 ambitions

The CSS 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 tag, e.g. "C" for this.

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

  H1 { text-color = red }     -- override imported sheet --

The @import .. statement is semantically equal to a <LINK REL=StyleSheet href= .. >. In case of a conflict, the imported style sheet has lower weight than the one from where it's 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.

Typically, UAs will assume that the style sheets of your initial page (if it finds any) is your personal favorite, and apply them to all subsequent documents. If subsequent documents have their own style sheets, conflicts may arise. Conflict resolution is based on each style assignment having a weight. By default, the weights of the reader's assignments is less that the weights of assignments 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 assignments will be used.

Style sheet designers can increase the weights of their assignments:

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

An important (or legal) reader assignment will override an incoming assignment with normal weight. An important (or legal) incoming assignment will override an important (or legal) reader assignment. A complete description of the cascading order can be found later in this specification.

The reference to the statutes should be displayed to the reader as a warning when the UA is not able to honor a legal assignment. 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 assignment 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 style sheet pointed to by a LINK. In general, the HTML3 banner area is a better place to put legal information.

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. This will be possible with the environment variables of level 2, but for level 1 we need to introduce pseudo-classes that can be used for addressing:
  A.link { text-color = red }       -- unvisited link --
  A.visited { text-color = blue }   -- visited links --
  A.active { text-color = orange }  -- active links --

ID as selector

[It has been suggested the the ID attribute, which always has a unique value, should be given a special addressing syntax and a special weight in the cascading order. Suggestions are welcome.]

Formatting model

This document suggests a simple box-oriented formatting model. Each element that implies a line break (e.g. H1 and P, but not EM) is surrounded by a box. The size of the box is the sum of the formatted content (e.g. text or image), the box offset, and the margins. The background of the box 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 box-offsets format:

    <STYLE>
      UL { 
           background = red, 
           margin = A B C D,      -- let's pretend we have constants in CSS --
           box-offset = 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 CSS --
           box-offset = 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 box-offset (red)                    |   |
   |    |    _______________________________________    |   |
   |    | H |                                       | F |   |
   |    |   |    a   LI margin (transparent,        |   |   |
   |    |   |        so red shines through)         |   |   |
   |    |   |    _______________________________    |   |   |
   |    |   | d |                               | b |   |   |
   |    |   |   |    e    LI box-offset (blue)  |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   | h  1st element of list        |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   |    g                          |   |   |   |
   |    |   |   |_______________________________|   |   |   |
   |    |   |                                       |   |   |
   |    |   |     max(a, c)                         |   |   |
   |    |   |                                       |   |   |
   |    |   |    _______________________________    |   |   |
   |    |   |   |                               |   |   |   |
   |    |   | d |    e    LI box-offset (blue)  |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   | h  2nd element of list        |   |   |   |
   |    |   |   |                               |   |   |   |
   |    |   |   |    g                          |   |   |   |
   |    |   |   |_______________________________|   |   |   |
   |    |   |                                       |   |   |
   |    |   |   c    LI margin (transparent,        |   |   |
   |    |   |        so red shines through)         |   |   |
   |    |   |_______________________________________|   |   |
   |    |                                               |   |
   |    |    G                                          |   |
   |    |_______________________________________________|   |
   |                                                        |
   |    C                                                   |
   |________________________________________________________|

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

Horizontally, boxes inherit the with of the parent element (i.e. after the margin and box-offset has 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.

Horizontal margins and width

Five properties influence the horizontal dimensions of an element: width, box-offset-left, box-offset-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. box-offset-left
  2. box-offset-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".

Blockbefore and blockafter elements

[The layout of these elements require special handling. To be supplied.]

Level 1 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 CSS level 1.

The list of level 1 properties has been kept to a 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, text-style and break), and can be considered optional.

Also, an ASCII-based UA in a monochrome environment is not able to honor color values, but may try to lay out elements based on the style sheet 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>
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.

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

Value: <number> | xx-small | x-small | small | medium | large | x-large | xx-large
Initial: medium
Example: font-size-index = x-large

Index 0 corresponds to "medium" (the actual size is application dependent and/or set-able by the user). A scaling factor of 1.2 is suggested between adjacent indexes, e.g. if the "medium" font is 10pt, the "large" font should be 12pt.

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's 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 | -3 | -2 | -1 | 0 | 1 | 2 | 3
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.

font-style

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

If the preferred font style can't be accomplished, the following substitutions should be attempted by the UA:

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

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

[should "roman" instead be a generic font family?]

font-leading

Value: <length>
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's 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: text-color = 0.0 0.0 0.5

See the section on units for a description.

background

Value: <color> | <uri> | none
Initial: UA specific
Example: text-background = "http://www.pat.com/pats/silk.gif"

Text

text-spacing

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

Default text spacing is 0%. The UA is free to select text spacing algorithm.

text-decoration

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

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

text-position

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

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 and 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 letter of the element is rendered using the alternate properties. There is no case conversion.
drop-cap
the first alphabetical letter of the element is rendered using the alternate propertiesand "dropped" into the box enclosing the paragraph.
alt-firstline
the first line (as formatted by the UA) of the paragraph is rendered using the alternate properties.

Alternate properties

Some typographic styles require an alternate set of properties to be rendered. In level 1, this is the case for text-effect where the initial letter of the initial-cap and drop-cap values, as well as the first line of alt-firstline. In level 2 they will also be used for labels and inserted text before/after the element.

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-line
  alt-text-position
  alt-text-transform

Layout

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

box-offset-top, box-offset-right, box-offset-bottom, box-offset-left

Value: <length>
Initial: 0
Example: box-offset-left = 20%

How much space to insert between the border of the box and the content (e.g. text or image). See the formatting model for more on these properties.

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

box-offset

Value: <length> [ <length> [ <length> [ <length> ] ] ]
Initial: 0
Example: box-offset = 20% 20%

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

The property is shorthand for setting "box-offset-top", "box-offset-right" "box-offset-bottom" and "box-offset-left" separately. The individual assignments take precedence if the weights are otherwise equal.

margin-left, margin-right

Value: <length> | 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 relationsship between these properties and "width".

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

[Should we also be able to do margins relative to the width of the current 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. For example, between `abc' and `def' in the fragment "...abc</P></LI></OL><P>def..." the space is the maximum of the bottom margins of P:margin, LI:margin, OL:margin and the top margin of P:margin.

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

Vertical margins must be positive.

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's only one, it applies to all sides, if there are two or three, the missing lengths are taken from the opposite side.

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

break

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

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

align

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

This property describes how text is aligned. It applies only to elements that have a break before them.

indent

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

This property is not inherited.

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

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

width

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

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

[Should scaling preserve the aspect ratio?]

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

See the formatting model for a description of the relationsship between this property and "margin-left, margin-right".

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 = -2 }

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: 0
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 ("encourage"), and don't care about page-break inside element ("neutral").

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)
  characters (ch)     -- should be dropped in favor of ems?   --
  picas (pc)
Also, specifying a percentage (%) is legal as a length unit. Most often, the percentage is relative to the width of the parent element. font-leading is a exception.

Percentage

Most often, a percentage unit is relative to a length unit. However, text-spacing is an example of a property that only accept a percentage value.

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

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

Different ways to specify red:

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

URI

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

  BODY { text-background = "http://www.bg.com/pinkish.gif" }
Partial URIs are interpreted relative to the source of the style sheet, not relative to the document.

Cascading order

[still needs a bit work]

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 assignments that apply to the element in question.
  3. Sort the assignments by explicit weight: assignments marked "!important" or "!legal .." are heavier than unmarked (normal) assignments.
  4. Sort by specificity of selector: the "longer" the selector, the more specific it is. The exact definition of "length" is no yet clear, but intuitively, this holds:
      "*" < "LI" < "(UL) (OL) LI" < "(UL) (OL) LI.red".
    
  5. Sort by origin: incoming style sheets override the reader's style sheet. [does this mean the reader can add weight to the assignments by putting "HTML" first in all selectors?]
  6. Resolve conflicts between properties: individual assignments will override compound assignments. 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.

Aliases

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

color  : colour
italic : italics

Formal grammar

This is the grammar for CSS. It consists of two parts: a context free grammar in Yacc format and a lexical analyzer in Lex format.

Yacc grammar, level 2

stylesheet: imports decls rules;
imports: imports IMPORT url;
url: STRING;
decls: decls constant_decl | decls archform_decl | /* empty */;
constant_decl: DEFINE unique_id '.' value ';';
unique_id: IDENT;
archform_decl: 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: address address_list '{' property property_list '}' priority_opt;
address_list: address_list ',' address | /* empty */;
address: 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: '[' attrname constval_opt ']';
constval_opt: '=' constval | /* empty */;
constval: signedval | STRING| HEXCOLOR | IDENT;
signedval: mondadic_opt length | monadic_opt NUMBER;
length: LENGTH | EMS | NCHARS;
priority_opt: IMPORTANT | LEGAL STRING | /* empty */;
property: propname '=' value | propname op_eq value;
propname: IDENT;
value: mondaic_opt term more_terms;
more_terms: more_terms op monadic_opt term | /* empty */;
term: length | STRING | HEXCOLOR | NUMBER | IDENT | attref | propref |
    ENVVAR | '( value ');
attref: '[' attrname ']';
propref: propname;
monadic_opt: '+' | '-' | /* empty */;
op: '+' | '-' | '*' | '/' | INTERPLATEHI | INTERPOLATELO | /* empty */;
op_eq: PLUS_EQ | MINUS_EQ | STAR_EQ | SLASH_EQ;

Yacc grammar, level 1

Level 1 is a simplified version of level 2. It could be shortened even more, when some rules were rewritten.
stylesheet: imports decls rules;
imports: imports IMPORT url;
url: STRING;
decls: archform_decl | /* empty */;
archform_decl: ARCHFORM attrname;
attrname: IDENT;
rules: rule_seq;
rule_seq: rule_seq rule | /* empty */;
rule: address address_list '{' property property_list '}' priority_opt;
address_list: address_list ',' address | /* empty */;
address: toplevel | ancestors elemspec;
toplevel: '*';
ancestors: ancestors ancestor | /* empty */;
ancestor: '(' elemspec ')';
elemname: IDENT | IDENT '.' IDENT;
elemspec: elemname;
length: LENGTH | EMS | NCHARS;
priority_opt: IMPORTANT | LEGAL STRING | /* empty */;
property: propname '=' value;
propname: IDENT;
value: mondaic_opt term more_terms;
more_terms: more_terms op monadic_opt term | /* empty */;
term: length | STRING | HEXCOLOR | NUMBER | IDENT | attref | propref |
    ENVVAR | '( value ');
attref: '[' attrname ']';
propref: propname;
monadic_opt: '+' | '-' | /* empty */;
op: /* empty */;

Lexical scanner

The lexical scanner needs some more patterns (at least for level 2):
"!legal"	   return LEGAL;
"!important"	   return IMPORTANT;
"$"{ident}	   {yylval.string = yytext; return ENVVAR;}
{number}{w}d	   |
{number}{w}day	   |
{number}{w}days	   {yylval.number = atof(yytext) * DAY; return NUMBER;}
{number}{w}w	   |
{number}{w}week	   |
{number}{w}weeks   {yylval.number = atof(yytext) * WEEK; return NUMBER;}
{number}{w}h	   |
{number}{w}hour	   |
{number}{w}hours   {yylval.number = atof(yytext) * HOUR; return NUMBER;}
{number}{w}m	   |
{number}{w}min	   |
{number}{w}minute  |
{number}{w}minutes {yylval.number = atof(yytext) * MINUTE; return NUMBER;}
{number}{w}s	   |
{number}{w}sec	   |
{number}{w}second  |
{number}{w}seconds {yylval.number = atof(yytext) * SECOND; return NUMBER;}
"--"(.|\n)*"--"	   { /* ignore comments */}
assuming C macros similar to these:
#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 ... some amount of pixels...
#define PICA (12 * INCH/72 * MM)
#define POINT (INCH/72 * MM)

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

Through www-style@w3.org and other electronic media, these people have actively contributed: Also, thanks to Tim Berners-Lee, Vincent Quint, Cécile Roisin, Irène Vatton, Phill Hallam-Baker, Terry Allen and Jon Smirl for constructive discussions. A special thanks goes to Dave Raggett for his encouragement, suggestions and work on HTML3.

Appendix A: Sketches of level 2

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

Attribute-based addressing

The CLASS attribute has been added to the HTML3 specifications with style sheets in mind, and enjoys a special shorthand notation as described above. Also, other attributes/values be used in addressing:
  A[HREF] { text-color = red }          -- the HREF attribute exists --
  H1[CLASS = huge] { font-size = 60pt } -- another way of writing H1.huge --

Sequential patterns

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

  /H1/ P { font-weight = bold }
The '/' indicates the start of a sequential pattern search. All property assignments are performed on the last element of the search pattern.

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

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

Multiple media

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

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

  :paper:
    H1 { font-size = 24pt }

  :overhead:
    h1 { font-size = 60pt }

Constraints and environment variables

[interesting, but potentially complex issue]

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

The following two are only defined inside an element that contains a hyperlink: One could then change the color of a hyperlink with:
  a[href] { text-color = dark-red << $LASTVISIT/30d >> dark-blue }
The combination of constraints and environment variables can be quite interesting. Set the left margin to be 1/10 of the window width, but always more than 2em and less than 20em:
  * { margin-left =  2em << $WIDTH/10 >> 20em }
Let the color of the background fade from white to yellow as the document ages. After two days (2d), the fading process is complete:
  * { color-background = white << $AGE/2d >> yellow }
Let the color of text links change from red to blue as the document loads:
  * { text-link = red << $FETCHED >> blue }

Addressing environment properties

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

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

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

  $HTML-SOURCE { font-family = courier, font-size = 12pt }
  $CLIENT-WINDOW { width = 600px, height = 800px }
  $CLIENT-WINDOW { font-family = helvetica }
  $HTML_ERROR { text-color = yellow, text-background = red }
An initial '$' marks environment elements.

Constants

  @define myred = 0.8, 0.1, 0.1

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

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

Arithmetic

Addition, subtraction, multiplication and division are supported.

Relative values

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

Appendix B: Suggested level 2 properties

border-style (or box-style)

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

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

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

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

border-width (or box-width)

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

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

The box is drawn inside the space set by the margins.

border-color (or box-color)

Value: <color> | <uri>
Initial: inherited (init: appl. dep.)
Level: 2
Example: border-color = "http://www.pat.com/pats/concrete.gif";

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

border-background (or box-background)

Value: <color> | <uri>
Initial: none
Level: 2
Example: border-background = yellow

A new one. I thought that maybe it wasn't such a good idea to let text-background do double duty. If this is accepted, then border-style `none' means: neither border nor background.

display

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

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

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

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

replace

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

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

height

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

Only applies to inline images and other insertions.

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

insert.before, insert.after

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

Uses alternate properties. Note that the string can be an expression:

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

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

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

Various non-sorted properties

List Numbering

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

[Needs some work, level 2 issue?]

Tables

[Level 2 issue]

Math

[Level 2+ issue]