You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
π Audit: The audit slugs are directly derived from the configured rules in the .stylelintrc.next.json
π Group: The groups are automatically detected by the configured severity (warning or error). A recommended set of rules provided by code-pushup statically pre-configures the core rules related to suggestions with warning and the ones for problems with error.
π Category: The categories are same as for eslint code-style and bug-prevention.
Details maintenance
π Issues: The details contain only issues. Every rule has lint issues that are directly mapped to the audits.
π Table: N/A
Runner maintenance
To get full access to configuration parsing we have to path the stylelint package in a postinstall hook.
This keeps the runner logic easy to maintain.
Acceptance criteria
supports all config formats (js, json)
rule name maps directly to audit name
audits are grouped into errors and warnings
the .stylelint.json controls the listed audits
a recommended set of stylelint rules is provided by code-pushup
Stylelint vs Prettier
Pretties and StyleLint don't have conflicting rules since version v15.
Alternatives
in the past there was stylelint-prettier that you could use to report Prettier issues as Stylelint warnings or errors. This is deprecated now as the conflicting rules are now disable by default.
Stylelint vs ESLint CSS Plugin
Stylelint and the ESLint CSS plugin are powerful tools for linting CSS, each tailored to specific workflows. Stylelint offers extensive rules for standalone styles and preprocessors, while ESLint excels in CSS-in-JS scenarios. Both tools provide autofix support.
Stylelint provides a significantly broader rule set, with 134 core rules, compared to the 4 rules offered by the ESLint CSS plugin. Below are rule equivalents:
Stylelint focuses on pure CSS, preprocessors (SCSS, LESS), and modern CSS standards, making it suitable for standalone workflows. The ESLint CSS plugin targets embedded CSS within JavaScript/TypeScript, particularly for CSS-in-JS frameworks like styled-components and Emotion.
Stylelint has more comprehensive CSS linting for standalone styles and preprocessors, with robust autofix capabilities for common styling issues. In contrast, ESLint with the CSS plugin is optimized for JavaScript-focused workflows, particularly CSS-in-JS, but offers limited autofix functionality.
Implementation details
π Key Note: The biggest flaw of the current PoC is the postinstall hook
there is a overlap in formatting rules with prettier that needs to be considered in the styllintpreset
A draft implementation of the plugin can be found here: TODO.
stylelint-config provided under @code-pushup/stylelint-config
Some configurations extend others, as shown in the diagram below. For example, extending the stylelint-config implicitly includes the stylelint-config-standard and stylelint-config-recommended configurations.
graph BT;
A[stylelint-config-standard] --> B[stylelint-config-recommended];
C[stylelint-config Custom] --> A;
%% Add links as notes
click A href "https://github.com/stylelint/stylelint-config-standard/blob/main/index.js" "stylelint-config-standard on GitHub"
click B href "https://github.com/stylelint/stylelint-config-recommended/blob/main/index.js" "stylelint-config-recommended on GitHub"
Loading
Configured rules and considerations
stylelint-config.js
/** * Standard Stylelint configuration that extends the stylelint-config-standard. * "Avoid errors" rules are set to "error" severity. * "Enforce conventions" rules are set to "warning" severity. */conststylelintConfig={extends: ['stylelint-config-standard'],rules: {// = Avoid errors - set as errors// == Descending'no-descending-specificity': [true,{severity: 'error'}],// == Duplicate'declaration-block-no-duplicate-custom-properties': [true,{severity: 'error'}],'declaration-block-no-duplicate-properties': [true,{severity: 'error',ignore: ['consecutive-duplicates-with-different-syntaxes']},],'font-family-no-duplicate-names': [true,{severity: 'error'}],'keyframe-block-no-duplicate-selectors': [true,{severity: 'error'}],'no-duplicate-at-import-rules': [true,{severity: 'error'}],'no-duplicate-selectors': [true,{severity: 'error'}],// == Empty'block-no-empty': [true,{severity: 'error'}],'comment-no-empty': [true,{severity: 'error'}],'no-empty-source': [true,{severity: 'error'}],// == Invalid'color-no-invalid-hex': [true,{severity: 'error'}],'function-calc-no-unspaced-operator': [true,{severity: 'error'}],'keyframe-declaration-no-important': [true,{severity: 'error'}],'media-query-no-invalid': [true,{severity: 'error'}],'named-grid-areas-no-invalid': [true,{severity: 'error'}],'no-invalid-double-slash-comments': [true,{severity: 'error'}],'no-invalid-position-at-import-rule': [true,{severity: 'error'}],'string-no-newline': [true,{severity: 'error'}],// == Irregular'no-irregular-whitespace': [true,{severity: 'error'}],// == Missing'custom-property-no-missing-var-function': [true,{severity: 'error'}],'font-family-no-missing-generic-family-keyword': [true,{severity: 'error'}],// == Non-standard'function-linear-gradient-no-nonstandard-direction': [true,{severity: 'error'}],// == Overrides'declaration-block-no-shorthand-property-overrides': [true,{severity: 'error'}],// == Unmatchable'selector-anb-no-unmatchable': [true,{severity: 'error'}],// == Unknown'annotation-no-unknown': [true,{severity: 'error'}],'at-rule-no-unknown': [true,{severity: 'error'}],'function-no-unknown': [true,{severity: 'error'}],'media-feature-name-no-unknown': [true,{severity: 'error'}],'property-no-unknown': [true,{severity: 'error'}],'selector-pseudo-class-no-unknown': [true,{severity: 'error'}],'selector-type-no-unknown': [true,{severity: 'error'}],'unit-no-unknown': [true,{severity: 'error'}],// == Maintainability Rules// Prevent overly specific selectors// Example: Good: `.class1 .class2`, Bad: `#id.class1 .class2`"selector-max-specificity": ["0,2,0",{severity: "warning"}],// Enforces a maximum specificity of 2 classes, no IDs, and no inline styles.// Encourages maintainable selectors.// Disallow the use of ID selectors// Example: Good: `.button`, Bad: `#button`"selector-max-id": [0,{severity: "warning"}],// Prevents the use of IDs in selectors, as they are too specific and hard to override.// Limit the number of class selectors in a rule// Example: Good: `.btn.primary`, Bad: `.btn.primary.large.rounded`"selector-max-class": [3,{severity: "off"}],// Can help avoid overly complex class chains, but may be unnecessary if specificity is already managed.// Limit the number of pseudo-classes in a selector// Example: Good: `.list-item:hover`, Bad: `.list-item:nth-child(2):hover:active`"selector-max-pseudo-class": [3,{severity: "warning"}],// Allows up to 3 pseudo-classes in a single selector to balance flexibility and simplicity.// Restrict the number of type selectors (e.g., `div`, `span`)// Example: Good: `.header`, Bad: `div.header`"selector-max-type": [1,{severity: "warning"}],// Promotes the use of semantic classes over type selectors for better reusability and maintainability.// Optional: Additional rules for project-specific preferences// Uncomment the following if relevant to your project:/* // Example: Limit the depth of combinators // Good: `.parent > .child`, Bad: `.parent > .child > .grandchild` "selector-max-combinators": [2, { severity: "warning" }], // Example: Restrict the number of universal selectors in a rule // Good: `* { margin: 0; }`, Bad: `.wrapper * .content { padding: 0; }` "selector-max-universal": [1, { severity: "warning" }], */// = Enforce conventions - set as warnings// == Allowed, disallowed & required'at-rule-no-vendor-prefix': [true,{severity: 'warning'}],'length-zero-no-unit': [true,{severity: 'warning'}],'media-feature-name-no-vendor-prefix': [true,{severity: 'warning'}],'property-no-vendor-prefix': [true,{severity: 'warning'}],'value-no-vendor-prefix': [true,{severity: 'warning'}],// == Case'function-name-case': ['lower',{severity: 'warning'}],'selector-type-case': ['lower',{severity: 'warning'}],'value-keyword-case': ['lower',{severity: 'warning'}],// == Empty lines'at-rule-empty-line-before': ['always',{severity: 'warning'}],'comment-empty-line-before': ['always',{severity: 'warning'}],'custom-property-empty-line-before': ['always',{severity: 'warning'}],'declaration-empty-line-before': ['always',{severity: 'warning'}],'rule-empty-line-before': ['always',{severity: 'warning'}],// == Max & min'declaration-block-single-line-max-declarations': [1,{severity: 'warning'}],'number-max-precision': [4,{severity: 'warning'}],// == Notation'alpha-value-notation': ['percentage',{severity: 'warning'}],'color-function-notation': ['modern',{severity: 'warning'}],'color-hex-length': ['short',{severity: 'warning'}],'hue-degree-notation': ['angle',{severity: 'warning'}],'import-notation': ['string',{severity: 'warning'}],'keyframe-selector-notation': ['percentage',{severity: 'warning'}],'lightness-notation': ['percentage',{severity: 'warning'}],'media-feature-range-notation': ['context',{severity: 'warning'}],'selector-not-notation': ['complex',{severity: 'warning'}],'selector-pseudo-element-colon-notation': ['double',{severity: 'warning'}],// == Pattern'custom-media-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',{severity: 'warning'}],'custom-property-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',{severity: 'warning'}],'keyframes-name-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',{severity: 'warning'}],'selector-class-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',{severity: 'warning'}],'selector-id-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',{severity: 'warning'}],// == Quotes'font-family-name-quotes': ['always-where-recommended',{severity: 'warning'}],'function-url-quotes': ['always',{severity: 'warning'}],'selector-attribute-quotes': ['always',{severity: 'warning'}],// == Redundant'declaration-block-no-redundant-longhand-properties': [true,{severity: 'warning'}],'shorthand-property-no-redundant-values': [true,{severity: 'warning'}],// == Whitespace inside'comment-whitespace-inside': ['always',{severity: 'warning'}],},};exportdefaultstylelintConfig;
StyleLint Plugin
Quality standards & Incremental Migration for CSS Styles
Seamlessly improve your codebase, standardise code style, avoid missconfiguration or errors.
π§ͺ Reference PR
π #??? β StyleLint Plugin PoC Implementation
Metric
CSS code quality based on StyleLint.
48
48 errors
0
1
) or failed (0
).User story
As a developer I want to be able to incrementally migrate to a better CSS code quality and track it over time.
Setup and Requirements
π¦ Package Dependencies
π Configuration Files
.stylelintrc.json
β Standard configuration file..stylelintrc.next.json
β Migration-specific configuration.Audit, groups and category maintenance
.stylelintrc.next.json
warning
orerror
). A recommended set of rules provided by code-pushup statically pre-configures the core rules related tosuggestions
withwarning
and the ones forproblems
witherror
.code-style
andbug-prevention
.Details maintenance
Runner maintenance
To get full access to configuration parsing we have to path the
stylelint
package in apostinstall
hook.This keeps the runner logic easy to maintain.
Acceptance criteria
js
,json
)errors
andwarnings
.stylelint.json
controls the listed auditsstylelint
rules is provided bycode-pushup
Stylelint vs Prettier
Pretties and StyleLint don't have conflicting rules since version v15.
Alternatives
stylelint-prettier
that you could use to report Prettier issues as Stylelint warnings or errors. This is deprecated now as the conflicting rules are now disable by default.Stylelint vs ESLint CSS Plugin
Stylelint and the ESLint CSS plugin are powerful tools for linting CSS, each tailored to specific workflows. Stylelint offers extensive rules for standalone styles and preprocessors, while ESLint excels in CSS-in-JS scenarios. Both tools provide autofix support.
Rule Definition and Severity Levels
off
error
(iftrue
)off
,warn
,error
off
,warning
,error
on
.true
.ESLint
StyleLint
Rules
Stylelint provides a significantly broader rule set, with 134 core rules, compared to the 4 rules offered by the ESLint CSS plugin. Below are rule equivalents:
no-duplicate-properties
declaration-block-no-duplicate-properties
no-invalid-hex
color-no-invalid-hex
property-no-unknown
property-no-unknown
selector-type-no-unknown
selector-type-no-unknown
CSS Formats
Stylelint focuses on pure CSS, preprocessors (SCSS, LESS), and modern CSS standards, making it suitable for standalone workflows. The ESLint CSS plugin targets embedded CSS within JavaScript/TypeScript, particularly for CSS-in-JS frameworks like styled-components and Emotion.
Comparison conclusion
Stylelint has more comprehensive CSS linting for standalone styles and preprocessors, with robust autofix capabilities for common styling issues. In contrast, ESLint with the CSS plugin is optimized for JavaScript-focused workflows, particularly CSS-in-JS, but offers limited autofix functionality.
Implementation details
A draft implementation of the plugin can be found here: TODO.
stylelint-config
provided under@code-pushup/stylelint-config
Some configurations extend others, as shown in the diagram below. For example, extending the
stylelint-config
implicitly includes thestylelint-config-standard
andstylelint-config-recommended
configurations.Configured rules and considerations
stylelint-config.js
Setup
To use the default configuration:
@code-pushup/stylelint-config
in your.stylelintrc.next.js
file:The plugin needs the following options:
Gather Confiig
Problem 1:
The current state on
stylelint
does not export a way to load the configiratoin from a.stylelintrc.(js|json)
file and consider extends properties.Solution:
Setup a
postinstall
hook that exports the code.Generating StyleLint Warnings
The
stylelint.lint
function produces a couple of interesting information:Relevant result output
invalidOptionWarnings
Configuration
deprecations
Warns about deprecated rules to ensure updated configurations.Configuration
warnings
error
-level issues (indicated byerrored
) andwarning
severities.Code Style
,Bug Prevention
errored
Boolean indicating whether anyerror
-level issues exist in thewarnings
array.N/AparseErrors
warnings
and not associated with any rules.Bug Prevention
ignoredFiles
Represents files skipped during linting due to.stylelintignore
orignoreFiles
configuration.Ignored Issues
_postcssResult
Internal Stylelint processing data (_postcssResult
), not directly tied to user-facing results.N/A
warnings
.Resources
The text was updated successfully, but these errors were encountered: