Stylelint Plugin
A Stylelint plugin that validates SpiraCSS design rules in SCSS files.
Designed to be used with the SpiraCSS Design Principles.
Install
Stylelint v16 or later is required. Node.js >= 20 is required.
yarn add -D @spiracss/stylelint-plugin stylelint stylelint-scss postcss-scssnpm install -D @spiracss/stylelint-plugin stylelint stylelint-scss postcss-scssRules
| Rule | Description |
|---|---|
spiracss/class-structure | Naming, parent-child structure, section structure |
spiracss/property-placement | Property placement (container / item / internal) |
spiracss/page-layer | Page entry SCSS boundaries and component links |
spiracss/interaction-scope | Interaction section placement and structure |
spiracss/interaction-properties | Transition / animation usage inside interaction |
spiracss/keyframes-naming | @keyframes placement and naming |
spiracss/pseudo-nesting | Pseudo-class / pseudo-element nesting |
spiracss/rel-comments | @rel comments for parent-child links |
For rule details (OK / NG examples), see the rule pages.
Configuration
This plugin reads spiracss.config.js at the project root.
Use createRules() to generate rule settings from the config.
Choose one configuration style depending on your project module system: CommonJS or ESM.
CommonJS (recommended)
const spiracss = require('@spiracss/stylelint-plugin')const plugin = spiracss.default ?? spiracssconst { createRules } = spiracss
module.exports = { plugins: [plugin, 'stylelint-scss'], customSyntax: 'postcss-scss', // Exclude shared partials; keep shared keyframes linted. ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'], rules: { ...createRules('./spiracss.config.js'), 'scss/at-rule-no-unknown': true }}ESM projects
If package.json has "type": "module", use export default.
Passing config object directly
import spiracssPlugin, { createRules } from '@spiracss/stylelint-plugin'import spiracssConfig from './spiracss.config.js'
export default { plugins: [spiracssPlugin, 'stylelint-scss'], customSyntax: 'postcss-scss', // Exclude shared partials; keep shared keyframes linted. ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'], rules: { ...createRules(spiracssConfig), 'scss/at-rule-no-unknown': true }}Path-based loading
If you need path-based loading in ESM, use createRulesAsync().
import spiracssPlugin, { createRulesAsync } from '@spiracss/stylelint-plugin'
const rules = await createRulesAsync('./spiracss.config.js')
export default { plugins: [spiracssPlugin, 'stylelint-scss'], customSyntax: 'postcss-scss', // Exclude shared partials; keep shared keyframes linted. ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'], rules: { ...rules, 'scss/at-rule-no-unknown': true }}Note: aliasRoots is required when using createRules() or createRulesAsync().
Disabling rules
There are two ways to disable or relax rules:
- Stylelint config: set a rule to
null(always works).
module.exports = { rules: { ...createRules('./spiracss.config.js'), 'spiracss/rel-comments': null // disable this rule }}spiracss.config.js: setstylelint.<rule>.enabled = falseor adjust rule options (only when usingcreateRules()/createRulesAsync()).
export default { stylelint: { keyframes: { enabled: false }, pseudo: { enabled: false }, rel: { requireChild: false } }}For detailed options, see Configuration Options.
Limitations
- Validates structural elements (class names, selector structure,
@relcomments) - Cannot automatically judge design decisions (Element chain intent, data/state validity)
- Supplement with design reviews or code reviews
Optional baseline (recommended)
Recommended setup: stylelint-config-standard-scss + stylelint-config-recess-order.
The recommended config for that setup is documented in Tips.