selector-complexity
October 8, 2025 ยท View on GitHub
Limit and disallow the CSS selectors.
Background
The CSS selectors are used to target HTML elements so that styles can be applied to them. Selectors can target HTML element tags, IDs, classes, or attributes applied to elements. Selectors can use simple syntax, such as targeting only IDs, classes, or HTML tags, or more complex syntax by combining classes, IDs, attributes, pseudo-classes, pseudo-elements and combinators to match specific elements or groups of elements.
It is a good practice to refrain from using complex selectors to improve maintainability and readability of code, reduce specificity issues, enhance performance, prevent bugs etc.
Rule Details
This rule limits the use of descendant selectors and disallows certain selectors or combinators to prevent overly complex CSS selectors.
Options
This rule accepts an option object with the following properties:
maxIds(default:Infinity) - Specify the number ofIDs can be used in a selector.maxClasses(default: -Infinity) - Specify the number ofclasses can be used in a selector.maxTypes(default:Infinity) - Specify the number oftypes can be used in a selector.maxAttributes(default:Infinity) - Specify the number ofattributes can be used in a selector.maxPseudoClasses(default:Infinity) - Specify the number ofpseudo-classes can be used in a selector.maxUniversals(default:Infinity) - Specify the number ofuniversals can be used in a selector.maxCompounds(default:Infinity) - Specify the number ofcompounds can be used in a selector.maxCombinators(default:Infinity) - Specify the number ofcombinators can be used in a selector.disallowCombinators(default:[]) - Specify an array ofcombinators that are not allowed to be used.disallowPseudoClasses(default:[]) - Specify an array ofpseudo-classes that are not allowed to be used.disallowPseudoElements(default:[]) - Specify an array ofpseudo-elements that are not allowed to be used.disallowAttributes(default:[]) - Specify an array ofattributes that are not allowed to be used.disallowAttributeMatchers(default:[]) - Specify an array ofattribute-matcherss oroperators that are not allowed to be used.
maxIds
Examples of incorrect code with { maxIds: 1 }:
/* eslint css/selector-complexity: ["error", { maxIds: 1 }] */
#foo #bar {
}
#foo > #bar {
}
Examples of correct code with { maxIds: 1 }:
/* eslint css/selector-complexity: ["error", { maxIds: 1 }] */
#foo {
}
#foo,
#bar {
}
#foo:not(#bar) {
}
maxClasses
Examples of incorrect code with { maxClasses: 2 }:
/* eslint css/selector-complexity: ["error", { maxClasses: 2 }] */
.foo .bar .baz {
}
.foo > .bar > .baz {
}
a.foo a.bar .baz {
}
Examples of correct code with { maxClasses: 2 }:
/* eslint css/selector-complexity: ["error", { maxClasses: 2 }] */
.foo .bar {
}
.foo .bar,
.baz {
}
a.foo a.bar {
}
maxTypes
Examples of incorrect code with { maxTypes: 2 }:
/* eslint css/selector-complexity: ["error", { maxTypes: 2 }] */
ul li a {
}
div.foo p a {
}
Examples of correct code with { maxTypes: 2 }:
/* eslint css/selector-complexity: ["error", { maxTypes: 2 }] */
li a {
}
li.foo a {
}
button img:not(img.foo) {
}
maxAttributes
Examples of incorrect code with { maxAttributes: 1 }:
/* eslint css/selector-complexity: ["error", { maxAttributes: 1 }] */
[name="foo"][type="text"] {
}
input:not([name="bar"][disabled]) {
}
Examples of correct code with { maxAttributes: 1 }:
/* eslint css/selector-complexity: ["error", { maxAttributes: 1 }] */
[name="foo"] {
}
[type="number"] {
}
maxPseudoClasses
Examples of incorrect code with { maxPseudoClasses: 1 }:
/* eslint css/selector-complexity: ["error", { maxPseudoClasses: 1 }] */
button:hover + a:visited {
}
.foo:first-child:hover {
}
Examples of correct code with { maxPseudoClasses: 1 }:
/* eslint css/selector-complexity: ["error", { maxPseudoClasses: 1 }] */
button:hover + a {
}
li:nth-child(2) a {
}
maxUniversals
Examples of incorrect code with { maxUniversals: 1 }:
/* eslint css/selector-complexity: ["error", { maxUniversals: 1 }] */
* * {
}
Examples of correct code with { maxUniversals: 1 }:
/* eslint css/selector-complexity: ["error", { maxUniversals: 1 }] */
* {
}
maxCompounds
Examples of incorrect code with { maxCompounds: 2 }:
/* eslint css/selector-complexity: ["error", { maxCompounds: 2 }] */
div p.foo span {
}
.foo #bar > a {
}
Examples of correct code with { maxCompounds: 2 }:
/* eslint css/selector-complexity: ["error", { maxCompounds: 2 }] */
p.foo span {
}
#bar a,
button {
}
maxCombinators
Examples of incorrect code with { maxCombinators: 1 }:
/* eslint css/selector-complexity: ["error", { maxCombinators: 1 }] */
.foo > .bar > .baz {
}
.foo + .bar > a {
}
Examples of correct code with { maxCombinators: 1 }:
/* eslint css/selector-complexity: ["error", { maxCombinators: 1 }] */
.foo + .bar {
}
.foo ~ p {
}
disallowCombinators
Examples of incorrect code with { disallowCombinators: [">"] }:
/* eslint css/selector-complexity: ["error", { disallowCombinators: [">"] }] */
.foo > .bar {
}
.foo + .bar > a {
}
Examples of correct code with { disallowCombinators: [">"] }:
/* eslint css/selector-complexity: ["error", { disallowCombinators: [">"] }] */
.foo + .bar {
}
.foo ~ p {
}
disallowPseudoClasses
Examples of incorrect code with { disallowPseudoClasses: ["hover"] }:
/* eslint css/selector-complexity: ["error", { disallowPseudoClasses: ["hover"] }] */
button:hover {
}
a:not(.foo):hover {
}
Examples of correct code with { disallowPseudoClasses: ["hover"] }:
/* eslint css/selector-complexity: ["error", { disallowPseudoClasses: ["hover"] }] */
ul li:nth-child(2) {
}
a:not(.foo) {
}
disallowPseudoElements
Examples of incorrect code with { disallowPseudoElements: ["marker"] }:
/* eslint css/selector-complexity: ["error", { disallowPseudoElements: ["marker"] }] */
li::marker {
}
Examples of correct code with { disallowPseudoElements: ["marker"] }:
/* eslint css/selector-complexity: ["error", { disallowPseudoElements: ["marker"] }] */
input::placeholder {
}
disallowAttributes
Examples of incorrect code with { disallowAttributes: ["class", "alt"] }:
/* eslint css/selector-complexity: ["error", { disallowAttributes: ["class", "alt"] }] */
[class*="foo"] {
}
img[alt="foo"] {
}
Examples of correct code with { disallowAttributes: ["class", "alt"] }:
/* eslint css/selector-complexity: ["error", { disallowAttributes: ["class", "alt"] }] */
input[type="text"] {
}
img[src$=".foo"] {
}
disallowAttributeMatchers
Examples of incorrect code with { disallowAttributeMatchers: ["*=", "^="] }:
/* eslint css/selector-complexity: ["error", { disallowAttributeMatchers: ["*=", "^="] }] */
[class*="foo"] {
}
img[alt^="foo"] {
}
Examples of correct code with { disallowAttributeMatchers: ["*=", "^="] }:
/* eslint css/selector-complexity: ["error", { disallowAttributeMatchers: ["*=", "^="] }] */
input[class="foo"] {
}
img[alt="foo-bar"] {
}
When Not to Use It
If you aren't concerned with the complexity of the selectors, then you can safely disable this rule.
Prior Art
- selector-max-id
- selector-max-class
- selector-max-type
- selector-max-attribute
- selector-max-pseudo-class
- selector-max-universal
- selector-max-compound-selectors
- selector-max-combinators
- selector-combinator-disallowed-list
- selector-pseudo-class-disallowed-list
- selector-pseudo-element-disallowed-list
- selector-attribute-name-disallowed-list
- selector-attribute-operator-disallowed-list