The @
symbol, known in CSS specifications as an <at-keyword-token>
, indicates the beginning of a CSS at-rule
. Once an at-rule begins with the @
symbol, nothing is considered invalid from the parser's standpoint. Everything up to the first semi-colon (;
) or the opening curly brace ({
) is part of the at-rule's prelude. The content of each at-rule is interpreted according to the grammar rules for that particular at-rule.
Statement at-rules, such as @import
and @namespace
declarations, contain just a prelude. The semicolon ends the at-rule immediately for statement at-rules. If the contents of the prelude are invalid according to the grammar for that at-rule, the at-rule is ignored, with the browser continuing to parse CSS after it encounters the next semi-colon. For example, if an @import
at-rule occurs after any CSS declaration other than @charset
, @layer
or other @import
statements, the @import
declaration is ignored.
@import "assets/fonts.css" layer(fonts);
@namespace svg url(http://www.w3.org/2000/svg);
If the parser encounters a curly brace ({
) before a semi-colon is encountered, the at-rule is parsed as a block at-rule. Block at-rules like @font-face
and @keyframes
, contain a block of declarations surrounded by curly braces ({}
). The opening curly brace informs the browser where the at-rule prelude ends and the at-rule's body starts. The parser looks forward, seeking matching blocks (content surrounded by ()
, {}
, or []
) until it finds a closing curly brace (}
) that isn't matched by any other curly braces: this closes the body of the at-rule.
Different at-rules have different grammar rules, different (or no) descriptors, and different rules for what, if anything, will invalidate the entire at-rule. The expected grammar for each at-rule and how errors are handled are documented on the respective at-rule page. The handling of invalid content depends on the error.
For example, the @font-face
rule requires both a font-family
and src
descriptor. If either of these is omitted or invalid, the entire @font-face
rule is invalid. Including an unrelated descriptor, any other valid font descriptor with an invalid value, or a property style declaration within the @font-face
nested block will not invalidate the font declaration. As long as the font name and font source are included and valid, any invalid CSS within the at-rule is ignored, but the @font-face
block is still parsed.
While the grammar of the @keyframe
at-rule is very different from the @font-face
rule grammar, the type of error still impacts what gets ignored. Important declarations (marked with the important
flag) and properties that can't be animated are ignored in keyframe rules, but they don't impact other styles declared in the same keyframe selector block. Including an invalid keyframe selector (such as a percentage value less than 0%
or greater than 100%
, or a <number>
omitting the %
) invalidates the keyframe selector list and therefore the style block is ignored. An invalid keyframe selector only invalidates the invalid selector's style block; it does not invalidate the entire @keyframe
declaration. Including styles between two keyframe selector blocks, on the other hand, will invalidate the entire @keyframe
at-rule.
Some at-rules are almost always valid. The @layer
at-rule comes in both regular and nested forms. The @layer
statement syntax contains just the prelude, ending with a semi-colon. Alternatively, the nested syntax has layer styles nested between curly braces coming after the prelude. Omitting a closing curly brace may be a logic error but is not a syntax error. In the case of a missing closing brace in @layer
, any styles coming after where the closing brace should have been are parsed as being in the cascade layer defined in the at-rule's prelude. The CSS is valid as there are no syntax errors; nothing is discarded. A syntax error may cause the named or anonymous layer to be empty, but the layer is still created.