Skip to content

fix: don't count keyframe selectors in selector-complexity - #586

Closed
ump45nose wants to merge 1 commit into
eslint:mainfrom
ump45nose:fix/selector-complexity-keyframe-selectors
Closed

ump45nose wants to merge 1 commit into
eslint:mainfrom
ump45nose:fix/selector-complexity-keyframe-selectors

Conversation

@ump45nose

@ump45nose ump45nose commented Oct 4, 2026 •

Copy link
Copy Markdown

What does this change?

css/selector-complexity counted the from, to and percentage selectors of an @keyframes rule toward maxTypes, because css-tree parses them as TypeSelector nodes even though they name no element. A stylesheet whose only "type selectors" were keyframe selectors therefore failed with { maxTypes: 0 }:

/* eslint css/selector-complexity: ["error", { "maxTypes": 0 }] */

@keyframes fade {
	from { opacity: 0; }
	to { opacity: 1; }
}
4:2  Exceeded maximum type selector. Only 0 allowed.
8:2  Exceeded maximum type selector. Only 0 allowed.

The fix tracks whether the selector sits inside a keyframes rule and skips those. It uses the same technique as the existing no-duplicate-keyframe-selectors rule, because @eslint/css's language exposes no parent links on AST nodes (I first tried walking node.parent and confirmed the property is undefined).

Vendor-prefixed keyframes rules are handled by the same regex that rule uses.

Fixes #582

Testing

Three cases added to tests/rules/selector-complexity.test.js:

  • @keyframes fade { from {...} to {...} } with { maxTypes: 0 } — the reported repro.
  • @keyframes slide { 0% {...} 100% {...} } with { maxTypes: 0 } — percentage selectors.
  • @keyframes followed by a .foo rule, and @keyframes followed by div span with { maxTypes: 1 } which must still report — proving the flag is cleared on the way out, not just set.

Verified

  • The two keyframe valid cases fail on main with exactly the reported messages (Should have no errors but had 2: ... Exceeded maximum type selector) and pass with the fix — confirmed by stashing the rule and re-running.
  • Full suite npx mocha "tests/**/*.test.js": 1236 passing, 0 failing (was 1233 before, +3 from this change).
  • npm run build (which also runs the rule-docs regeneration) exits 0.
  • npm run lint (the repo's own eslint) and prettier --check are clean.

Not verified

  • A browser/editor run — no visual change is involved; the rule's behaviour is fully covered by the RuleTester cases.

Docs

Added a short note plus example to docs/rules/selector-complexity.md under the existing maxTypes section. The rule description and options are unchanged.

Summary by CodeRabbit

  • Bug Fixes

    • Keyframe selectors such as from, to, and percentages no longer count toward the type-selector limit. Type selectors outside keyframes continue to be checked as before.
  • Documentation

    • Added an example showing how keyframe selectors interact with the maxTypes setting.

`maxTypes` counted the `from`, `to` and percentage selectors of an
`@keyframes` rule, because css-tree parses them as `TypeSelector` nodes
even though they name no element. A file whose only keyframes therefore
failed with `{ maxTypes: 0 }`:

	4:2  Exceeded maximum type selector. Only 0 allowed.
	8:2  Exceeded maximum type selector. Only 0 allowed.

Track whether the selector sits inside a keyframes rule and skip those,
the same way `no-duplicate-keyframe-selectors` tracks that depth (the
language's AST exposes no parent links).

Fixes eslint#582
@github-project-automation github-project-automation Bot moved this to Needs Triage in Triage Oct 4, 2026
@eslint-github-bot eslint-github-bot Bot added the bug Something isn't working label Oct 4, 2026
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0a07adfb-8a60-45fb-8e5d-29c123e8233e
📥 Commits

Reviewing files that changed from the base of the PR and between 2e80de0 and 1996e31.

📒 Files selected for processing (3)
  • docs/rules/selector-complexity.md
  • src/rules/selector-complexity.js
  • tests/rules/selector-complexity.test.js

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

The selector-complexity rule now excludes type selectors inside standard and vendor-prefixed keyframes. Tests cover keyframe selectors and selectors after keyframes. The rule documentation includes an example.

Changes

Keyframe type-selector counting

Layer / File(s) Summary
Track keyframes and exclude their type selectors
src/rules/selector-complexity.js, tests/rules/selector-complexity.test.js, docs/rules/selector-complexity.md
The rule tracks entry into and exit from standard and vendor-prefixed keyframes, and excludes type selectors inside them. Tests cover keyframe selectors and selectors after keyframes. The documentation includes a maxTypes: 0 example.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: pixel998

Merge Risk: ⚪ Minimal · up to 1996e

The change excludes keyframe step type selectors while continuing to check ordinary selectors afterward. No actionable issue is established, so the PR appears mergeable subject to normal project checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: excluding keyframe selectors from selector-complexity counts.
Linked Issues check ✅ Passed Issue #582 requires keyframe selectors to not count toward maxTypes. The rule tracks entry into and exit from standard and supported vendor-prefixed @keyframes at-rules, then excludes `TypeSelecto…
Out of Scope Changes check ✅ Passed The source change, tests, and documentation all support issue #582. The tests also verify that selectors after a keyframes rule remain subject to maxTypes. No unrelated changes appear in the pull re…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@DMartens

DMartens commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

The referenced issue is neither accepted nor assigned to you.
In the future please follow our contribution guidelines.

@DMartens DMartens closed this Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

Bug: selector-complexity reports keyframe selectors as type selectors

2 participants