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

[css-cascade] What is a valid at-rule? Or what is an invalid at-rule? #9175

Open
romainmenke opened this issue Aug 9, 2023 · 9 comments
Open

Comments

@romainmenke
Copy link
Member

romainmenke commented Aug 9, 2023

https://drafts.csswg.org/css-cascade-5/#at-import

Any @import rules must precede all other valid at-rules and style rules in a style sheet (ignoring @charset and @layer statement rules) and must not have any other valid at-rules or style rules between it and previous @import rules, or else the @import rule is invalid.

After reading this I was curious what the exact definition is for a valid at-rule.

I assume that the intention is to allow new at-rules to be added to the language later without invalidating all imports in older browser versions.

It wasn't immediately clear to me exactly when an at-rule becomes invalid.

Is it only when the at-keyword-token is unknown? (e.g. @unknown {})


Things I noticed I could place before an @import and still have it apply :

@unknown {}

@import url("./green.css");
@ {}

@import url("./green.css");
{}

@import url("./green.css");

@cdoublev
Copy link
Collaborator

cdoublev commented Aug 10, 2023

As far as I know, excluding rules in invalid order, there are rules invalid in the context (eg. @top-left {} at the top-level of the style sheet), rules with an invalid prelude (eg. @import <invalid>;), rules with an unexpected block (eg. @namespace ns {}), rules with a missing block (eg. @media all;), and rules with missing mandatory declarations (eg. syntax in @property).

Also curious if there are other cases.

@romainmenke
Copy link
Member Author

This works :

@top-left {}

@import url("./green.css");
@media all;

@import url("./green.css");
@namespace ns {}

@import url("./green.css");

This does not :

@property --foo {
	inherits: false;
	initial-value: 0;
}

@import url("./green.css");

I am only testing Chrome, not looking at interop at this time.

@cdoublev
Copy link
Collaborator

Yeah, FF discards it. I guess it is a bug in Chrome.


In 8. CSS stylesheets - CSS Syntax:

If any style rule is invalid, or any at-rule is not recognized or is invalid according to its grammar or context, it’s a parse error. Discard that rule.

Note the link on invalid:

After each construct (declaration, style rule, at-rule) is parsed, the user agent checks it against its expected grammar. If it does not match the grammar, it’s invalid, and gets ignored by the UA, which treats it as if it wasn’t there at all.

It could be a bit more exhaustive regarding invalid in the context.

@romainmenke
Copy link
Member Author

FF doesn't support @property yet, right?

@cdoublev
Copy link
Collaborator

Hmm, it supports @font-palette-values but it does not discard the rule when missing a declaration of font-family... Chrome and FF may have good reasons not to remove invalid rules from the CSSOM, I guess.

@cdoublev
Copy link
Collaborator

However I think they should honor @import following invalid rules.

@tabatkins
Copy link
Member

After reading this I was curious what the exact definition is for a valid at-rule.

It's an at-rule that's valid, per the relevant spec defining that at-rule. I'm not sure how else that could be stated. Could you clarify what exactly you're finding unclear about this?

@romainmenke
Copy link
Member Author

per the relevant spec defining that at-rule

That is obvious in hindsight :)
I was looking for answers in the [css-cascade] specifications and I wasn't reading the relevant documents for each at-rule.


@cdoublev Does raises an interesting point about @property.

https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule

@property rules require a syntax and inherits descriptor; if either are missing, the entire rule is invalid and must be ignored. The initial-value descriptor is optional only if the syntax is the universal syntax definition, otherwise the descriptor is required; if it’s missing, the entire rule is invalid and must be ignored.

This doesn't work :

@property --foo {
	inherits: false;
	initial-value: 0;
}

@import url("./green.css");

This does :

@property (--foo) {
	inherits: false;
	initial-value: 0;
}

@import url("./green.css");

From the outside this looks as if only the prelude is checked for validity in this specific case.


I think the specifications are clear but maybe there are a few blind spots in WPT and some bugs in implementations?

@cdoublev
Copy link
Collaborator

cdoublev commented Aug 12, 2023

Maybe something like in Selectors - 3.9. Invalid Selectors and Error Handling:

A rule is invalid if either:

  • it is invalid in the context: it appears somewhere where it is not allowed (after another rule, the top-level of the style sheet, or in another rule)
  • it is invalid according to the CSS grammar:
    • it is an at-rule whose name is unrecognized
    • its prelude has an invalid grammar
    • it has a block but is not allowed to have one
    • it is missing a mandatory declaration
    • etc

(I have no strong opinion on whether defining this explicitly is needed)


Edit: I think I am wrong here (as well as CSS Fonts for @font-palette-values and CSS Properties Values API for @property):

A rule is invalid if [...] it is missing a mandatory declaration

Whatever the content of the block, it must not be able to invalidate its rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants