Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New css module: CSS syntax. Partially deprecated charset. #30793

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
df11dae
New page: CSS syntax error handling
estelle Dec 5, 2023
e9bffa8
deprecate @charset and list as a rule not at-rule
estelle Dec 5, 2023
d5f1733
Define character encoding
estelle Dec 5, 2023
bddc9a2
New page: error handling
estelle Dec 5, 2023
9ff78fc
New page: css syntax module
estelle Dec 5, 2023
1c099d5
delete charset module. move to syntax module
estelle Dec 5, 2023
df627d9
still supported
estelle Dec 5, 2023
9b2da17
table of contents
estelle Dec 6, 2023
bd5f752
better grammar
estelle Dec 6, 2023
10d57b2
better grammar
estelle Dec 6, 2023
2d832cf
better grammar
estelle Dec 6, 2023
3afcdbd
better grammar
estelle Dec 6, 2023
e1424fb
Apply suggestions from code review
estelle Dec 7, 2023
4691893
added a few more notes - prefixes
estelle Dec 7, 2023
245d126
edits per review
estelle Dec 7, 2023
24772a4
change h2 to h3
estelle Dec 9, 2023
4d5c582
Apply suggestions from code review
estelle Dec 13, 2023
71944f1
add guide to module page.
estelle Dec 13, 2023
e287842
change UA to browser
estelle Dec 13, 2023
50c42ce
address https://github.com/mdn/content/pull/30793#discussion_r1421245493
estelle Dec 13, 2023
1ea3167
hyphens to underscores
estelle Dec 13, 2023
e0f68c2
rewrote the at-rule section
estelle Dec 14, 2023
ab85e39
rewrite grammar section
estelle Dec 15, 2023
53a33f3
fixing linter suggestions
dipikabh Dec 15, 2023
debf7a9
final tweaks
estelle Dec 15, 2023
a1c3201
Update files/en-us/web/css/css_syntax/error_handling/index.md
estelle Dec 15, 2023
496af3c
Update files/en-us/web/css/css_syntax/error_handling/index.md
estelle Dec 15, 2023
9d13c82
fix flaws
estelle Dec 15, 2023
30db514
closed comments
estelle Dec 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions files/en-us/_redirects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11480,6 +11480,7 @@
/en-US/docs/Web/CSS/CSS_User_Interface /en-US/docs/Web/CSS/CSS_basic_user_interface
/en-US/docs/Web/CSS/CSS_Variables /en-US/docs/Web/CSS/CSS_cascading_variables
/en-US/docs/Web/CSS/CSS_Viewport /en-US/docs/Web/CSS
/en-US/docs/Web/CSS/CSS_charsets /en-US/docs/Web/CSS/CSS_syntax
/en-US/docs/Web/CSS/CSS_descriptor_definition /en-US/docs/Web/CSS
/en-US/docs/Web/CSS/CSS_flex-wrap /en-US/docs/Web/CSS/flex-wrap
/en-US/docs/Web/CSS/CSS_grid_layout/Layout_using_line-based_placement /en-US/docs/Web/CSS/CSS_grid_layout/Grid_layout_using_line-based_placement
Expand Down
8 changes: 4 additions & 4 deletions files/en-us/_wikihistory.json
Original file line number Diff line number Diff line change
Expand Up @@ -77124,10 +77124,6 @@
"modified": "2020-07-07T12:03:44.891Z",
"contributors": ["wbamberg", "mfluehr"]
},
"Web/CSS/CSS_charsets": {
"modified": "2020-10-15T21:38:35.251Z",
"contributors": ["wbamberg", "fscholz", "mfluehr", "Sebastianz", "teoli"]
},
"Web/CSS/CSS_colors": {
"modified": "2020-12-02T11:04:05.642Z",
"contributors": ["peterbe", "wbamberg", "fscholz", "Sheppy", "mfluehr"]
Expand Down Expand Up @@ -78500,6 +78496,10 @@
"modified": "2020-04-27T22:31:21.929Z",
"contributors": ["ExE-Boss", "mfuji09", "rachelandrew"]
},
"Web/CSS/CSS_syntax": {
"modified": "2020-10-15T21:38:35.251Z",
"contributors": ["wbamberg", "fscholz", "mfluehr", "Sebastianz", "teoli"]
},
"Web/CSS/CSS_table": {
"modified": "2020-07-07T12:26:58.542Z",
"contributors": ["wbamberg", "fscholz", "mfluehr", "Sebastianz", "teoli"]
Expand Down
4 changes: 3 additions & 1 deletion files/en-us/web/css/@charset/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ browser-compat: css.at-rules.charset

{{CSSRef}}

The **`@charset`** [CSS](/en-US/docs/Web/CSS) [at-rule](/en-US/docs/Web/CSS/At-rule) specifies the character encoding used in the style sheet. It must be the first element in the style sheet and not be preceded by any character; as it is not a [nested statement](/en-US/docs/Web/CSS/Syntax#nested_statements), it cannot be used inside [conditional group at-rules](/en-US/docs/Web/CSS/At-rule#conditional_group_rules). If several `@charset` at-rules are defined, only the first one is used, and it cannot be used inside a `style` attribute on an HTML element or inside the {{ HTMLElement("style") }} element where the character set of the HTML page is relevant.
The **`@charset`** [CSS](/en-US/docs/Web/CSS) rule specifies the character encoding used in the style sheet. Although the first character in `@charset` is the `@` symbol, it is not an [at-rule](/en-US/docs/Web/CSS/At-rule). The [CSS syntax](/en-US/docs/Web/CSS/CSS_syntax) module deprecates this rule, defining it as an unrecognized legacy rule to be dropped when a stylesheet is grammar-checked, but it is [fully supported in all browsers](#browser-compatibility).

The `@charset` rule must be the first element in the style sheet and not be preceded by any character; as it is not a [nested statement](/en-US/docs/Web/CSS/Syntax#nested_statements), it cannot be used inside [conditional group at-rules](/en-US/docs/Web/CSS/At-rule#conditional_group_rules). If several `@charset` at-rules are defined, only the first one is used, and it cannot be used inside a `style` attribute on an HTML element or inside the {{ HTMLElement("style") }} element where the character set of the HTML page is relevant.

```css
@charset "utf-8";
Expand Down
24 changes: 0 additions & 24 deletions files/en-us/web/css/css_charsets/index.md

This file was deleted.

120 changes: 120 additions & 0 deletions files/en-us/web/css/css_syntax/error_handling/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: CSS syntax errors
slug: Web/CSS/CSS_syntax/error_handling
page-type: guide
---

{{CSSRef}}

When an error is made in CSS, instead of [throwing an error like in JavaScript](/en-US/docs/Web/JavaScript/Reference/Errors), the browser will gracefully recover, skipping the invalid content. While the user agent won't alert you to CSS errors, the user agent won't fail either. This is a feature of CSS, not a bug.

When an error is made in CSS, the user-agent's parser ignores the lines containing the errors, discarding the minimum amount of content before returning to parsing as normal. As new features are added to CSS, a browser may not recognize these new features. The recovery from errors allows a browser to discard the line containing the unrecognized content. This CSS feature allows for adding new features to CSS without worrying that anything, other than the new feature, is broken in older browsers. It also allows for both old and new syntaxes to coexist, in that order. Browsers render the old syntax until they recognize the new syntax as valid. Because user agents ignore CSS errors, the valid fallback CSS doesn't get overwritten by perceived as invalid new CSS.

The type and amount of CSS that a browser ignores due to an error depends on the type of error. Some of common error situations are listed below:

estelle marked this conversation as resolved.
Show resolved Hide resolved
- For [errors in at-rules](#at-rule-errors), whether a single line or the entire at-rule fails depends on the at-rule and the type of error.
estelle marked this conversation as resolved.
Show resolved Hide resolved
- If the [error is an invalid selector](#errors-in-selector-lists), the entire declaration block is ignored.
- An [error due to a missing semi-colon](#errors-within-css-declaration-blocks) between property declarations causes an invalid value, in which case, the property-value declaration is ignored.
- If the [error is a property name or value](#errors-within-css-declaration-blocks), such as an unrecognized property name or invalid data type, the property-value declaration is ignored.
- If the [error is due to a missing end-bracket](#auto-closed-endings), the extent of what is ignored depends on the browser's ability to parse the error as nested CSS.

After parsing each declaration, style rule, at-rule, and so on, the browser checks the parsed content against its expected [grammar](#grammar-check) for that construct. If the content does not match the expected grammar for that construct, the browser considers it invalid and ignores it.

## CSS parser errors

### At-rule errors

The `@` symbol, known in the CSS specifications as an `<at-keyword-token>`, indicates the beginning of an {{cssxref("at-rule")}}. Some at-rules such as {{cssxref("@import")}} and some {{cssxref("@layer")}} declarations contain just a prelude and and other at-rule blocks contain a body of declarations, as in {{cssxref("@keyframes")}}, {{cssxref("@font-face")}}, and `@layer` declarations, which include styles blocks. These at-rule blocks are generally multi-statement and referred to as multi-line, even though they can be declared with no line breaks.

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 semicolon ends the at-rule immediately for single-line at-rules. If there is an open curly brace, this informs the browser where the completed at-rule prelude ends and the at-rule's body starts. For these multi-line at-rules, the parser looks forward, seeking matching blocks (content surrounded by `()`, `{}`, or `[]`) until it finds a closing curly brace (`}`) that isn't matched by anything else or inside of another block, to close the body of the at-rule. The contents of the at-rule are then interpreted according to the grammar rules for that particular at-rule.

> **Note:** Different at-rules have different grammar rules, different (or no) descriptors, and different rules for what will invalidate the entire at-rule, if at all. The expected grammar for each at-rule and how errors are handled are documented on the respective at-rule page.

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. A `@layer` statement, which can be declared either as a prelude or can contain a body of declarations, will always create at least an anonymous layer. If there is a declaration body, the handling of any error depends on the error. The user-agent won't fail; rather, invalid CSS is ignored. If the error is a missing closing curly brace, it is considered a logic error not a CSS error. In the case of a missing closing brace in `@layer`, the styles are assumed to be in the cascade layer that is defined in the at-rule's prelude. This represents a developer mistake, a logic error. In this case, the CSS is considered valid; because there are no syntactic errors, the parser does not ignore any part.

### Errors in selector lists

There are many ways you might make a mistake writing a selector, but only invalid selectors cause [invalid selector list](/en-US/docs/Web/CSS/Selector_list#invalid_selector_list) issues.
estelle marked this conversation as resolved.
Show resolved Hide resolved

If you include a {{cssxref("class_selectors", "class")}}, {{cssxref("id_selectors", "id")}}, or {{cssxref("type_selectors", "type")}} selector for a class, id, element or custom-element, respectively, that doesn't exist, it may be a logic error, but it's not an error the parser needs to handle. If, however, you have a typo in a pseudo-class or a pseudo-element, it might create an invalid selector, which is an error the parser will notice.

If a selector list contains any selectors that are in the [invalid selector list](/en-US/docs/Web/CSS/Selector_list#invalid_selector_list), then the entire style block is ignored. There are exceptions: if the invalid selector is within the {{cssxref(":is")}} or {{cssxref(":where")}} pseudo-class, which accept [forgiving selector lists](/en-US/docs/Web/CSS/Selector_list#forgiving_selector_list) or if the unknown selector is a [`-webkit-` prefixed pseudo-element](#webkit-exception), only the unknown selector is ignored as not matching anything. The selector list is not invalidated.

If a selector list contains any invalid selectors outside of these exceptions, a single invalid or unsupported selector in the selector list will invalidate the entire rule. The entire selector block will be ignored. The user-agent will look for the closing curly brace and will continue parsing again from that point on.

#### Webkit exception

Due to legacy issues from the overuse of browser-specific prefixes in selectors and in [property names and values](#vendor-prefixes), browsers avoid the invalidation of selector lists by treating all [pseudo-elements](/en-US/docs/Web/CSS/Pseudo-elements) that start with a case-insensitive `-webkit-` prefix and don't end with `()` as valid.

This means that a pseudo-element like `::-webkit-works-only-in-samsung` will not invalidate a selector list, regardless of the browser. In such cases, the pseudo-element may not be recognized or supported by the browser, but it will not cause the entire selector list and it's associated style block to be ignored. On the other hand, the unknown prefixed selector with a function notation `::-webkit-imaginary-function()` will invalidate the entire selector list and the browser will ignore the entire selector block.

### Errors within CSS declaration blocks

When it comes to CSS properties and values within a declaration block, if either the property or the value is invalid, that property-value pair is ignored and discarded. When a user agent parses or interprets a list of declarations, unknown syntax at any point causes the user-agent's parser to discard only that specific rule. It then continues parsing CSS after the next semicolon or closing curly bracket is encountered, whichever comes first.

The parser seeks forward until it finds a semicolon (or the end of the block). It then starts fresh, trying to parse a declaration again.
estelle marked this conversation as resolved.
Show resolved Hide resolved

This example contains an error. The parser ignores the error (and the comments), seeking forward until it encounters a semi-colon, then restarts parsing:

```css-nolint bad
p {
/* Invalid syntax due to missing semi-colon */
border-color: red
background-color: green;

/* Valid syntax but likely a logic error */
border-width: 100vh;
}
```

The reason the first declaration in this selector block is invalid is because the semi-colon is missing and the declaration is not the last declaration in the block. The property missing the semi-colon is ignored, as is the property-value pair following it because the browser only continues parsing after a semi-colon or closing bracket is encountered. In the above CSS, the `border-color` value is parsed as `red background-color: green;` which is not a valid {{cssxref("&lt;color&gt;")}} value.

The parser ignores the property with an invalid value, and starts parsing again after it encounters the next semi-colon. The {{cssxref("border-width")}} value of `100vh` is likely a mistake, but it's not an error. As it is syntactically valid, it will be parsed and applied to the elements matching the selector.

#### Vendor prefixes

Vendor-prefixed property names and property values, when not understood by a browser, are ignored. Only the single rule containing the invalid property or value is ignored. The parser looks for the next semi-colon or closing curly brace and then continues parsing from there.

You may come across legacy CSS that looks like the following:

```css example-bad
/* Prefixed values */
.wrapper {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
/* Prefixed properties */
.rounded {
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
-ms-border-radius: 50%;
-o-border-radius: 50%;
border-radius: 50%;
}
```

In both the declaration blocks above, the last declaration is valid. The parser ignores the declarations it doesn't understand as invalid. If the user agent does understand one of the prefixed declarations, for example, all browsers understand `display: flex;` and `border-radius: 50%;`, the values in the last, valid declaration are used, not because they are the valid ones, but rather due to the [cascade](/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance#source_order) [order of appearance](/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) rule.

> **Note:** Avoid including prefixed properties or property values. If you must, declare the prefixed values before the valid, non-prefixed standard property-value pairs.

### Errors with auto-closed endings

If a stylesheet — be it an external style sheet, selector blocks within an HTML {{HTMLElement("style")}} element, or inline rules within a [`style`](/en-US/docs/Web/HTML/Global_attributes/style) attribute — ends while a rule, declaration, function, string, etc. is still open, the parser will automatically close everything that was left unclosed.

If the content between the last semi-colon and the end of the stylesheet is valid, even if incomplete, the CSS will be parsed normally. Failing to properly close CSS statements doesn't necessarily make the statements invalid.
estelle marked this conversation as resolved.
Show resolved Hide resolved

> **Note:** Do not take advantage of CSS's forgiving nature. Always close all of your statements and style blocks. It makes your CSS easier to read and maintain and ensures that the browser parses the CSS you intended.
estelle marked this conversation as resolved.
Show resolved Hide resolved

> **Note:** If a comment starts with `/*` but is not closed, all CSS code until the closing comment `*/` is encountered will be treated as part of the comment. While an unclosed comment does not invalidate your CSS, but it causes the CSS inside the comment to be ignored.

### Grammar check

After each declaration, style rule, at-rule, etc. is parsed, the user agent checks to make sure the grammar is the expected grammar for that declaration. For example, if a property value is of the wrong data type or if a descriptor is not valid for the at-rule being described, the content that does not match the expected grammar is deemed invalid, and gets ignored.
estelle marked this conversation as resolved.
Show resolved Hide resolved

## See also

- [CSS syntax](/en-US/docs/Web/CSS/CSS_syntax) module
- [Syntax](/en-US/docs/Web/CSS/Syntax) guide
- [Value definition syntax](/en-US/docs/Web/CSS/Value_definition_syntax)
97 changes: 97 additions & 0 deletions files/en-us/web/css/css_syntax/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: CSS syntax
slug: Web/CSS/CSS_syntax
page-type: css-module
spec-urls: https://drafts.csswg.org/css-syntax
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec is rendering as "Unknown specification" though the link is valid

---

{{CSSRef}}

The **CSS syntax** module describes, in general terms, the structure and syntax of cascading stylesheets, or CSS. It defines CSS as the language for describing the rendering of structured documents (such as HTML and XML), on the web and elsewhere.

This module doesn't define any properties, {{cssxref("css_types", "data types")}}, {{cssxref("css_functions", "functions")}}, or {{cssxref("at-rule", "at-rules")}}. Rather, it elaborates on how all of these features should be defined and how user agents should parse CSS.

The module explicitly states that {{cssxref("@charset")}} is not an actual at-rule, but rather an unrecognized legacy rule that should be omitted when a stylesheet is grammar-checked.

## Reference

### Key concepts

- {{cssxref("at-rule")}}
- [character escaping](/en-US/docs/Web/CSS/custom-ident#escaping_characters)
- [CSS comments](/en-US/docs/Web/CSS/Comments)
- [CSS declaration](/en-US/docs/Web/API/CSS_Object_Model/CSS_Declaration)
- [CSS declaration block](/en-US/docs/Web/API/CSS_Object_Model/CSS_Declaration_Block)
- [CSS function](/en-US/docs/Web/CSS/CSS_Functions)
- [invalid](/en-US/docs/Web/CSS/CSS_syntax/error_handling)
- [style rule](/en-US/docs/Web/API/CSSStyleRule)

### Glossary terms

- {{glossary("CSS_Descriptor", "CSS descriptor")}}
- {{glossary("parse")}}
- {{glossary("stylesheet")}}
- {{glossary("whitespace")}}

## Guides

estelle marked this conversation as resolved.
Show resolved Hide resolved
- [Syntax](/en-US/docs/Web/CSS/Syntax)

- : Overview of CSS syntax, including CSS declarations, declaration blocks, rulesets, and statements.

- [Value definition syntax](/en-US/docs/Web/CSS/Value_definition_syntax)

- : The formal grammar for defining valid values for CSS properties and functions, along with semantic constraints. A guide for understanding CSS component value types, combinators, and multipliers.

- [CSS syntax error handling](/en-US/docs/Web/CSS/CSS_syntax/error_handling)

- : Overview of how the user-agent handles invalid CSS
estelle marked this conversation as resolved.
Show resolved Hide resolved

## Related concepts

estelle marked this conversation as resolved.
Show resolved Hide resolved
[CSS selectors](/en-US/docs/Web/CSS/CSS_selectors) module:

- [CSS specificity](/en-US/docs/Web/CSS/Specificity)

[CSS cascade](/en-US/docs/Web/CSS/CSS_cascade) module:

- {{cssxref("@import")}} at-rule
- {{cssxref("important")}} flag
- [Initial values](/en-US/docs/Web/CSS/initial_value)
- [Computed values](/en-US/docs/Web/CSS/computed_value)
- [Used values](/en-US/docs/Web/CSS/used_value)
- [Actual values](/en-US/docs/Web/CSS/actual_value)
- [CSS inheritance](/en-US/docs/Web/CSS/Inheritance)
- {{Glossary("Property/CSS", "CSS property")}}

[CSS custom properties for cascading variables](/en-US/docs/Web/CSS/CSS_cascading_variables) module:

- [custom property (`--*`)](/en-US/docs/Web/CSS/--*)
- {{cssxref("var")}} function

[CSS conditional rules](/en-US/docs/Web/CSS/CSS_conditional_rules) module:

- {{cssxref("@media")}} at-rule
- {{cssxref("@supports")}} at-rule

[CSS Object Model (CSSOM)](/en-US/docs/Web/API/CSS_Object_Model) API:

- {{domxref("CSSValue.cssText", "cssText")}} property
- {{domxref("CSSStyleSheet.insertRule()", "insertRule(rule)")}} method
- {{domxref("CSSStyleSheet.replace()", "replace(text)")}} method

[WHATWG](/en-US/docs/Glossary/WHATWG) specification:

- {{HTMLElement("style")}} element
- {{HTMLElement("link")}} element
- [`class`](/en-US/docs/Web/HTML/Global_attributes/class) attribute
- [`rel`](/en-US/docs/Web/HTML/Attributes/rel#stylesheet) attribute

## Specifications

{{Specifications}}

## See also

- [CSS selectors](/en-US/docs/Web/CSS/CSS_selectors) module
- [CSS values and units](/en-US/docs/Web/CSS/CSS_Values_and_units) module
Loading