stylelint: Add `no-invalid-position-var-function`
What is the problem you’re trying to solve?
Using the var() function inside a @ rule block is a CSS syntax error that should be detectable:
@font-face {
font-family: foo;
font-weight: var(--font-weight-normal); /* Syntax Error */
}
Firefox will raise a Unknown descriptor ‘var(’ in @font-face rule. Skipped to next declaration..
What solution would you like to see?
A rule that detects such cases. I dug through the CSS specs and found:
Block at-rules will typically contain a collection of (generic or at-rule–specific) at-rules, qualified rules, and/or descriptor declarations subject to limitations defined by the at-rule. Descriptors are similar to properties (and are declared with the same syntax) but are associated with a particular type of at-rule rather than with elements and boxes in the tree.
The var() function can be used in place of any part of a value in any property on an element. The var() function can not be used as property names, selectors, or anything else besides property values. (Doing so usually produces invalid syntax, or else a value whose meaning has no connection to the variable.)
I’m sure there are more functions besides var that would be invalid for a descriptor declaration, but a rule that just warns for var would be a good start.
About this issue
- Original URL
- State: open
- Created a year ago
- Comments: 22 (16 by maintainers)
That’s a good summary.
I agree.
SGTM. It’ll tie into the “The
var()function can not be used as property names, selectors, or anything else besides property values” part of the spec that @silverwind mentioned above.I had thought
envandvarwere similar and so a rule would apply to them both, but it turns outenvcan be used in more places:Our closest existing rule is no-invalid-position-at-import-rule, so called because it’s scoped to the whole source like this rule.
Suggested blueprint:
no-invalid-position-var-functionvar()functions.trueThe
var()function can be used in place of any part of a value in any property on an element. Thevar()function can not be used as property names, selectors, or anything else besides property values.This rule checks:
We’ll want to ensure we don’t needlessly call any of the constructor parsers when checking any of the above.
According to the CSS tree reference, the following at-rule have descriptors:
counter-stylefont-facepagepropertyviewportShall I label as ready to implement?
Maybe it can be approached from a different perspective?
Part of the issue here is that
var()is expected by many to just work everywhere. Especially for people coming from preprocessors like scss.A rule that warns on invalid locations of
var()functions could cover :@font-facedescriptor values@mediafeature valuesI think this is also easier to test and verify so that it is correct with the CSS specification.
If I recall correctly this is the difference between descriptors and properties.
@font-face,@property,@counter-styleall take a list of descriptors, whereas@pagetakes a list of declarations (property / value pairs).https://www.w3.org/TR/css-variables-1/#using-variables
https://www.w3.org/TR/css-fonts-4/#font-face-rule
Edit :
@pagealso has a set of descriptors:sizepage-orientationOkay, I suggest a blueprint:
at-rule-no-invalid-descriptorUnexpected invalid descriptor within "@<at-rule>"trueExample:
Please feel free to give me any feedback.
Agree, renamed title to
at-rule-no-invalid-descriptor.If this rule is limited to at-rule, starting the rule name with
at-rule-might be better. 🤔Ref:
Agree, syntax errors are topics for a parser, not a linter.
@silverwind yeah, I think it is more about grammar parsing than linting, so I hope in future we resolve problems with our parser and will catch this on the parser side (or will have rule to apply grammar parsing to each things in your CSS)