-
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Rule: no-id-selector #19
Comments
A CSS equivalent to JavaScript's We couldn't take this approach in Stylelint because the general parser we use is limited to a few node types. We ended up with many separate rules, including The CSSTree parser is far more granular and id selectors are a node type ( {
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "IdSelector",
"message": "Id selectors are not allowed."
},
]
}
} (Mixing AST selectors and CSS selector types could be confusing for people, though.)
A rule to limit specificity would complement the |
Ah interesting, that may be a better way to go than just limited blocking of ID selectors. |
Looking into this right now. Would it make sense to ever set a minimum specificity? For instance, would a rule like this have any value?
|
Rough draft: #24 |
As a +1 to a restricted syntax rule, I'd also want to ban some tag selectors. These selectors tend to be slow with common elements: .foo > div {} /* must evaluate every div */ or they get abused by developers instead of using classes dialog > div > span:nth-child(1) > img {} |
I agree. Classes are always better than tag selectors and less prone to breakage |
Not everyone would use a For example, with the @scope (.component) to (.content) {
a {
color: red;
}
} Or within the Shadow Dom using (Lit) Web Components: import {LitElement, html, css} from 'lit';
import {customElement} from 'lit/decorators.js';
@customElement('my-element')
export class MyElement extends LitElement {
static styles = css`
p {
color: green;
}
`;
protected render() {
return html`<p>I am green!</p>`;
}
} The nice thing about a
{
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "IdSelector",
"message": "Id selectors are not allowed."
},
{
"selector": "TypeSelector",
"message": "Type selectors are not allowed."
},
{
"selector": "Rule > SelectorList > Selector > Combinator",
"message": "Top-level combinators are not allowed."
},
]
}
} By only disallowing top-level combinators, you'll still be able to use them in powerful pseudo-classes like .component {
&:hover {}
}
.child {
&:has(+ .alt) {}
} While disallowing things like: #id {
& > div {
& > div {}
}
} A |
It turns out that the core You can disallow id and type selectors with: import css from "@eslint/css";
export default [
{
files: ["**/*.css"],
language: "css/css",
...css.configs.recommended,
},
{
rules: {
"no-restricted-syntax": [
"error",
{
selector: "IdSelector",
message: "Id selectors are not allowed.",
},
{
selector: "TypeSelector",
message: "Type selectors are not allowed.",
},
],
},
},
]; |
Thinking out loud: maybe what we're really after is a rule that limits the complexity of selectors? If that was the original intent of We could have options for:
Would that make sense? |
Selector complexity in CSS is an odd one because it's:
It seems that the way people use selectors is a broad spectrum. On one side, there are people who:
People at the other end lean into all the selector features. For example, using /* selecting cards that don't have an `img` within */
.card:not(:has(img)) {}
/* selecting boxes that have 3 or more items */
.box:has(.item:nth-last-child(n + 3)) {}
/* selecting boxes that preceded a circle */
.box:has(~ .circle) {} Or, using /* this */
header :is(h1, h2) a {}
/* instead of this */
header h1 a,
header h2 a {} Or, using type selectors within @scope (.component) to (.content) {
a {
color: red;
}
} And then there's everyone in between those ends of the spectrum. Realising that there isn't a one-size-fits-all when it comes to selector use, we added a bunch of rules to Stylelint that people can use to enforce their conventions based on their ideas of complexity and consistency. They can use these rules to limit the:
And a rule to disallow qualifying, and a general one to disallow patterns in selectors. We also added Some may see complexity as the number of compound selectors or combinators, whereas for someone else, it may be the number of different types of selectors used (id, class, universal and so on). It'd be great to accommodate both with this rule. Rather than single out id and type selectors and the |
Yes, that was actually my intent. I just included some examples off the top of my head in my previous comment. It seems like a rule that allows everything to start and you have to configure it to disallow something might make sense? So maybe you'd have a "max" option for each part of a selector (i.e., |
Rule details
Flag any CSS selector that uses the ID selector
What type of rule is this?
Warns about a potential problem
Example code
The
#id
selector has very high specificity and doesn't always play well with other rules. An alternative is to use a.class
selector instead.When using a component-based UI framework, id selectors are often not very useful. You can hardcode an id into a component, but this makes the component non-reusable. The framework-generated unique ids cannot be referenced in CSS. Therefore, using id selectors in these cases is likely a mistake.
Participation
Additional comments
From MDN:
The text was updated successfully, but these errors were encountered: