selector-complexity
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 }:
#foo #bar {
}
#foo > #bar {
}
Examples of correct code with { maxIds: 1 }:
#foo {
}
#foo,
#bar {
}
#foo:not(#bar) {
}
maxClasses
Examples of incorrect code with { maxClasses: 2 }:
.foo .bar .baz {
}
.foo > .bar > .baz {
}
a.foo a.bar .baz {
}
Examples of correct code with { maxClasses: 2 }:
.foo .bar {
}
.foo .bar,
.baz {
}
a.foo a.bar {
}
maxTypes
Examples of incorrect code with { maxTypes: 2 }:
ul li a {
}
div.foo p a {
}
Examples of correct code with { maxTypes: 2 }:
li a {
}
li.foo a {
}
button img:not(img.foo) {
}
maxAttributes
Examples of incorrect code with { maxAttributes: 1 }:
[name="foo"][type="text"] {
}
input:not([name="bar"][disabled]) {
}
Examples of correct code with { maxAttributes: 1 }:
[name="foo"] {
}
[type="number"] {
}
maxPseudoClasses
Examples of incorrect code with { maxPseudoClasses: 1 }:
button:hover + a:visited {
}
.foo:first-child:hover {
}
Examples of correct code with { maxPseudoClasses: 1 }:
button:hover + a {
}
li:nth-child(2) a {
}
maxUniversals
Examples of incorrect code with { maxUniversals: 1 }:
* * {
}
Examples of correct code with { maxUniversals: 1 }:
* {
}
maxCompounds
Examples of incorrect code with { maxCompounds: 2 }:
div p.foo span {
}
.foo #bar > a {
}
Examples of correct code with { maxCompounds: 2 }:
p.foo span {
}
#bar a,
button {
}
maxCombinators
Examples of incorrect code with { maxCombinators: 1 }:
.foo > .bar > .baz {
}
.foo + .bar > a {
}
Examples of correct code with { maxCombinators: 1 }:
.foo + .bar {
}
.foo ~ p {
}
disallowCombinators
Examples of incorrect code with { disallowCombinators: [">"] }:
.foo > .bar {
}
.foo + .bar > a {
}
Examples of correct code with { disallowCombinators: [">"] }:
.foo + .bar {
}
.foo ~ p {
}
disallowPseudoClasses
Examples of incorrect code with { disallowPseudoClasses: ["hover"] }:
button:hover {
}
a:not(.foo):hover {
}
Examples of correct code with { disallowPseudoClasses: ["hover"] }:
ul li:nth-child(2) {
}
a:not(.foo) {
}
disallowPseudoElements
Examples of incorrect code with { disallowPseudoElements: ["marker"] }:
li::marker {
}
Examples of correct code with { disallowPseudoElements: ["marker"] }:
input::placeholder {
}
disallowAttributes
Examples of incorrect code with { disallowAttributes: ["class", "alt"] }:
[class*="foo"] {
}
img[alt="foo"] {
}
Examples of correct code with { disallowAttributes: ["class", "alt"] }:
input[type="text"] {
}
img[src$=".foo"] {
}
disallowAttributeMatchers
Examples of incorrect code with { disallowAttributeMatchers: ["*=", "^="] }:
[class*="foo"] {
}
img[alt^="foo"] {
}
Examples of correct code with { 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