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.
This module defines the abstract syntax and parsing of CSS stylesheets
and other things which use CSS syntax
(such as the HTML style attribute).
It defines algorithms for converting a stream of codepoints
(in other words, text)
into a stream of CSS tokens,
and then further into CSS objects
such as stylesheets, rules, and declarations.
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 style 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 style 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.
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 style 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 idents,
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.
Tokenizing and Parsing CSS
User agents must use the parsing rules described in this specifiction
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.
To decode the stream of bytes into a stream of characters,
UAs must follow these steps.
If HTTP or equivalent protocol defines an encoding (e.g. via the charset parameter of the Content-Type header),
get an encoding for the specified value.
If that does not return failure,
set encoding to the return value
and jump to the last step of this algorithm.
Check the byte stream. If the first several bytes match the hex sequence
40 63 68 61 72 73 65 74 20 22 (XX)* 22 3B
then get an encoding for the sequence of XX bytes,
decoded per windows-1252,
and let temp be the return value.
Note: Anything ASCII-compatible will do, so using windows-1252 is fine.
Note: The byte sequence above,
when decoded as ASCII,
is the string "@charset "…";",
where the "…" is the sequence of bytes corresponding to the encoding's name.
If temp is utf-16 or utf-16be,
set temp to utf-8.
If temp is not failure,
set encoding to it
and jump to the last step.
This mimics HTML <meta> behavior.
Get an encoding for the value of the charset attribute on the <link> element or <?xml-stylesheet?> processing instruction that caused the style sheet to be included, if any.
If that does not return failure,
set encoding to the return value
and jump to the last step.
Set encoding to the encoding of the referring style sheet or document,
if any.
Decode the byte stream using fallback encoding encoding.
Note: the decode algorithm lets the byte order mark (BOM) take precedence,
hence the usage of the term "fallback" above.
Anne says that steps 4/5 should be an input to this algorithm from the specs that define importing stylesheet,
to make the algorithm as a whole cleaner.
Perhaps abstract it into the concept of an "environment charset" or something?
Preprocessing the input stream
The input stream consists of the characters pushed into it as the input byte stream is decoded.
Before sending the input stream to the tokenizer,
implementations must make the following character substitutions:
Replace any U+000D CARRIAGE RETURN (CR) characters
or pairs of U+000D CARRIAGE RETURN (CR) followed by U+000A LINE FEED (LF)
by a single U+000A LINE FEED (LF) character.
Replace any U+0000 NULL characters with U+FFFD REPLACEMENT CHARACTER (�).
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.
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:
ident,
function,
at-keyword,
hash,
string,
bad-string,
url,
bad-url,
delim,
number,
percentage,
dimension,
unicode-range,
include-match,
dash-match,
prefix-match,
suffix-match,
substring-match,
whitespace,
cdo,
cdc,
colon,
semicolon,
[,
],
(,
),
{,
}.
ident, 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.
Several types of tokens that are guaranteed to be language-defined,
like at-keywords, functions, or dimension units,
are always lowercased when serialized.
Should we eagerly lowercase them in the parser,
or leave that to serialization to deal with?
(I slightly lean toward letting serialization deal with it,
so we don't mess with the capitalization of variable values.)
The tokenizer state machine consists of the states defined in the following subsections.
Token Railroad Diagrams
This section is non-normative.
This section presents an informative view of the token parser,
in the form of railroad diagrams.
Railroad diagrams are more compact than a state-machine,
but often easier to read than a regular expression.
These diagrams are informative and incomplete;
they describe the grammar of "correct" tokens,
but do not describe error-handling at all.
They are provided solely to make it easier to get an intuitive grasp of the syntax of each token.
escape
IDENT
FUNCTION
AT-KEYWORD
HASH
STRING
URL
NUMBER
DIMENSION
PERCENTAGE
UNICODE-RANGE
COMMENT
CDO
CDC
Tokenizer Flags
The tokenizer can be run with any of several flags that alter its behavior.
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+0080 <control>.
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.
Tokenizer State Machine
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+0024 DOLLAR SIGN ($)
If the next input character is
U+003D EQUALS SIGN (=),
consume it
and emit a suffix-match token.
Remain in this state.
Otherwise,
emit a delim token
with its value set to the current input character.
Remain in this 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+002A ASTERISK (*)
If the next input character is
U+003D EQUALS SIGN (=),
consume it
and emit a substring-match token.
Remain in this state.
Otherwise,
emit a delim token
with its value set to the current input character.
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,
switch to the ident state.
Reconsume the current input character.
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 ident state.
Reconsume the current input character.
U+005D RIGHT SQUARE BRACKET (])
Emit a ] token.
Remain in this state.
U+005E CIRCUMFLEX ACCENT (^)
If the next input character is
U+003D EQUALS SIGN (=),
consume it
and emit a prefix-match token.
Remain in this state.
Otherwise,
emit a delim token
with its value set to the current input character.
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
or U+003F QUESTION MARK (?),
consume the next input character.
Note: don't consume both of them.
Switch to the unicode-range state.
Otherwise,
switch to the ident state.
Reconsume the current input character.
name-start character
Switch to the ident state.
Reconsume the current input character.
U+007C VERTICAL LINE (|)
If the next input character is
U+003D EQUALS SIGN (=),
consume it
and emit a dash-match token.
Remain in this state.
Otherwise,
emit a delim token
with its value set to the current input character.
Remain in this state.
U+007E TILDE (~)
If the next input character is
U+003D EQUALS SIGN (=),
consume it
and emit an includes-match token.
Remain in this state.
Otherwise,
emit a delim token
with its value set to the current input character.
Remain in this state.
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,
Create an at-keyword token
with its value initially set to U+002D HYPHEN-MINUS.
Switch to the at-keyword-rest state.
Otherwise,
if the next two characters are
U+005C REVERSE SOLIDUS (\)
followed by anything but
a newline
or EOF,
create an at-keyword token
with its value initially set to U+002D HYPHEN-MINUS.
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.
Ident 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 ident-rest state.
Otherwise,
if the next two characters are
U+005C REVERSE SOLIDUS (\)
followed by anything but
a newline
or EOF,
create an identifer token
with its value initially set to U+002D HYPHEN-MINUS.
Switch to the ident-rest state.
Otherwise,
emit a delim token
with its value set to U+002D HYPHEN-MINUS (-).
Switch to the data state.
name-start character
Create an ident token
with its value set to the current input character.
Switch to the ident-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 ident token
with its value set to the returned character.
Switch to the ident-rest state.
Ident-rest state
Consume the next input character.
name character
Append the current input character
to the ident token's value.
Remain in this state.
U+005C REVERSE SOLIDUS (\)
If the next input character is
a newline or EOF,
emit the ident token.
Switch to the data state.
Reconsume the current input character.
Otherwise,
consume an escaped character.
Append the returned character to the ident token's value.
Remain in this state.
U+0028 LEFT PARENTHESIS (()
If the identifier token's value is
an ASCII case-insensitive match for "url",
switch to the url state.
Otherwise,
Emit a function token
with its value set to the identifier token's value.
Switch to the data state.
whitespace
If the transform function whitespace flag is set,
reconsume the current input character
and switch to the transform-function-whitespace state.
Otherwise,
emit the ident token.
Switch to the data state.
Reconsume the current input character.
anything else
Emit the ident token.
Switch to the data state.
Reconsume the current input character.
Transform-function-whitespace state
Consume the next input character.
whitespace
If the next input character is whitespace,
remain in this state.
Otherwise,
if the next input character is U+0028 LEFT PARENTHESES ((),
emit a function token
with its value set to the identifer token's value.
Switch to the data state.
Otherwise,
emit the identifer 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 percentage 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.
U+0045 LATIN CAPITAL LETTER E (E)
U+0065 LATIN SMALL LETTER E (e)
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+0025 PERCENT SIGN (%)
Emit a percentage 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.
U+0045 LATIN CAPITAL LETTER E (E)
U+0065 LATIN SMALL LETTER E (e)
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
Set the number token's type flag to "number".
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 data state.
Reconsume the current input character.
URL state
Consume the next input character.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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-printable 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.
EOF
This is a parse error.
Emit a bad-url token.
Switch to the data state.
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 zero,
or 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.
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.
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.
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.
Some flags have been added for SVG-compatible tokenizing,
so that a single state machine can be used for both "vanilla" and SVG CSS parsing.
Scientific notation is supported for numbers,
per WG resolution.
Parsing
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 component values,
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 component values,
and a value consisting of a list of at-rules or declarations.
declaration
A declaration has a name,
a value consisting of a list of component values,
and an important flag which is initially unset.
component value
A component value is one of the preserved tokens,
a function,
or a simple block.
preserved tokens
The tokens that can appear in the tree are:
ident,
hash,
string,
url,
delim,
number,
percentage,
dimension,
unicode-range,
whitespace,
colon,
semicolon,
at-keyword,
include-match,
dash-match,
prefix-match,
suffix-match,
and substring-match.
This means that the following tokens emitted by the tokenizer stage will not appear in the stylesheet object:
function,
bad-string,
bad-url,
cdo,
cdc,
[,
],
(,
),
{,
and }.
function
A function has a name,
and a list of arguments.
Each argument is a list of component values.
simple block
A simple block has an associated token (either a [, (, or { token)
and a value consisting of a list of component values.
When the parser is invoked,
it must be provided with a list of recognized at-rule names,
where each name is additionally associated with whether the at-rule is
rule-filled,
declaration-filled,
or neither.
TODO:
Handle the an+b production somehow.
Maybe just define it in property grammar terms?
This flag is set when the parser is invoked to consume just a set of declarations,
not any rules.
It causes the } token to be a syntax error,
rather than have special rule-closing behavior.
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.
reconsume the current input token
Push the current input token back onto the list of tokens produced by the tokenizer,
so that the next time a mode instructs you to consume the next input token,
it will instead reconsume the current input 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.
top-level rule
A rule is a top-level rule if the stack of open rules contains only it and the stylesheet object.
Otherwise, it is not a top-level rule.
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 is rule-filled
if it is in the list of recognized at-rules
and marked as such.
This type of at-rule may have a prelude,
and finishes with a block
which contains at-rules and/or style rules.
Examples of rule-filled at-rules are ''@media'' and ''@keyframes''.
declaration-filled
An at-rule is declaration-filled
if it is in the list of recognized at-rules
and marked as such.
This type of at-rule may have a prelude,
and finishes with a block
which contains at-rules and/or declarations.
Examples of declaration-filled at-rules are ''@font-face'' and ''@page''.
ASCII case-insensitive
When two strings are to be matched ASCII case-insensitively,
temporarily convert both of them to ASCII lower-case form
by adding 32 (0x20) to the value of each codepoint between
U+0041 LATIN CAPITAL LETTER A (A)
and U+005A LATIN CAPITAL LETTER Z (Z),
inclusive,
and then compare them on a codepoint-by-codepoint basis.
Parser State Machine
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-prelude 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.
Reconsume the current input token.
At-rule-prelude mode
Consume the next input token.
semicolon token
If the current rule is declaration-filled or rule-filled,
this is a parse error.
Discard the current rule.
Switch to the current rule's content mode.
Otherwise,
pop the current rule.
Switch to the current rule's content mode.
{ token
If the current rule is rule-filled,
switch to the rule-block mode.
Otherwise,
if the current rule is declaration-filled,
switch to the declaration-block mode.
Otherwise, this is a parse error.
Discard the current rule.
Consume a component value
and ignore the return value.
Switch to the current rule's content mode.
} token
If the current rule is a top-level rule,
this is a parse error.
Discard the current rule.
Switch to the next-block-or-statement error mode.
Reconsume the current input token.
Otherwise,
if the current rule is declaration-filled or rule-filled,
this is a parse error.
Discard the current rule.
Switch to the current rule's content mode.
Reconsume the current input token.
Otherwise,
pop the current rule.
Switch to the current rule's content mode.
Reconsume the current input token.
EOF token
If the current rule is declaration-filled or rule-filled,
this is a parse error.
Discard the current rule.
Finish parsing.
Otherwise,
finish parsing.
anything else
Consume a component value.
If anything was returned,
append the returned value
to the prelude of the current rule.
Remain in this mode.
Otherwise,
this is a parse error.
Discard the current rule.
If the current rule is declaration-filled or rule-filled,
switch to the next-block error mode;
otherwise,
switch to the next-block-or-statement error mode.
Reconsume the current input token.
Rule-block mode
Consume the next input token.
whitespace token
Do nothing.
Remain in this mode.
} 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-prelude 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.
Reconsume the current input token.
Selector mode
Consume the next input token.
{ token
Switch to the declaration-block mode.
} token
If the current rule is a top-level rule,
this is a parse error.
Discard the current rule.
Switch to the next-block error mode.
Reconsume the current input token.
Otherwise,
this is a parse error.
Discard the current rule.
Switch to the current rule's content mode.
Reconsume the current input token.
EOF token
This is a parse error.
Discard the current rule.
Finish parsing.
anything else
Consume a component value.
If anything was returned,
append the returned value
to the selector of the current rule.
Remain in this mode.
Otherwise,
this is a parse error.
Discard the current rule.
Switch to the next-block error mode.
Reconsume the current input token.
Declaration-block mode
Consume the next input token.
whitespace token
semicolon token
Do nothing.
Remain in this mode.
} token
If the only declarations flag is set
and the current rule is a top-level rule,
this is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
Otherwise,
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-prelude mode.
ident token
Create a declaration
with its name set to the value of the current input token.
Set it as the current declaration.
Switch to the after-declaration-name mode.
EOF token
Finish parsing.
anything else
This is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
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.
Unset the current declaration.
Switch to the current rule's content mode.
EOF token
Unset the current declaration.
Finish parsing.
anything else
This is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
Declaration-value mode
Consume the next input token.
delim token with a value of "!"
Switch to the declaration-important mode.
semicolon token
If the current declaration is grammatically valid,
append it to the value of the current rule.
Unset the current declaration.
Switch to the current rule's content mode.
} token
If the only declarations flag is set
and the current rule is a top-level rule,
this is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
Otherwise,
if the current declaration is grammatically valid,
append it to the value of the current rule.
Unset the current declaration.
Pop the current rule.
Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
If the quirks mode flag is set,
and the current declaration's name
is an ASCII case-insensitive match
for one of the property names on the hashless color quirk list,
consume a component value with the hashless color quirk.
If anything was returned,
append the returned value
to the value of the current declaration
and remain in this mode;
otherwise,
unset the current declaration
and switch to the next-declaration error mode.
Reconsume the current input token.
Otherwise,
if the quirks mode flag is set,
and the current declaration's name
is an ASCII case-insensitive match
for one of the property names on the unitless length quirk list,
consume a component value with the unitless length quirk.
If anything was returned,
append the returned value
to the value of the current declaration
and remain in this mode;
otherwise,
unset the current declaration
and switch to the next-declaration error mode.
Reconsume the current input token.
Otherwise,
consume a component value.
If anything was returned,
append the returned value
to the value of the current declaration
and remain in this mode;
otherwise,
unset the current declaration
and switch to the next-declaration error mode.
Reconsume the current input token.
Declaration-important mode
Consume the next input token.
whitespace token
Do nothing.
Remain in this mode.
ident token whose value is an ASCII case-insensitive match for "important"
Set the important flag of the current declaration to true.
Switch to the declaration-end mode.
anything else
This is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
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 current declaration.
Switch to the current rule's content mode.
} token
If the only declarations flag is set
and the current rule is a top-level rule,
this is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
Otherwise,
if the current declaration is grammatically valid,
append it to the value of the current rule.
Unset the current declaration.
Pop the current rule.Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
This is a parse error.
Unset the current declaration.
Switch to the next-declaration error mode.
Reconsume the current input token.
Next-block error mode
Consume the next input token.
{ token
Consume a component value.
Ignore the return value.
Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
Consume a component value.
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-block mode.
} token
If the only declarations flag is set
and the current rule is a top-level rule,
do nothing.
Remain in this mode.
Otherwise,
do nothing.
Switch to the declaration-block mode.
Reconsume the current input token.
EOF token
Finish parsing.
anything else
Consume a component value.
Ignore the return value.
Remain in this mode.
Next-block-or-statement error mode
Consume the next input token.
semicolon token
Do nothing.
Switch to the current rule's content mode.
{ token
Consume a component value.
Ignore the return value.
Switch to the current rule's content mode.
EOF token
Finish parsing.
anything else
Consume a component value.
Ignore the return value.
Remain in this mode.
Consume a component value
This section describes how to consume a component value.
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.
Otherwise, if the current input token
is an EOF token,
finish parsing.
Otherwise, if the current input token
is a cdo token,
cdc token,
} token,
] token,
) token,
bad-string token,
or bad-url token,
this is a parse error.
Return nothing.
Otherwise, return the current input token.
Consume a component value with the hashless color quirk
This section describes how to consume a component value with the hashless color quirk.
The hashless color quirk list contains the following property names:
'background-color'
'border-color'
'border-top-color'
'border-right-color'
'border-bottom-color'
'border-left-color'
'color'
If the current input token is a number token,
let value be the token's representation.
If the current input token is a dimension token,
let value be the token's representation followed by the token's unit.
If the current input token is an ident token,
let value be the token's value.
If value has a length of 3 or 6 and is composed solely of hex digits,
create a hash token with its value set to the value
and return it.
Otherwise,
consume a component value
and return the returned value.
Consume a component value with the unitless length quirk
This section describes how to consume a component value with the unitless length quirk.
The unitless length quirk list contains the following property names:
'border-top-width'
'border-right-width'
'border-bottom-width'
'border-left-width'
'border-width'
'bottom'
'font-size'
'height'
'left'
'letter-spacing'
'margin'
'margin-right'
'margin-left'
'margin-top'
'margin-bottom'
'padding'
'padding-top'
'padding-right'
'padding-bottom'
'padding-left'
'right'
'top'
'width'
'word-spacing'
If the current input token is a number token,
create a dimension token with its value and representation set to the token's value and representation,
and its unit set to "px".
Return the dimension token.
Otherwise,
consume a component value
and return the returned value.
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.
Initialize a valid flag to true.
Repeatedly consume the next input token and process it as follows:
EOF token
ending token
If the valid flag is true,
return the block.
Otherwise,
return nothing.
anything else
Consume a component value.
If anything was returned,
append the returned value
to the value of the current block;
otherwise, set the valid flag to false.
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.
Initialize a valid flag to true.
Repeatedly consume the next input token and process it as follows:
EOF token
) token
If the valid flag is true,
append the current argument to the function's argument list.
Return the function.
Otherwise,
return nothing.
delim token with the value ","
Append the current argument to the function's argument list.
Create a new current argument which is initially empty.
number token
If the quirks mode flag is set,
and the function's name is as ASCII case-insensitive match with "rect",
consume a component value with the unitless length quirk.
If anything was returned,
append the returned value
to the value of the current argument;
otherwise, set the valid flag to false.
Otherwise,
consume a component value.
If anything was returned,
append the returned value
to the value of the current argument;
otherwise, set the valid flag to false.
anything else
Consume a component value.
If anything was returned,
append the returned value
to the value of the current argument;
otherwise, set the valid flag to false.
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-block mode.
If the current rule is a rule-filled at-rule,
switch to the rule-block 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.
If the rule does not match its required grammar,
or if it's not valid in its current context,
discard it.
Otherwise, pop the current rule from the stack of open rules
and append it to the value of the new current rule.
Discard the current rule
This section describes how to discard the current rule.
It is invoked whenever the parser determines that the rule it's currently parsing isn't valid,
and thus must not be included in the parsed stylesheet.
Pop the current rule from the stack of open rules.
Don't do anything with it.
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.
The handling of some miscellanous "special" tokens
(like an unmatched } token)
showing up in various places in the grammar
has been specified with some reasonable behavior shown by at least one browser.
Previously, stylesheets with those tokens in those places just didn't match the stylesheet grammar at all,
so their handling was totally undefined.
Specifically:
[] blocks, () blocks and functions can now contain {} blocks, at-keywords or semicolons
Selectors can now contain semicolons
Selectors and at-rule preludes can now contain at-keywords
Quirks mode parsing differences are now officially recognized in the parser.
Parser Entry Points
The state machines defined in this specification can be invoked in multiple ways,
to convert a stream of text into various CSS concepts.
All of the algorithms defined in this section begin in the parser.
It is assumed that the input preprocessing
and tokenization
steps have already been completed,
resulting in a stream of tokens.
The following notes should probably be translated into normative text in the relevant specs,
hooking this spec's terms:
"Parse a stylesheet" is intended to be the normal parser entry point,
for parsing stylesheets.
"Parse a rule" is intended for use by the CSSStyleSheet#insertRule method,
and similar functions which might exist,
which parse text into a single rule.
"Parse a list of declarations" is for the contents of a style attribute,
which parses text into the contents of a single style rule.
Dunno about "Parse a value" yet.
I'll remove it if I don't figure out what to do with it.
"Parse a list of values" is for the contents of presentational attributes,
which parse text into a single declaration's value.
"Parse a comma-separated list of values" is similar,
but for comma-separated lists.
Are there any other things somewhere where some tech (that isn't straight CSS itself) needs to parse some text into CSS?
Parse a stylesheet
To parse a stylesheet:
Initialize the stack of open rules by pushing a new stylesheet onto it.
Initialize the stack of open rules by pushing a new stylesheet onto it,
and then pushing a new style rule onto it
with a selector set to the empty string
and an initially empty value.
Invoke the parser,
with the only declarations flag set,
starting in the declaration-block mode.
Return the value of the style rule in the value of the stylesheet it returns.
Parse a component value
To parse a component value:
Discard whitespace tokens from the token stream until a non-whitespace token is reached.
If the token stream is exhausted without finding a non-whitespace token,
return a syntax error.
Consume a component value.
If nothing is returned,
return a syntax error.
Discard whitespace tokens from the token stream until a non-whitespace token is reached.
If the token stream is exhausted without finding a non-whitespace token,
return the value found in the previous step.
Otherwise,
return a syntax error.
This algorithm is token/component-value agnostic,
which means it can be called with either a stream of tokens
or a stream of component values
with identical results.
Parse a list of component values
To parse a list of component values:
Repeatedly consume a component value until the token stream is exhausted,
appending the returned values into a list.
If at any point nothing is returned,
return a syntax error.
Return the list.
This algorithm is token/component-value agnostic.
Parse a comma-separated list of component values
To parse a comma-separated list of component values:
Initialize val to an empty list,
and temp to an empty list.
Repeatedly consume a component value,
appending the returned values to temp,
until either a comma token is returned,
or the token stream is exhausted.
If at any point nothing is returned,
return a syntax error.
If a comma token is encountered,
do not append it to temp.
Instead,
append temp to val.
Create a new temp,
and return to step 2.
If the token stream is exhausted,
append temp to val,
and return val.
This algorithm is token/component-value agnostic.
Parse an+b notation
To parse an+b notation:
Initialize an integer called step to 0,
an integer called offset to 0,
and a string called repr to the empty string.
Repeatedly consume the next input token
and process it as follows:
ident token
number token with its type flag set to "integer"
dimension token
Append the token's value, representation, or representation and unit, respectively, to repr.
delim token with the value "+"
Append U+002B PLUS SIGN (+) to repr.
delim token with the value "-"
Append U+002D HYPHEN-MINUS (-) to repr.
whitespace token
Append U+0020 SPACE ( ) to repr.
EOF
Continue to the next step of the algorithm.
anything else
This is a parse error.
Return a syntax error.
Trim U+0020 SPACE ( ) characters from the front and back of repr,
then process it as follows:
If repr is an ASCII case-insensitive match
for the string "odd",
set step to 2
and offset to 1.
Otherwise, if repr is an ASCII case-insensitive match
for the string "even",
set step to 2
and offset to 0.
Otherwise, if repr consists solely of digits,
optionally prefixed with a single
U+002B PLUS SIGN (+)
or U+002D HYPHEN-MINUS (-),
interpret repr as a base-10 number,
and set step to the result.
Otherwise, if repr contains
U+004E LATIN CAPITAL LETTER N (N),
or U+006E LATIN SMALL LETTER N (n),
split repr into two substrings
composed respectively of the characters preceding and following the first such letter.
Interpret the first string as follows:
If the first string is empty,
set step to 1.
Otherwise, if the first string consists solely of a single
U+002B PLUS SIGN (+)
or U+002D HYPHEN-MINUS (-),
set step to 1 or -1, respectively.
Otherwise, if the first string consists solely of digits,
optionally prefixed with a single
U+002B PLUS SIGN (+)
or U+002D HYPHEN-MINUS (-),
interpret the first string as a base-10 number,
and set step to the result.
Otherwise, this is a parse error;
return a syntax error.
Interpret the second string as follows:
If the second string is empty,
set offset to 0.
Otherwise, if the second string consists solely of
0 or more U+0020 SPACE characters,
optionally followed by a single
U+002B PLUS SIGN (+)
or U+002D HYPHEN-MINUS (-) character,
followed by 0 or more U+0020 SPACE characters,
followed by 1 or more digits,
interpret the digits as a base-10 number.
If there was a U+002D HYPHEN-MINUS (-) character,
negate the result.
Set offset to the result.
Otherwise, this is a parse error;
return a syntax error.
Otherwise, this is a parse error;
return a syntax error.
Return step and offset.
This algorithm is token/component-value agnostic.
Serialization
This specification does not define how to serialize CSS in general,
leaving that task to the CSSOM and individual feature specifications.
However, there is one important facet that must be specified here regarding comments,
to ensure accurate "round-tripping" of data from text to CSS objects and back.
The tokenizer described in this specification does not produce tokens for comments,
or otherwise preserve them in any way.
Implementations may preserve the contents of comments and their location in the token stream.
If they do, this preserved information must have no effect on the parsing step,
but must be serialized in its position as
"/*"
followed by its contents
followed by "*/".
If the implementation does not preserve comments,
it must insert the text "/**/" between the serialization of adjacent tokens
when the two tokens are of the following pairs:
hash or at-keyword token followed by a number, percentage, ident, dimension, unicode-range, url, or a function token;
number, ident, and dimension tokens in any combination;
number, ident, or dimension token followed by a percentage, unicode-range, url, or function token;
ident token followed by a ( token;
a delim token containing "#" or "@" followed by any token except whitespace;
a delim token containing "-", "+", ".", "<", ">", or "!" following or followed by any token except whitespace;
a delim token containing "/" following or followed by a delim token containing "*".
The preceding pairs of tokens can only be adjacent due to comments in the original text,
so the above rule reinserts the minimum number of comments into the serialized text to ensure an accurate round-trip.
(Roughly. The delim token rules are slightly too powerful, for simplicity.)
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 Syntax Module Level 3 is defined for three conformance classes: