Skip to content

Bug: no-invalid-properties does not validate calc() contents #501

Open

Description

@przemyslaw-zan

Environment

ESLint version: 9.39.4
@eslint/css version: 1.4.0
Node version: v24.15.0
npm version: 11.12.1
Operating System: Ubuntu (within WSL)

Which language are you using?

stylesheet

What did you do?

Configuration
import css from "@eslint/css";

export default [
	{
		files: ["**/*.css"],
		plugins: { css },
		language: "css/css",
		rules: {
			"css/no-invalid-properties": "error"
		}
	}
];
a {
	width: red;
	width: calc(red);
	width: calc(1px+2px);
	width: calc();
	width: calc(1px + );
	width: calc(1px ** 2px);
}

What did you expect to happen?

All six declarations reported as invalid. In particular:

  • calc(red), calc(), calc(1px + ) and calc(1px ** 2px) do not match the <calc-sum> grammar at all.
  • calc(1px+2px) is invalid per CSS Values and Units: "White space is required on both sides of the + and - operators." (1px+2px tokenizes as the two dimensions 1px and +2px with no operator between them.)

Browsers agree and drop all six declarations.

What actually happened?

Only the unwrapped width: red is reported. Every calc() variant passes:

/home/projects/eslint-css-calc-repro/style.css
  2:10  error  Invalid value 'red' for property 'width'. Expected auto | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content( <length-percentage [0,∞]> ) | <calc-size()> | <anchor-size()> | stretch | <-non-standard-size>  css/no-invalid-properties

✖ 1 problem (1 error, 0 warnings)

So wrapping an arbitrary invalid value in calc() bypasses validation entirely - width: red is flagged while width: calc(red) is not.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/eslint-css-calc-repro

Participation

  • I am willing to submit a pull request for this issue.

AI acknowledgment

  • I did not use AI to generate this issue report.
  • (If the above is not checked) I have reviewed the AI-generated content before submitting.

Additional comments

It looks like math function contents are treated as opaque during value matching (possibly on the @eslint/css-tree side), i.e. a calc() is accepted wherever a numeric type is expected without checking its operands or operators.

Activity

  1. DMartens commented on Jul 13, 2026

    @DMartens
    Contributor

    As you said we use csstree for the matching and its tool csstree/validator reports for the same cases.
    The browser drops the declarations not because calc evaluates to an invalid value but because it does not match the calc() syntax.
    As such I would see this as a new rule to validate functions with specific syntax (such as calc).

  2. moved this from Needs Triage to Feedback Needed in Triageon Jul 13, 2026
  3. przemyslaw-zan commented on Jul 14, 2026

    @przemyslaw-zan
    Author

    In this case, prior art with part of the functionality:

  4. DMartens commented on Jul 14, 2026

    @DMartens
    Contributor

    This is not prior art as it is purely a stylistic rule enforcing spacing around the operators and not checking the syntax as proposed here.

  5. przemyslaw-zan commented on Jul 14, 2026

    @przemyslaw-zan
    Author

    The issue I've made contains explanation that in this case calc is whitespace sensitve, thus this is not stylistic issue but a validity one.

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

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

  • Status
    Feedback Needed

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions