CSS Syntax Module Level 3

[LONGSTATUS] [DATE]

This version:
http://dev.w3.org/csswg/css3-syntax/
Editor's draft:
http://dev.w3.org/csswg/css3-syntax/
Previous version:
http://www.w3.org/TR/2003/WD-css3-syntax-20030813/
Issue Tracking:
W3C Bugzilla
Feedback:
www-style@w3.org with subject line “[css3-syntax] … message topic …
Editors:
(Google, Inc.),

Abstract

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, in speech, etc. This module describes, in general terms, the basic structure and syntax of CSS stylesheets. It defines, in detail, the syntax and parsing of CSS - how to turn a stream of bytes into a meaningful stylesheet.

Status of this document

The following features are at risk: …

Table of contents

Introduction

This section is not normative.

Provide background, motivation, etc.

Module interactions

This module defines the syntax and parsing of CSS stylesheets. It supersedes the lexical scanner and grammar defined in CSS 2.1.

Description of CSS's Syntax

This section is not normative.

A CSS document is a series of rules, which apply CSS properties to elements in the source document, and at-rules, which define special processing rules or values for the CSS document.

A rule starts with a selector (defined by the Selectors specification), then has a {}-wrapped block containing a sequence of declarations. The selector specifies which elements the declarations will apply to. Each declaration has a property name, followed by a colon and the property value, and finished with a semicolon.

A typical rule might look something like this:

p > a { 
	color: blue;
	text-decoration: underline;
}

In the above rule, "p > a" is the selector, which, if the source document is HTML, selects any <a> elements that are children of a <p> element.

"color: blue;" is a declaration specifying that, for the elements that match the selector, their 'color' property should have the value ''blue''. Similiarly, their 'text-decoration' property should have the value ''underline''.

At-rules are all different, but they have a basic structure in common. They start with an "@" character followed by their name. Some at-rules are simple statements, with their name followed by more CSS values to specify their behavior, and finally ended by a semicolon. Others are blocks; they can have CSS values following their name, but they end with a {}-wrapped block, similar to a rule. Even the contents of these blocks are specific to the given at-rule: sometimes they contain a sequence of declarations, like a rule; other times, they may contain additional blocks, or at-rules, or other structures altogether.

Here are several examples of at-rules that illustrate the varied syntax they may contain.

@import "my-styles.css";

The ''@import'' at-rule is a simple statement. After its name, it takes a single string or ''url()'' function to indicate the stylesheet that it should import.

@page :left {
	margin-left: 4cm;
	margin-right: 3cm;
}

The ''@page'' at-rule consists of an optional page selector (the ":left" pseudoclass), followed by a block of properties that apply to the page when printed. In this way, it's very similar to a normal rule, except that its properties don't apply to any "element", but rather the page itself.

@media print {
	body { font-size: 10pt }
}

The ''@media'' at-rule begins with a media type and a list of optional media queries. Its block contains entire rules, which are only applied when the ''@media''s conditions are fulfilled.

Property names and at-rule names are always identifiers, which have to start with a letter or a hyphen followed by a letter, and then can contain letters, numbers, hyphens, or underscores. You can include any character at all, even ones that CSS uses in its syntax, by escaping it with a backslash (\) or by using a hexadecimal escape.

The syntax of selectors is defined in the Selectors spec. Similarly, the syntax of the wide variety of CSS values is defined in the Values & Units spec. The special syntaxes of individual at-rules can be found in the specs that define them.

Parsing

User agents must use the parsing rules described in this section to generate the CSSOM trees from text/css resources. Together, these rules define what is referred to as the CSS parser.

This specification defines the parsing rules for CSS documents, whether they are syntactically correct or not. Certain points in the parsing algorithm are said to be parse errors. The error handling for parse errors is well-defined: user agents must either act as described below when encountering such problems, or must abort processing at the first error that they encounter for which they do not wish to apply the rules described below.

Conformance checkers must report at least one parse error condition to the user if one or more parse error conditions exist in the document and must not report parse error conditions if none exist in the document. Conformance checkers may report more than one parse error condition if more than one parse error condition exists in the document. Conformance checkers are not required to recover from parse errors.

Overview of the Parsing Model

The input to the CSS parsing process consists of a stream of Unicode code points, which is passed through a tokenization stage followed by a tree construction stage. The output is a CSSStyleSheet object.

Implementations that do not support scripting do not have to actually create a CSSOM CSSStyleSheet object, but the CSSOM tree in such cases is still used as the model for the rest of the specification.

The input byte stream

The stream of Unicode code points that comprises the input to the tokenization stage will be initially seen by the user agent as a stream of bytes (typically coming over the network or from the local file system). The bytes encode the actual characters according to a particular character encoding, which the user agent must use to decode the bytes into characters.

The encoding sniffing algorithm defined below is used to determine the character encoding.

Given an encoding, the bytes in the input byte stream must be converted to Unicode code points for the tokenizer's input stream, as described by the rules for that encoding, except that the leading U+FEFF BYTE ORDER MARK character, if any, must not be stripped by the encoding layer (it is stripped by the rule below).

Bytes or sequences of bytes in the original byte stream that could not be converted to Unicode code points must be converted to U+FFFD REPLACEMENT CHARACTERs. Specifically, if the encoding is UTF-8, the bytes must be decoded with the error handling defined in this specification.

Bytes or sequences of bytes in the original byte stream that did not conform to the encoding specification (e.g. invalid UTF-8 byte sequences in a UTF-8 input byte stream) are errors that conformance checkers are expected to report.

Determining the character encoding

General algorithm:

  1. If the stylesheet is embedded, the charset is the charset of the outer document.
  2. If the resource carried a Charset header, and the value of the header is a valid charset, that's the charset of the stylesheet.
  3. If the document contains an @charset rule at the very top (specify how to parse this in the presence of arbitrary charsets) and it specifies a valid charset, that's the charset of the stylesheet.
  4. The charset is UTF-8.

Preprocessing the input stream

The input stream consists of the characters pushed into it as the input byte stream is decoded.

One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present in the input stream.

The requirement to strip a U+FEFF BYTE ORDER MARK character regardless of whether that character was used to determine the byte order is a willful violation of Unicode, motivated by a desire to increase the resilience of user agents in the face of naïve transcoders.

U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. All CR characters must be converted to LF characters, and any LF characters that immediately follow a CR character must be ignored. Thus, newlines in CSS stylesheets are represented by LF characters, and there are never any CR characters in the input to the tokenization stage.

The next input character is the first character in the input stream that has not yet been consumed or explicitly ignored by the requirements in this section. Initially, the next input character is the first character in the input. The current input character is the last character to have been consumed.

The "EOF" character in the tables below is a conceptual character representing the end of the input stream.

Parse State

...

Tokenization

Implementations must act as if they used the following state machine to tokenize CSS. The state machine must start in the data state. Most states consume a single character, which may have various side-effects, and either switches the state machine to a new state to reconsume the same character, or switches it to a new state to consume the next character, or stays in the same state to consume the next character. Some states have more complicated behavior and can consume several characters before switching to another state.

The output of the tokenization step is a series of zero or more of the following tokens: identifier, function, at-keyword, hash, string, bad-string, url, bad-url, delim, number, percentage, dimension, unicode-range, whitespace, cdo, cdc, colon, semicolon, [, ], (, ), {, }.

Identifier, function, at-keyword, hash, string, and url tokens have a value composed of zero or more characters. Delim tokens have a value composed of a single character. Number, percentage, and dimension tokens have a representation composed of 1 or more character, a numeric value, and a type flag set to either "integer" or "number". The type flag defaults to "integer" if not otherwise set. Dimension tokens additionally have a unit composed of one or more characters. Unicode-range tokens have a range of characters.

The tokenizer state machine consists of the states defined in the following subsections.

Tokenizer Flags

The tokenizer can be run with any of several flags that alter its behavior.

the supports scientific notation flag
This flag is set if the tokenizer supports scientific notation in numbers. When this is set, a sequence of characters like "12e3" will tokenize as a number token with the value "12000". (Without the flag, they would tokenize as a dimension token with value "12" and unit "e3".)

Currently, this flag is only set when parsing SVG presentational attributes.

the transform function whitespace flag
This flag is set when parsing SVG's transform attribute. When this is set, whitespace is allowed between the name of a transform function and its opening parenthesis.

Definitions

This section defines several terms used during the tokenization phase.

digit
A character between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
hex digit
A digit, or a character between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F), or a character between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
uppercase letter
A character between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
lowercase letter
A character between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
letter
An uppercase letter or a lowercase letter.
non-ASCII character
A character with a codepoint equal to or greater than U+00A0 NO-BREAK SPACE.
name-start character
A letter, a non-ASCII character, or U+005F LOW LINE (_).
name character
A name-start character, A digit, or U+002D HYPHEN-MINUS (-).
non-printable character
A character between U+0000 NULL and U+0008 BACKSPACE or a character between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE or a character between U+007F DELETE and U+009F APPLICATION PROGRAM COMMAND.
newline
U+000A LINE FEED or U+000C FORM FEED. Note that U+000D CARRIAGE RETURN is not included in this definition, as it is removed from the stream during preprocessing.
whitespace
A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
maximum allowed codepoint
The greatest codepoint defined by Unicode. This is currently U+10FFFF.

Data state

Consume the next input character.

whitespace
Consume as much whitespace as possible. Emit a whitespace token. Remain in this state.
U+0022 QUOTATION MARK (")
Switch to the double-quote-string state.
U+0023 NUMBER SIGN (#)
Switch to the hash state.
U+0027 APOSTROPHE (')
Switch to the single-quote-string state.
U+0028 LEFT PARENTHESIS (()
Emit a ( token. Remain in this state.
U+0029 RIGHT PARENTHESIS ())
Emit a ) token. Remain in this state.
U+002B PLUS SIGN (+)
If the next input character is a digit, or the next 2 input characters are U+002E FULL STOP (.) followed by a digit, switch to the number state. Reconsume the current input character.

Otherwise, emit a delim token with its value set to U+002B PLUS SIGN (+). Remain in this state.

U+002D HYPHEN-MINUS (-)
If the next 2 input characters are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them, emit a CDC token, and remain in this state.

Otherwise, if the next input character is a digit, or the next 2 input characters are U+002E FULL STOP (.) followed by a digit, switch to the number state. Reconsume the current input character.

Otherwise, if the next input character is a name-start character, switch to the identifier state. Reconsume the current input character.

Otherwise, emit a delim token with its value set to U+002D HYPHEN-MINUS (-). Remain in this state.

U+002E FULL STOP (.)
If the next input character is a digit, switch to the number state. Reconsume the current input character.

Otherwise, emit a delim token with its value set to U+002E FULL STOP (.). Remain in this state.

U+002F SOLIDUS (/)
If the next input character is U+002A ASTERISK (*), consume it and switch to the comment state.

Otherwise, emit a delim token with its value set to U+002F SOLIDUS (/). Remain in this state.

U+003A COLON (:)
Emit a colon token. Remain in this state.
U+003B SEMICOLON (;)
Emit a semicolon token. Remain in this state.
U+003C LESS-THAN SIGN (<)
If the next 3 input characters are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), consume them and emit a cdo token. Remain in this state.

Otherwise, emit a delim token with its value set to U+003C LESS-THAN SIGN (<). Remain in this state.

U+0040 COMMERCIAL AT (@)
Switch to the at-keyword state.
U+005B LEFT SQUARE BRACKET ([)
Emit a [ token. Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, this is a parse error. Emit a delim token with its value set to U+005C REVERSE SOLIDUS (\). Remain in this state.

Otherwise, switch to the identifier state. Reconsume the current input character.

U+005D RIGHT SQUARE BRACKET (])
Emit a ] token. Remain in this state.
U+007B LEFT CURLY BRACKET ({)
Emit a [ token. Remain in this state.
U+007D RIGHT CURLY BRACKET (})
Emit a } token. Remain in this state.
digit
Switch to the number state. Reconsume the current input character.
U+0055 LATIN CAPITAL LETTER U (U)
U+0075 LATIN SMALL LETTER U (u)
If the next 2 input character are U+002B PLUS SIGN (+) followed by a hex digit, consume the next input character. Note: don't consume both of them. Switch to the unicode-range state.

Otherwise, if the next 3 input characters are U+0052 LATIN CAPITAL LETTER R (R) or U+0072 LATIN SMALL LETTER R (r) followed by U+004C LATIN CAPITAL LETTER L (L) or U+006C LATIN SMALL LETTER L (l) followed by U+0028 LEFT PARENTHESIS ((), consume them. Switch to the url state.

Otherwise, switch to the identifier state. Reconsume the current input character.

name-start character
Switch to the identifier state. Reconsume the current input character.
EOF
Emit an end-of-file token.
anything else
Emit a delim token with its value set to the current input character. Remain in this state.

Double-quote-string state

If a string token has not yet been created since entering this state, create a string token with its value initially set to the empty string.

Consume the next input character.

U+0022 QUOTATION MARK (")
Emit the string token. Return to the data state.
EOF
This is a parse error. Emit the string token. Switch to the data state. Reconsume the current input character.
newline
This is a parse error. Emit a bad-string token. Switch to the data state. Reconsume the current input character.
U+005C REVERSE SOLIDUS (\)
If the next input character is an EOF, this is a parse error. Emit a bad-string token, then switch to the data state.

Otherwise, if the next input character is a newline, consume it. Remain in this state.

Otherwise, consume an escaped character. Append the returned character to the string token's value. Remain in this state.

anything else
Append the current input character to the string token's value. Remain in this state.

Single-quote-string state

If a string token has not yet been created since entering this state, create a string token with its value initially set to the empty string.

Consume the next input character.

U+0027 APOSTROPHE (')
Emit the string token. Return to the data state.
EOF
This is a parse error. Emit the string token. Switch to the data state. Reconsume the current input character.
newline
This is a parse error. Emit a bad-string token. Switch to the data state. Reconsume the current input character.
U+005C REVERSE SOLIDUS (\)
If the next input character is an EOF, this is a parse error. Emit a bad-string token, then switch to the data state.

Otherwise, if the next input character is a newline, consume it. Remain in this state.

Otherwise, consume an escaped character. Append the returned character to the string token's value. Remain in this state.

anything else
Append the current input character to the string token's value. Remain in this state.

Hash state

Consume the next input character.

name character
Create a hash token with its value set to the current input character. Switch to the hash-rest state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit a delim token with its value set to U+0023 NUMBER SIGN (#). Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Create a hash token with its value set to the returned character. Switch to the hash-rest state.

anything else
Emit a delim token with its value set to U+0023 NUMBER SIGN (#). Switch to the data state. Reconsume the current input character.

Hash-rest state

Consume the next input character.

name character
Append the current input character to the hash token's value. Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit the hash token. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Append the returned character to the hash token's value. Remain in this state.

anything else
Emit the hash token. Switch to the data state. Reconsume the current input character.

Comment state

Consume the next input character.

U+002A ASTERISK (*)
If the next input character is U+002F SOLIDUS (/), consume it, and switch to the data state.

Otherwise, do nothing and remain in this state.

EOF
This is a parse error. Switch to the data state. Reconsume the current input character.
anything else
Do nothing and remain in this state.

At-keyword state

Consume the next input character.

U+002D HYPHEN-MINUS (-)
If the next input character is a name-start character, consume it. Create an at-keyword token with its value set to U+002D HYPHEN-MINUS followed by the current input character. Switch to the at-keyword-rest state.

Otherwise, emit a delim token with its value set to U+0040 COMMERCIAL AT (@). Switch to the data state. Reconsume the current input character.

name-start character
Create an at-keyword token with its value set to the current input character. Switch to the at-keyword-rest state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit a delim token with its value set to U+0040 COMMERCIAL AT (@). Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Create an at-keyword token with its value set to the returned character. Switch to the at-keyword-rest state.

anything else
Emit a delim token with its value set to U+0040 COMMERCIAL AT (@). Switch to the data state. Reconsume the current input character.

At-keyword-rest state

Consume the next input character.

name character
Append the current input character to the at-keyword token's value. Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit the at-keyword token. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Append the returned character to the at-keyword token's value. Remain in this state.

anything else
Emit the at-keyword token. Switch to the data state. Reconsume the current input character.

Identifier state

Consume the next input character.

U+002D HYPHEN-MINUS (-)
If the next input character is a name-start character, create an identifer token with its value initially set to U+002D HYPHEN-MINUS. Switch to the identifier-rest state.

Otherwise, switch to the data state. Reconsume the current input character.

name-start character
Create an identifier token with its value set to the current input character. Switch to the identifier-rest state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Create an identifier token with its value set to the returned character. Switch to the identifier-rest state.

anything else
Switch to the data state. Reconsume the current input character.

Identifier-rest state

Consume the next input character.

name character
Append the current input character to the identifier token's value. Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit the identifier token. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Append the returned character to the identifier token's value. Remain in this state.

U+0028 LEFT PARENTHESIS (()
Emit a function token with its value set to the identifer token's value. Switch to the data state.
whitespace
If the transform function whitespace flag is set, switch to the transform-function-whitespace state.

Otherwise, emit the identifier token. Switch to the data state. Reconsume the current input character.

anything else
Emit the identifier token. Switch to the data state. Reconsume the current input character.

Transform-function-whitespace state

Consume the next input character.

whitespace
Remain in this state.
U+0028 LEFT PARENTHESIS (()
Emit a function token with its value set to the identifer token's value. Switch to the data state.
anything else
Emit the identifier token. Switch to the data state. Reconsume the current input character.

Number state

Create a number token with its representation initially set to the empty string.

Consume the next input character.

U+002D HYPHEN-MINUS (-)
If the next input character is a digit, consume it. Append U+002D HYPHEN-MINUS (-) to the number token's representation. Append the digit to the number token's representation. Switch to the number-rest state.

Otherwise, if the next 2 input characters are U+002E FULL STOP followed by a digit, consume them. Append U+002D HYPHEN-MINUS (-) to the number token's representation. Append U+002E FULL STOP (.) to the number token's representation. Append the digit to the number token's representation. Switch to the number fraction state.

Otherwise, switch to the data state. Reconsume the current input character.

U+002B PLUS SIGN (+)
If the next input character is a digit, consume it. Append U+002D PLUS SIGN (+) to the number token's representation. Append the digit to the number token's representation. Switch to the number-rest state.

Otherwise, if the next 2 input characters are U+002E FULL STOP followed by a digit, consume them. Append U+002D PLUS SIGN (+) to the number token's representation. Append U+002E FULL STOP (.) to the number token's representation. Append the digit to the number token's representation. Switch to the number fraction state.

Otherwise, switch to the data state. Reconsume the current input character.

digit
Append the current input character to the number token's representation. Switch to the number-rest state.
U+002E FULL STOP (.)
If the next input character is a digit, consume it. Append U+002E FULL STOP (.) to the number token's representation. Append the digit to the number token's representation. Switch to the number-fraction state.

Otherwise, switch to the data state. Reconsume the current input character.

anything else
Switch to the data state. Reconsume the current input character.

Number-rest state

Consume the next input character.

digit
Append the current input character to the number token's representation. Remain in this state.
U+002E FULL STOP (.)
If the next input character is a digit, consume it. Append U+002E FULL STOP (.) followed by the digit to the number token's representation. Switch to the number-fraction state.

Otherwise, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

U+0025 PERCENT SIGN
Emit a percent token with its value set to the number produced by interpreting the number token's representation as a base-10 number. Switch to the data state. Reconsume the current input character.
U+0045 LATIN CAPITAL LETTER E (E)
U+0065 LATIN SMALL LETTER E (e)
If the parser doesn't support scientific notation, create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.

Otherwise, if the next input character is a digit, or the next 2 input characters are U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-) followed by a digit, consume them and append them to the number token's representation. switch to the sci-notation state.

Otherwise, create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.

U+002D HYPHEN-MINUS (-)
If the next input character is a name-start character, consume it. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to U+002D HYPHEN-MINUS followed by the name-start character. Switch to the dimension state.

Otherwise, if the next 2 input characters are U+005C REVERSE SOLIDUS (\) followed by a newline, or U+005C REVERSE SOLIDUS (\) followed by EOF, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

Otherwise, if the next input character is U+005C REVERSE SOLIDUS (\), consume it, then consume an escaped character. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to U+002D HYPHEN-MINUS followed by the returned character. Switch to the dimension state.

Otherwise, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

name-start character
Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the returned character. Switch to the dimension state.

anything else
Emit a number token with its value set to the number produced by interpreting the string token's value as a base-10 number. Switch to the data state. Reconsume the current input character.

Number-fraction state

Set the number token's type flag to "number".

Consume the next input character.

digit
Append the current input character to the string token's value. Remain in this state.
U+002E FULL STOP (.)
Set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.
U+0025 PERCENT SIGN
Emit a percent token with its value set to the number produced by interpreting the number token's representation as a base-10 number. Switch to the data state. Reconsume the current input character.
U+0045 LATIN CAPITAL LETTER E (E)
U+0065 LATIN SMALL LETTER E (e)
If the parser doesn't support scientific notation, create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.

Otherwise, if the next input character is a digit, or the next 2 input characters are U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-) followed by a digit, consume them and append them to the number token's representation. switch to the sci-notation state.

Otherwise, create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.

U+002D HYPHEN-MINUS (-)
If the next input character is a name-start character, consume it. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to U+002D HYPHEN-MINUS followed by the name-start character. Switch to the dimension state.

Otherwise, if the next 2 input characters are U+005C REVERSE SOLIDUS (\) followed by a newline, or U+005C REVERSE SOLIDUS (\) followed by EOF, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

Otherwise, if the next input character is U+005C REVERSE SOLIDUS (\), consume it, then consume an escaped character. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to U+002D HYPHEN-MINUS followed by the returned character. Switch to the dimension state.

Otherwise, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

name-start character
Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the current input character. Switch to the dimension state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, set the number token's value to the number produced by interpreting the number token's representation as a base-10 number and emit it. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Create a dimension token with its representation set to the number token's representation, its value set to the number produced by interpreting the number token's representation as a base-10 number, and a unit initially set to the returned character. Switch to the dimension state.

anything else
Emit a number token with its value set to the number produced by interpreting the string token's value as a base-10 number. Switch to the data state. Reconsume the current input character.

Dimension state

Consume the next input character.

name character
Append the current input character to the dimension token's unit. Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is a newline or EOF, emit the dimension token. Switch to the data state. Reconsume the current input character.

Otherwise, consume an escaped character. Append the returned character to the dimension token's unit.

anything else
Emit the dimension token. Switch to the data state. Reconsume the current input character.

Sci-notation state

Consume the next input character.

digit
Append the current input character to the number token's representation. Remain in this state.
anything else
Let base be the result of interpreting the portion of the number token's representation preceding the U+0045 LATIN CAPITAL LETTER E (E) or U+0065 LATIN SMALL LETTER E (e) as a base-10 number.

Let power be the result of interpreting the portion of the number token's representation following the U+0045 LATIN CAPITAL LETTER E (E) or U+0065 LATIN SMALL LETTER E (e) as a base-10 number.

Set the number token's value to base * 10power. If the number token's value is not an integer, set the number token's type flag to "number". Emit the number token. Switch to the date state. Reconsume the current input character.

URL state

Consume the next input character.

U+0022 QUOTATION MARK (")
Switch to the url-double-quote state.
U+0027 APOSTROPHE (')
Switch to the url-single-quote state.
U+0029 RIGHT PARENTHESIS ())
Emit a url token with its value set to the empty string. Switch to the data state.
whitespace
Remain in this state.
anything else
Switch to the url-unquoted state. Reconsume the current input character.

URL-double-quote state

If a url token has not yet been created since entering this state, create a url token with its value initially set to the empty string.

Consume the next input character.

U+0022 QUOTATION MARK (")
Switch to the url-end state.
newline
This is a parse error. Switch to the bad-url state.
U+005C REVERSE SOLIDUS (\)
If the next input character is EOF, this is a parse error. Emit a bad-url token. Switch to the data state. Reconsume the current input character.

Otherwise, if the next input character is a newline, consume it and remain in this state.

Otherwise, consume an escaped character. Append the returned character to the url token's value. Remain in this state.

anything else
Append the current input character to the url token's value. Remain in this state.

URL-single-quote state

If a url token has not yet been created since entering this state, create a url token with its value initially set to the empty string.

Consume the next input character.

U+0027 APOSTROPHE (')
Switch to the url-end state.
newline
This is a parse error. Switch to the bad-url state.
U+005C REVERSE SOLIDUS (\)
If the next input character is EOF, this is a parse error. Emit a bad-url token. Switch to the data state. Reconsume the current input character.

Otherwise, if the next input character is a newline, consume it and remain in this state.

Otherwise, consume an escaped character. Append the returned character to the url token's value. Remain in this state.

anything else
Append the current input character to the url token's value. Remain in this state.

URL-end state

Consume the next input character.

whitespace
Remain in this state.
U+0029 RIGHT PARENTHESIS ())
Emit the url token. Switch to the data state.
anything else
This is a parse error. Switch to the bad-url state. Reconsume the current input character.

URL-unquoted state

If a url token has not yet been created since entering this state, create a url token with its value initially set to the empty string.

Consume the next input character.

whitespace
Switch to the url-end state.
U+0029 RIGHT PARENTHESIS ())
Emit the url token. Switch to the data state.
U+0022 QUOTATION MARK (")
U+0027 APOSTROPHE (')
U+0028 LEFT PARENTHESIS (()
non-printing character
This is a parse error. Switch to the bad-url state.
U+005C REVERSE SOLIDUS
If the next input character is a newline or EOF, this is a parse error. Switch to the bad-url state.

Otherwise, consume an escaped character. Append the returned character to the url token's value. Remain in this state.

anything else
Append the current input character to the url token's value. Remain in this state.

Bad-URL state

Consume the next input character.

U+0029 RIGHT PARENTHESIS ())
Emit a bad-url token. Switch to the data state.
U+005C REVERSE SOLIDUS
If the next input character is a newline or EOF, do nothing and remain in this state.

Otherwise, consume an escaped character. Remain in this state.

anything else
Do nothing. Remain in this state.

Unicode-range state

Create a new unicode-range token with an empty range.

Consume as many hex digits as possible, but no more than 6. If less than 6 hex digits were consumed, consume as many U+003F QUESTION MARK (?) characters as possible, but no more than enough to make the total of hex digits and U+003F QUESTION MARK (?) characters equal to 6.

If any U+003F QUESTION MARK (?) characters were consumed, first interpret the consumed characters as a hexadecimal number, with the U+003F QUESTION MARK (?) characters replaced by U+0030 DIGIT ZERO (0) characters. This is the start of the range. Then interpret the consumed characters as a hexadecimal number again, with the U+003F QUESTION MARK (?) character replaced by U+0046 LATIN CAPITAL LETTER F (F) characters. This is the end of the range. Set the unicode-range token's range, then emit it. Switch to the data state.

Otherwise, interpret the digits as a hexadecimal number. This is the start of the range.

Consume the next input character.

U+002D HYPHEN-MINUS (-)
If the next input character is a hex digit, consume as many hex digits as possible, but no more than 6. Interpret the digits as a hexadecimal number. This is the end of the range. Set the unicode-range token's range, then emit it. Switch to the data state.

Otherwise, set the unicode-range token's range and emit it. Switch to the data state. Reconsume the current input character.

anything else
Set the unicode-range token's range and emit it. Switch to the data state. Reconsume the current input character.

Consume an escaped character

This section describes how to consume an escaped character. It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and that the next input character has already been verified to not be a newline or EOF. It will return a character.

Consume the next input character.

hex digit
Consume as many hex digits as possible, but no more than 5. Note that this means 1-6 hex digits have been consumed in total. If the next input character is whitespace, consume it as well. Interpret the hex digits as a hexadecimal number. If this number is greater than the maximum allowed codepoint, return U+FFFD REPLACEMENT CHARACTER. Otherwise, return the character with that codepoint.
anything else
Return the current input character.

Set the unicode-range token's range

This section describes how to set a unicode-range token's range so that the range it describes is within the supported range of unicode characters.

It assumes that the start of the range has been defined, the end of the range might be defined, and both are non-negative integers.

If the start of the range is greater than the maximum allowed codepoint, the unicode-range token's range is empty.

If the end of the range is defined, and it is less than the start of the range, the unicode-range token's range is empty.

If the end of the range is not defined, the unicode-range token's range is the single character whose codepoint is the start of the range.

Otherwise, if the end of the range is greater than the maximum allowed codepoint, change it to the maximum allowed codepoint. The unicode-range token's range is all characters between the character whose codepoint is the start of the range and the character whose codepoint is the end of the range.

Changes from CSS 2.1 Tokenizer

This section is non-normative.

Here are the changes that I know that I've made to the tokenizer of 2.1. If there are changes not present here, please let me know as they may be unintentional.

Note that the point of this spec is to match reality; changes from CSS2.1's tokenizer are nearly always because the tokenizer specified something that doesn't match actual browser behavior, or left something unspecified. If some detail doesn't match browsers, please let me know as it's almost certainly unintentional.

  1. The DASHMATCH and INCLUDES tokens have been removed. They can instead be handled simply by having them parse as DELIM tokens. It was weird to privilege just those two types of attribute equality operators, when Selectors 3 adds several more.
  2. The BAD-URI token (now bad-url) is "self-contained". In other words, once the tokenizer realizes it's in a bad-url rather than a url token, it just seeks forward to look for the closing ), ignoring everything else. This behavior is simpler than treating it like a FUNCTION token and paying attention to opened blocks and such. Only WebKit exhibits this behavior, but it doesn't appear that we've gotten any compat bugs from it.
  3. The number, percentage, and dimension tokens have been changed to include the preceding +/- sign as part of their value (rather than as a separate DELIM token that needs to be manually handled every time the token is mentioned in other specs). The only consequence of this is that comments can no longer be inserted between the sign and the number.
  4. Several flags have been added for SVG-compatible tokenizing, so that a single state machine can be used for both "vanilla" and SVG CSS parsing.

Tree Construction

The input to the tree construction stage is a sequence of tokens from the tokenization stage. The output is a tree of items with a stylesheet at the root and all other nodes being at-rules, style rules, or declarations.

The construction of this stylesheet does not take into account unrecognized items, like unknown properties or at-rules. It simply produces a tree of rules according to the fundamental syntax of CSS. Unrecognized or misplaced rules are handled in the CSSOM Construction stage.

The items that can appear in the tree are a mixture of basic tokens and new objects:

stylesheet
A stylesheet has a value consisting of a list of at-rules and style rules.
at-rule
An at-rule has a name, a prelude consisting of a list of primitives, and a value consisting of a list of at-rules, style rules, or declarations.
style rule
A style rule has a selector consisting of a list of primitives, and a value consisting of a list of at-rules or declarations.
declaration
A declaration has a name and a value consisting of a list of primitives.
primitive
A primitive is one of the preserved tokens, a function, or a simple block.
preserved tokens
The tokens that can appear in the tree are: identifier, hash, string, url, delim, number, percentage, dimension, unicode-range, whitespace, cdo, cdc, colon, semicolon, at-keyword, ], ), and }.

This means that the following tokens emitted by the tokenizer stage will not appear in the stylesheet object: function, bad-string, bad-url, [, (, {. I need to make sure this is true.

function
A function has a name, and a list of arguments. Each argument is a list of primitives.
simple block
A simple block has an associated token (either a [, (, or { token) and a value consisting of a list of primitives.

TODO:

Definitions

current input token
The token currently being operated on, from the list of tokens produced by the tokenizer.
next input token
The token following the current input token in the list of tokens produced by the tokenizer. If there isn't a token following the current input token, the next input token is an EOF token.
stack of open rules
A stack of rules. This stack always contains the stylesheet object at the bottom of the stack, gains additional rules as block are opened, and loses them when blocks are closed.
current rule
The topmost rule in the stack of open rules.
current declaration
The declaration currently being built. There may or may not be a current declaration at any given time, but there is never more than one.
rule-filled
An at-rule that takes a block, and within that block accepts at-rules and/or style rules (which encompasses more than just style rules, such as keyframe rules), is called rule-filled. Examples of rule-filled at-rules are ''@media'' and ''@keyframes''.
declaration-filled
An at-rule that takes a block, and within that block accepts at-rules and/or declarations, is called declaration-filled. Examples of declaration-filled at-rules are ''@font-face'' and ''@page''.

Top-level mode

Consume the next input token.

cdo token
cdc token
whitespace token
Do nothing. Remain in this mode.
at-keyword token
Create an at-rule with its name set to the value of the current input token and push it onto the stack of open rules. Switch to the at-rule mode.
{ token
This is a parse error. Consume a primitive and ignore the return value. Remain in this state.
EOF token
Finish parsing.
anything else
Create a style rule and push it onto the stack of open rules. Switch to the selector mode. Reprocess the current input token.

At-rule mode

Consume the next input token.

semicolon token
Pop the current rule. Switch to the current rule's content mode.
{ token
If the current rule is rule-filled, switch to the rule mode.

Otherwise, if the current rule is declaration-filled, switch to the declaration mode.

Otherwise, this is a parse error. Discard the current rule. Switch to the next-block error mode. Reconsume the current input token.

EOF token
Finish parsing.
anything else
Consume a primitive and append the returned value to the prelude of the current rule. Remain in this mode.

Rule mode

Consume the next input token.

whitespace token
Do nothing, and remain in this state.
} token
Pop the current rule. Switch to the current rule's content mode.
at-keyword token
Create an at-rule with its name set to the value of the current input token and push it onto the stack of open rules. Switch to the at-rule mode.
EOF token
Finish parsing.
anything else
Create a style rule and push it onto the stack of open rules. Switch to the selector mode. Reprocess the current input token.

Selector mode

Consume the next input token.

{ token
Switch to the declaration mode.
EOF token
Discard the current rule. Finish parsing.
anything else
Consume a primitive and append the returned value to the selector of the current rule. Remain in this mode.

Declaration mode

Consume the next input token.

whitespace token
semicolon token
Do nothing. Remain in this mode.
} token
Pop the current rule. Switch to the current rule's content mode.
at-rule token
Create an at-rule with its name set to the value of the current input token and push it onto the stack of open rules. Switch to the at-rule mode.
ident token
Create a declaration with its name set to the value of the current input token. If the document is in quirks mode, and the value of the current input token matches one of the properties that support hashless hex colors, set the quirk-hashless flag. Otherwise, if the document is in quirks mode, and the value of the current input token matches one of the properties that support unitless lengths, set the quirk-unitless flag. Switch to the after-declaration-name mode.
EOF token
Finish parsing.
anything else
This is a parse error. Discard the current declaration. Switch to the next-declaration error mode.

After-declaration-name mode

Consume the next input token.

whitespace
Do nothing. Remain in this mode.
colon token
Do nothing. Switch to the declaration-value mode.
semicolon token
This is a parse error. Discard the current declaration. Switch to the current rule's content mode.
EOF token
Discard the current declaration. Finish parsing.
anything else
This is a parse error. Discard the current declaration. Switch to the next-declaration error mode.

Declaration-value mode

Consume the next input token.

delim token with a value of "!"
If the next input token is an identifier token with the value "important", consume it and set the important flag of the current declaration to true. Switch to the declaration-end mode.

This currently always parses !important at the end of a declaration as meaning that the declaration has its important flag set. It's not entirely clear yet that that's the behavior we want.

Otherwise, append the token to the value of the current declaration.

semicolon token
If the current declaration is grammatically valid, append it to the value of the current rule. Unset the quirk-hashless flag and the quirk-unitless flag. Switch to the current rule's content mode.
} token
If the current declaration is grammatically valid, append it to the value of the current rule. Pop the current rule. Unset the quirk-hashless flag and the quirk-unitless flag. Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
Consume a primitive and append the returned value to the value of the current declaration. Remain in this mode.

Declaration-end mode

Consume the next input token.

whitespace token
Do nothing. Remain in this mode.
semicolon token
If the current declaration is grammatically valid, append it to the value of the current rule. Unset the quirk-hashless flag and the quirk-unitless flag. Switch to the current rule's content mode.
} token
If the current declaration is grammatically valid, append it to the value of the current rule. Pop the current rule. Unset the quirk-hashless flag and the quirk-unitless flag. Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
This is a parse error. Discard the current declaration. Unset the quirk-hashless flag and the quirk-unitless flag. Switch to the next-declaration error mode.

Next-block error mode

Consume the next input token.

{ token
Consume a primitive. Ignore the return value. Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
Consume a primitive. Ignore the return value. Remain in this mode.

Next-declaration error mode

Consume the next input token.

semicolon token
Do nothing. Switch to the declaration mode.
} token
Do nothing. Switch to the declaration mode. Reprocess the current input token.
EOF token
Finish parsing.
anything else
Consume a primitive. Ignore the return value. Remain in this mode.

Consume a primitive

This section describes how to consume a primitive.

If the current input token is a {, [, or ( token, consume a simple block and return it.

Otherwise, if the current input token is a function token, consume a function and return it.

If the quirk-hashless flag is set, and the quirk-function flag is not set, run these steps:

  1. Let token be the current input token.

  2. Let value be the representation of token if token is a number token, the representation of token followed by the unit of token if token is a dimension token, or the value of token otherwise.

  3. If the following conditions are true, let token be a new hash token with its value set to value.

    • token is a number token, dimension token or identifier token.

    • value has a length that is 3 or 6.

    • value consists of only characters in the range [0-9A-Fa-f] (U+0030 to U+0039, U+0041 to U+0046, U+0061 to U+0066).

  4. Return token.

If the quirk-unitless flag is set, and the quirk-function flag is not set, run these steps:

  1. Let token be the current input token.

  2. If token is a number token, let token be a new dimension token with the representation set to token's representation, the value set to token's value, and the unit set to "px" (U+0070 U+0078).

  3. Return token.

Otherwise, return the current input token.

Consume a simple block

This section describes how to consume a simple block.

The ending token is the mirror variant of the current input token. (E.g. if it was called with [, the ending token is ].)

Create a simple block with its associated token set to the current input token. This is the current block.

Repeatedly consume the next input token and process it as follows:

EOF token
ending token
Return the block.
anything else
Consume a primitive and append the returned value to the value of the current block.

Consume a function

This section describes how to consume a function.

Create a function with a name equal to the value of the current input token. Create an argument, called the current argument, which is initially empty. If the quirk-hashless flag is set, or if the quirk-unitless flag is set and the value of the current input token is not "rect" (U+0072 U+0065 U+0063 U+0074), set the quirk-function flag.

Repeatedly consume the next input token and process it as follows:

EOF token
) token
Append the current argument to the function's argument list. Unset the quirk-function flag. Return the function.
delim token with the value ","
Append the current argument to the function's argument list. Create a new current argument which is initially empty.
anything else
Consume a primitive and append the returned value to the value of the current argument.

Switch to the current rule's content mode

This section describes how to switch to the current rule's content mode. It is invoked whenever a declaration or rule has been successfully completed, or when an error has finished recovery.

If the current rule is a style rule or a declaration-filled at-rule, switch to the declaration mode.

If the current rule is a rule-filled at-rule, switch to the rule mode.

If the current rule is a stylesheet, switch to the top-level mode.

Pop the current rule

This section describes how to pop the current rule. It is invoked whenever a rule is "finished" parsing and can be made part of its parent rule.

First, validate the current rule according to the appropriate grammar rules. If the rule does not match its required grammar, discard it.

Otherwise, pop the current rule from the stack of open rules and append it to the value of the new current rule.

Finish parsing

This section describes how to finish parsing. It is invoked whenever an EOF token is encountered.

If there is a current declaration, and it is grammatically valid, append it to the value of the current rule.

While there's more than one rule on the stack of open rules, pop the current rule.

Finally, return the current rule as the result of parsing.

Changes from CSS 2.1 Core Grammar

This section is non-normative.

Here are the changes that I know that I've made to the Core Grammar of 2.1. If there are changes not present here, please let me know as they may be unintentional.

Note that the point of this spec is to match reality; changes from CSS2.1's Core Grammar are nearly always because the Core Grammar specified something that doesn't match actual browser behavior, or left something unspecified. If some detail doesn't match browsers, please let me know as it's almost certainly unintentional.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [[!RFC2119]]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformance classes

Conformance to CSS TEMPLATE Module is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to CSS TEMPLATE Module if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to CSS TEMPLATE Module if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by CSS TEMPLATE Module by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to CSS TEMPLATE Module if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Experimental implementations

To avoid clashes with future CSS features, the CSS2.1 specification reserves a prefixed syntax for proprietary and experimental extensions to CSS.

Prior to a specification reaching the Candidate Recommendation stage in the W3C process, all implementations of a CSS feature are considered experimental. The CSS Working Group recommends that implementations use a vendor-prefixed syntax for such features, including those in W3C Working Drafts. This avoids incompatibilities with future changes in the draft.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group's website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

CR exit criteria

[Change or remove the following CR exit criteria if the spec is not a module, but, e.g., a Note or a profile. This text was decided on 2008-06-04.]

For this specification to be advanced to Proposed Recommendation, there must be at least two independent, interoperable implementations of each feature. Each feature may be implemented by a different set of products, there is no requirement that all features be implemented by a single product. For the purposes of this criterion, we define the following terms:

independent
each implementation must be developed by a different party and cannot share, reuse, or derive from code used by another qualifying implementation. Sections of code that have no bearing on the implementation of this specification are exempt from this requirement.
interoperable
passing the respective test case(s) in the official CSS test suite, or, if the implementation is not a Web browser, an equivalent test. Every relevant test in the test suite should have an equivalent test created if such a user agent (UA) is to be used to claim interoperability. In addition if such a UA is to be used to claim interoperability, then there must one or more additional UAs which can also pass those equivalent tests in the same way for the purpose of interoperability. The equivalent tests must be made publicly available for the purposes of peer review.
implementation
a user agent which:
  1. implements the specification.
  2. is available to the general public. The implementation may be a shipping product or other publicly available version (i.e., beta version, preview release, or “nightly build”). Non-shipping product releases must have implemented the feature(s) for a period of at least one month in order to demonstrate stability.
  3. is not experimental (i.e., a version specifically designed to pass the test suite and is not intended for normal usage going forward).

The specification will remain Candidate Recommendation for at least six months.

Acknowledgments

[acknowledgments]

References

Normative references

Other references

Index

Property index